Fix Batch Cred Deletes
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / batch / helpers / Cred.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 IBM.
7  * ===========================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END====================================================
20  *
21  */
22
23 package org.onap.aaf.auth.batch.helpers;
24
25 import java.util.ArrayList;
26 import java.util.Date;
27 import java.util.GregorianCalendar;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Set;
32 import java.util.TreeMap;
33
34 import org.onap.aaf.auth.dao.cass.CredDAO;
35 import org.onap.aaf.auth.dao.hl.Question;
36 import org.onap.aaf.cadi.util.CSV;
37 import org.onap.aaf.misc.env.Env;
38 import org.onap.aaf.misc.env.TimeTaken;
39 import org.onap.aaf.misc.env.Trans;
40 import org.onap.aaf.misc.env.util.Chrono;
41
42 import com.datastax.driver.core.ResultSet;
43 import com.datastax.driver.core.Row;
44 import com.datastax.driver.core.Session;
45 import com.datastax.driver.core.SimpleStatement;
46 import com.datastax.driver.core.Statement;
47
48 public class Cred  {
49     public static final TreeMap<String,Cred> data = new TreeMap<>();
50     public static final TreeMap<String,List<Cred>> byNS = new TreeMap<>();
51
52     public final String id;
53     public final List<Instance> instances;
54     public final String ns;
55
56     public Cred(String id) {
57         this.id = id;
58         instances = new ArrayList<>();
59         ns=Question.domain2ns(id);
60     }
61
62     public static class Instance {
63         public final int type;
64         public final Date expires,written;
65         public final Integer other;
66         public final String tag;
67         public List<Note> notes;
68
69
70         public Instance(int type, Date expires, Integer other, long written, String tag) {
71             this.type = type;
72             this.expires = expires;
73             this.other = other;
74             this.written = new Date(written);
75             this.tag = tag;
76         }
77
78         /**
79          * Usually returns Null...
80          * @return
81          */
82         public List<Note> notes() {
83             return notes;
84         }
85
86         public void addNote(int level, String note) {
87             if(notes==null) {
88                 notes=new ArrayList<>();
89             }
90             notes.add(new Note(level,note));
91         }
92
93         public String toString() {
94             return expires.toString() + ": " + type + ' ' + tag;
95         }
96     }
97
98     public static class Note {
99         public final int level;
100         public final String note;
101
102         public Note(int level, String note) {
103             this.level = level;
104             this.note = note;
105         }
106     }
107     public Date last(final int ... types) {
108         Date last = null;
109         for (Instance i : instances) {
110             if (types.length>0) { // filter by types, if requested
111                 boolean quit = true;
112                 for (int t : types) {
113                     if (t==i.type) {
114                         quit=false;
115                         break;
116                     }
117                 }
118                 if (quit) {
119                     continue;
120                 }
121             }
122             if (last==null || i.expires.after(last)) {
123                 last = i.expires;
124             }
125         }
126         return last;
127     }
128
129
130     public Set<Integer> types() {
131         Set<Integer> types = new HashSet<>();
132         for (Instance i : instances) {
133             types.add(i.type);
134         }
135         return types;
136     }
137
138     public static void load(Trans trans, Session session, int ... types ) {
139         load(trans, session,"select id, type, expires, other, writetime(cred), tag from authz.cred;",types);
140     }
141
142     public static void loadOneNS(Trans trans, Session session, String ns,int ... types ) {
143         load(trans, session,"select id, type, expires, other, writetime(cred), tag from authz.cred WHERE ns='" + ns + "';", types);
144     }
145
146     private static void load(Trans trans, Session session, String query, int ...types) {
147
148         trans.info().log( "query: " + query );
149         TimeTaken tt = trans.start("Read Creds", Env.REMOTE);
150
151         ResultSet results;
152         try {
153             Statement stmt = new SimpleStatement( query );
154             results = session.execute(stmt);
155         } finally {
156             tt.done();
157         }
158         int count = 0;
159         try {
160             Iterator<Row> iter = results.iterator();
161             Row row;
162             tt = trans.start("Load Credentials", Env.SUB);
163             try {
164                 while (iter.hasNext()) {
165                     ++count;
166                     row = iter.next();
167                     int type = row.getInt(1);
168                     if (types.length>0) { // filter by types, if requested
169                         boolean hastype = false;
170                         for (int t : types) {
171                             if (t==type) {
172                                 hastype=true;
173                                 break;
174                             }
175                         }
176                         if (!hastype) {
177                             continue;
178                         }
179                     }
180                     add(row.getString(0), row.getInt(1),row.getTimestamp(2),row.getInt(3),row.getLong(4),
181                             row.getString(5));
182                 }
183             } finally {
184                 tt.done();
185             }
186         } finally {
187             trans.info().log("Found",count,"creds");
188         }
189     }
190
191     public static void add(
192             final String id,
193             final int type,
194             final Date timestamp,
195             final int other,
196             final long written,
197             final String tag
198             ) {
199         Cred cred = data.get(id);
200         if (cred==null) {
201             cred = new Cred(id);
202             data.put(id, cred);
203         }
204         cred.instances.add(new Instance(type, timestamp, other, written/1000,tag));
205
206         List<Cred> lscd = byNS.get(cred.ns);
207         if (lscd==null) {
208             lscd=new ArrayList<>();
209             byNS.put(cred.ns,lscd);
210         }
211         boolean found = false;
212         for (Cred c : lscd) {
213             if (c.id.equals(cred.id)) {
214                 found=true;
215                 break;
216             }
217         }
218         if (!found) {
219             lscd.add(cred);
220         }
221     }
222
223
224     /**
225      * Count entries in Cred data.
226      * Note, as opposed to other methods, need to load the whole cred table for the Types.
227      * @param numbuckets
228      * @return
229      */
230     public static CredCount count(int numbuckets) {
231         CredCount cc = new CredCount(numbuckets);
232         for (Cred c : data.values()) {
233             for (Instance ci : c.instances) {
234                 cc.inc(ci.type,ci.written, ci.expires);
235             }
236         }
237         return cc;
238     }
239
240     public static class CredCount {
241         public int raw[];
242         public int basic_auth[];
243         public int basic_auth_256[];
244         public int cert[];
245         public int x509Added[];
246         public int x509Expired[];
247         public Date dates[];
248
249         public CredCount(int numbuckets) {
250             raw = new int[numbuckets];
251             basic_auth = new int[numbuckets];
252             basic_auth_256 = new int[numbuckets];
253             cert = new int[numbuckets];
254             x509Added = new int[numbuckets];
255             x509Expired = new int[numbuckets];
256             dates = new Date[numbuckets];
257             GregorianCalendar gc = new GregorianCalendar();
258             dates[0]=gc.getTime(); // now
259             gc.set(GregorianCalendar.DAY_OF_MONTH, 1);
260             gc.set(GregorianCalendar.HOUR, 0);
261             gc.set(GregorianCalendar.MINUTE, 0);
262             gc.set(GregorianCalendar.SECOND,0);
263             gc.set(GregorianCalendar.MILLISECOND,0);
264             gc.add(GregorianCalendar.MILLISECOND, -1); // last milli of month
265             for (int i = 1; i < numbuckets; ++i) {
266                 dates[i] = gc.getTime();
267                 gc.add(GregorianCalendar.MONTH, -1);
268             }
269
270         }
271
272         public void inc(int type, Date start, Date expires) {
273             for (int i = 0; i < dates.length - 1; ++i) {
274                 if (start.before(dates[i])) {
275                     if ((type == CredDAO.CERT_SHA256_RSA)&&(start.after(dates[i + 1]))) {
276                             ++x509Added[i];
277                          }
278                     if (expires.after(dates[i])) {
279                         switch(type) {
280                             case CredDAO.RAW:
281                                 ++raw[i];
282                                 break;
283                             case CredDAO.BASIC_AUTH:
284                                 ++basic_auth[i];
285                                 break;
286                             case CredDAO.BASIC_AUTH_SHA256:
287                                 ++basic_auth_256[i];
288                                 break;
289                             case CredDAO.CERT_SHA256_RSA:
290                                 ++cert[i];
291                                 break;
292                         }
293                     }
294                 }
295             }
296         }
297
298         public long authCount(int idx) {
299             return (long)basic_auth[idx] + basic_auth_256[idx];
300         }
301
302         public long x509Count(int idx) {
303             return cert[idx];
304         }
305
306     }
307
308     public void row(final CSV.Writer csvw, final Instance inst) {
309         csvw.row("cred",id,ns,Integer.toString(inst.type),Chrono.dateOnlyStamp(inst.expires),
310                 inst.expires.getTime(),inst.tag);
311     }
312
313     public void row(final CSV.Writer csvw, final Instance inst, final String reason) {
314         csvw.row("cred",id,ns,Integer.toString(inst.type),Chrono.dateOnlyStamp(inst.expires),
315                 inst.expires.getTime(),inst.tag,reason);
316     }
317
318     public static void batchDelete(StringBuilder sb, List<String> row) {
319         long l = Long.parseLong(row.get(5));
320         String date = Chrono.batchFmt.format(new Date(l));
321         sb.append("DELETE from authz.cred WHERE id='");
322         sb.append(row.get(1));
323         sb.append("' AND type=");
324         sb.append(Integer.parseInt(row.get(3)));
325         // Note: We have to work with long, because Expires is part of Key... can't easily do date.
326         sb.append(" AND expires='");
327         sb.append(date);
328         sb.append("';\n");
329
330     }
331
332     public String toString() {
333         StringBuilder sb = new StringBuilder(id);
334         sb.append('[');
335         for (Instance i : instances) {
336             sb.append('{');
337             sb.append(i.type);
338             sb.append(",\"");
339             sb.append(i.expires);
340             sb.append("\"}");
341         }
342         sb.append(']');
343         return sb.toString();
344     }
345
346     /* (non-Javadoc)
347      * @see java.lang.Object#hashCode()
348      */
349     @Override
350     public int hashCode() {
351         return id.hashCode();
352     }
353
354     /* (non-Javadoc)
355      * @see java.lang.Object#equals(java.lang.Object)
356      */
357     @Override
358     public boolean equals(Object obj) {
359         return id.equals(obj);
360     }
361
362
363     public static String histSubject(List<String> row) {
364         return row.get(1);
365     }
366
367
368     public static String histMemo(String fmt, String orgName, List<String> row) {
369         String reason;
370         if(row.size()>5) { // Reason included
371             reason = row.get(5);
372         } else {
373             reason = String.format(fmt, row.get(1),orgName,row.get(4));
374         }
375         return reason;
376     }
377
378
379     public static void clear() {
380         data.clear();
381         byNS.clear();
382     }
383 }