Add AAF in a Nutshell to docs
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / batch / reports / Expiring.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  *
7  * Modifications Copyright (C) 2019 IBM.
8  * ===========================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END====================================================
21  *
22  */
23
24 package org.onap.aaf.auth.batch.reports;
25
26 import java.io.File;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.security.cert.Certificate;
30 import java.security.cert.CertificateException;
31 import java.security.cert.X509Certificate;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.TreeMap;
39 import java.util.UUID;
40
41 import org.onap.aaf.auth.batch.Batch;
42 import org.onap.aaf.auth.batch.helpers.Approval;
43 import org.onap.aaf.auth.batch.helpers.Cred;
44 import org.onap.aaf.auth.batch.helpers.Cred.Instance;
45 import org.onap.aaf.auth.batch.helpers.ExpireRange;
46 import org.onap.aaf.auth.batch.helpers.ExpireRange.Range;
47 import org.onap.aaf.auth.batch.helpers.Future;
48 import org.onap.aaf.auth.batch.helpers.UserRole;
49 import org.onap.aaf.auth.batch.helpers.X509;
50 import org.onap.aaf.auth.dao.cass.CredDAO;
51 import org.onap.aaf.auth.env.AuthzTrans;
52 import org.onap.aaf.auth.org.OrganizationException;
53 import org.onap.aaf.cadi.configure.Factory;
54 import org.onap.aaf.cadi.util.CSV;
55 import org.onap.aaf.misc.env.APIException;
56 import org.onap.aaf.misc.env.Env;
57 import org.onap.aaf.misc.env.TimeTaken;
58 import org.onap.aaf.misc.env.util.Chrono;
59
60
61 public class Expiring extends Batch {
62     
63         private static final String CSV = ".csv";
64         private static final String INFO = "info";
65         private static final String EXPIRED_OWNERS = "ExpiredOwners";
66         private int minOwners;
67         private Map<String, CSV.Writer> writerList;
68         private ExpireRange expireRange;
69         private Date deleteDate;
70         private CSV.Writer deleteCW;
71         
72         public Expiring(AuthzTrans trans) throws APIException, IOException, OrganizationException {
73         super(trans.env());
74         trans.info().log("Starting Connection Process");
75         
76         TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB);
77         try {
78             TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
79             try {
80                 session = cluster.connect();
81             } finally {
82                 tt.done();
83             }
84             
85             // Load Cred.  We don't follow Visitor, because we have to gather up everything into Identity Anyway
86             Cred.load(trans, session);
87
88             minOwners=1;
89
90             // Create Intermediate Output 
91             writerList = new HashMap<>();
92             
93             expireRange = new ExpireRange(trans.env().access());
94             String sdate = Chrono.dateOnlyStamp(expireRange.now);
95             for( List<Range> lr : expireRange.ranges.values()) {
96                 for(Range r : lr ) {
97                         if(writerList.get(r.name())==null) {
98                         File file = new File(logDir(),r.name() + sdate +CSV);
99                         CSV csv = new CSV(env.access(),file);
100                         CSV.Writer cw = csv.writer(false);
101                         cw.row(INFO,r.name(),Chrono.dateOnlyStamp(expireRange.now),r.reportingLevel());
102                         writerList.put(r.name(),cw);
103                         if("Delete".equals(r.name())) {
104                                 deleteDate = r.getEnd();
105                                 deleteCW = cw;
106                         }
107                         trans.init().log("Creating File:",file.getAbsolutePath());
108                         }
109                 }
110             }
111             Approval.load(trans, session, Approval.v2_0_17);
112         } finally {
113             tt0.done();
114         }
115     }
116
117     @Override
118     protected void run(AuthzTrans trans) {
119         
120                 ////////////////////
121                 trans.info().log("Checking for Expired Futures");
122                 Future.load(trans, session, Future.v2_0_17, fut -> {
123                         if(fut.expires().before(expireRange.now)) {
124                                 Future.row(deleteCW,fut);
125                                 List<Approval> appls = Approval.byTicket.get(fut.id());
126                                 if(appls!=null) {
127                                         for(Approval a : appls) {
128                                                 Approval.row(deleteCW, a);
129                                         }
130                                 }
131                         }
132                 });
133                 
134                 try {
135                         File file = new File(logDir(), EXPIRED_OWNERS + Chrono.dateOnlyStamp(expireRange.now) + CSV);
136                         final CSV ownerCSV = new CSV(env.access(),file);
137
138                         Map<String, Set<UserRole>> owners = new TreeMap<String, Set<UserRole>>();
139                         trans.info().log("Process UserRoles");
140                         
141                         /**
142                            Run through User Roles.  
143                            Owners are treated specially in next section.
144                            Regular roles are checked against Date Ranges.  If match Date Range, write out to appropriate file.
145                         */
146                         UserRole.load(trans, session, UserRole.v2_0_11, ur -> {
147                                 // Cannot just delete owners, unless there is at least one left. Process later
148                                 if ("owner".equals(ur.rname())) {
149                                         Set<UserRole> urs = owners.get(ur.role());
150                                         if (urs == null) {
151                                                 urs = new HashSet<UserRole>();
152                                                 owners.put(ur.role(), urs);
153                                         }
154                                         urs.add(ur);
155                                 } else {
156                                         writeAnalysis(trans,ur);
157                                 }
158                         });
159
160                         /**
161                           Now Process Owners, one owner Role at a time, ensuring one is left,
162                           preferably a good one. If so, process the others as normal. 
163                           
164                           Otherwise, write to ExpiredOwners Report
165                         */
166                         if (!owners.values().isEmpty()) {
167                                 // Lazy Create file
168                                 CSV.Writer expOwner = null;
169                                 try {
170                                         for (Set<UserRole> sur : owners.values()) {
171                                                 int goodOwners = 0;
172                                                 for (UserRole ur : sur) {
173                                                         if (ur.expires().after(expireRange.now)) {
174                                                                 ++goodOwners;
175                                                         }
176                                                 }
177
178                                                 for (UserRole ur : sur) {
179                                                         if (goodOwners >= minOwners) {
180                                                                 writeAnalysis(trans, ur);
181                                                         } else {
182                                                                 if (expOwner == null) {
183                                                                         expOwner = ownerCSV.writer();
184                                                                         expOwner.row(INFO,EXPIRED_OWNERS,Chrono.dateOnlyStamp(expireRange.now),2);
185                                                                 }
186                                                                 expOwner.row("owner",ur.role(), ur.user(), Chrono.dateOnlyStamp(ur.expires()));
187                                                         }
188                                                 }
189                                         }
190                                 } finally {
191                                         if(expOwner!=null) {
192                                                 expOwner.close();
193                                         }
194                                 }
195                         }
196                         
197                         /**
198                          * Check for Expired Credentials
199                          * 
200                          * 
201                          */
202                         trans.info().log("Checking for Expired Credentials");                   
203                         for (Cred cred : Cred.data.values()) {
204                         List<Instance> linst = cred.instances;
205                         if(linst!=null) {
206                                 Instance lastBath = null;
207                                 for(Instance inst : linst) {
208                                         // Special Behavior: only eval the LAST Instance
209                                         if (inst.type == CredDAO.BASIC_AUTH || inst.type == CredDAO.BASIC_AUTH_SHA256) {
210                                                 if(deleteDate!=null && inst.expires.before(deleteDate)) {
211                                                         writeAnalysis(trans, cred, inst); // will go to Delete
212                                                 } else if(lastBath==null || lastBath.expires.before(inst.expires)) {
213                                                         lastBath = inst;
214                                                 }
215                                         } else {
216                                                 writeAnalysis(trans, cred, inst);
217                                         }
218                                 }
219                                 if(lastBath!=null) {
220                                         writeAnalysis(trans, cred, lastBath);
221                                 }
222                         }
223                         }
224
225                         ////////////////////
226                         trans.info().log("Checking for Expired X509s");
227                         X509.load(trans, session, x509 -> {
228                                 try {
229                                         for(Certificate cert : Factory.toX509Certificate(x509.x509)) {
230                                                 writeAnalysis(trans, x509, (X509Certificate)cert);
231                                         }
232                                 } catch (CertificateException | IOException e) {
233                                         trans.error().log(e, "Error Decrypting X509");
234                                 }
235
236                         });
237
238                 } catch (FileNotFoundException e) {
239                         trans.info().log(e);
240                 }
241                 
242                 ////////////////////
243                 trans.info().log("Checking for Orphaned Approvals");
244                 Approval.load(trans, session, Approval.v2_0_17, appr -> {
245                         UUID ticket = appr.add.ticket;
246                         if(ticket==null) {
247                                 Approval.row(deleteCW,appr);
248                         }
249                 });
250                 
251
252         }
253     
254  
255         private void writeAnalysis(AuthzTrans trans, UserRole ur) {
256                 Range r = expireRange.getRange("ur", ur.expires());
257                 if(r!=null) {
258                         CSV.Writer cw = writerList.get(r.name());
259                         if(cw!=null) {
260                                 ur.row(cw);
261                         }
262                 }
263         }
264     
265     private void writeAnalysis(AuthzTrans trans, Cred cred, Instance inst) {
266         if(cred!=null && inst!=null) {
267                         Range r = expireRange.getRange("cred", inst.expires);
268                         if(r!=null) {
269                                 CSV.Writer cw = writerList.get(r.name());
270                                 if(cw!=null) {
271                                         cred.row(cw,inst);
272                                 }
273                         }
274         }
275         }
276
277     private void writeAnalysis(AuthzTrans trans, X509 x509, X509Certificate x509Cert) throws IOException {
278                 Range r = expireRange.getRange("x509", x509Cert.getNotAfter());
279                 if(r!=null) {
280                         CSV.Writer cw = writerList.get(r.name());
281                         if(cw!=null) {
282                                 x509.row(cw,x509Cert);
283                         }
284                 }
285         }
286
287     /*
288     private String[] contacts(final AuthzTrans trans, final String ns, final int levels) {
289         List<UserRole> owners = UserRole.getByRole().get(ns+".owner");
290         List<UserRole> current = new ArrayList<>();
291         for(UserRole ur : owners) {
292                 if(expireRange.now.before(ur.expires())) {
293                         current.add(ur);
294                 }
295         }
296         if(current.isEmpty()) {
297                 trans.warn().log(ns,"has no current owners");
298                 current = owners;
299         }
300         
301         List<String> email = new ArrayList<>();
302         for(UserRole ur : current) {
303                 Identity id;
304                 int i=0;
305                 boolean go = true;
306                 try {
307                         id = org.getIdentity(trans, ur.user());
308                         do {
309                                 if(id!=null) {
310                                                 email.add(id.email());
311                                                 if(i<levels) {
312                                                         id = id.responsibleTo();
313                                                 } else {
314                                                         go = false;
315                                                 }
316                                 } else {
317                                         go = false;
318                                 }
319                         } while(go);
320                         } catch (OrganizationException e) {
321                                 trans.error().log(e);
322                         }
323         }
324         
325         return email.toArray(new String[email.size()]);
326     }
327 */
328     
329         @Override
330     protected void _close(AuthzTrans trans) {
331         session.close();
332         for(CSV.Writer cw : writerList.values()) {
333                 cw.close();
334         }
335     }
336
337 }