2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
24 package org.onap.aaf.auth.batch.reports;
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;
38 import java.util.TreeMap;
39 import java.util.UUID;
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;
61 public class Expiring extends Batch {
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;
72 public Expiring(AuthzTrans trans) throws APIException, IOException, OrganizationException {
74 trans.info().log("Starting Connection Process");
76 TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB);
78 TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
80 session = cluster.connect();
85 // Load Cred. We don't follow Visitor, because we have to gather up everything into Identity Anyway
86 Cred.load(trans, session);
90 // Create Intermediate Output
91 writerList = new HashMap<>();
93 expireRange = new ExpireRange(trans.env().access());
94 String sdate = Chrono.dateOnlyStamp(expireRange.now);
95 for( List<Range> lr : expireRange.ranges.values()) {
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();
107 trans.init().log("Creating File:",file.getAbsolutePath());
111 Approval.load(trans, session, Approval.v2_0_17);
118 protected void run(AuthzTrans trans) {
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());
127 for(Approval a : appls) {
128 Approval.row(deleteCW, a);
135 File file = new File(logDir(), EXPIRED_OWNERS + Chrono.dateOnlyStamp(expireRange.now) + CSV);
136 final CSV ownerCSV = new CSV(env.access(),file);
138 Map<String, Set<UserRole>> owners = new TreeMap<String, Set<UserRole>>();
139 trans.info().log("Process UserRoles");
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.
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());
151 urs = new HashSet<UserRole>();
152 owners.put(ur.role(), urs);
156 writeAnalysis(trans,ur);
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.
164 Otherwise, write to ExpiredOwners Report
166 if (!owners.values().isEmpty()) {
168 CSV.Writer expOwner = null;
170 for (Set<UserRole> sur : owners.values()) {
172 for (UserRole ur : sur) {
173 if (ur.expires().after(expireRange.now)) {
178 for (UserRole ur : sur) {
179 if (goodOwners >= minOwners) {
180 writeAnalysis(trans, ur);
182 if (expOwner == null) {
183 expOwner = ownerCSV.writer();
184 expOwner.row(INFO,EXPIRED_OWNERS,Chrono.dateOnlyStamp(expireRange.now),2);
186 expOwner.row("owner",ur.role(), ur.user(), Chrono.dateOnlyStamp(ur.expires()));
198 * Check for Expired Credentials
202 trans.info().log("Checking for Expired Credentials");
203 for (Cred cred : Cred.data.values()) {
204 List<Instance> linst = cred.instances;
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)) {
216 writeAnalysis(trans, cred, inst);
220 writeAnalysis(trans, cred, lastBath);
226 trans.info().log("Checking for Expired X509s");
227 X509.load(trans, session, x509 -> {
229 for(Certificate cert : Factory.toX509Certificate(x509.x509)) {
230 writeAnalysis(trans, x509, (X509Certificate)cert);
232 } catch (CertificateException | IOException e) {
233 trans.error().log(e, "Error Decrypting X509");
238 } catch (FileNotFoundException e) {
243 trans.info().log("Checking for Orphaned Approvals");
244 Approval.load(trans, session, Approval.v2_0_17, appr -> {
245 UUID ticket = appr.add.ticket;
247 Approval.row(deleteCW,appr);
255 private void writeAnalysis(AuthzTrans trans, UserRole ur) {
256 Range r = expireRange.getRange("ur", ur.expires());
258 CSV.Writer cw = writerList.get(r.name());
265 private void writeAnalysis(AuthzTrans trans, Cred cred, Instance inst) {
266 if(cred!=null && inst!=null) {
267 Range r = expireRange.getRange("cred", inst.expires);
269 CSV.Writer cw = writerList.get(r.name());
277 private void writeAnalysis(AuthzTrans trans, X509 x509, X509Certificate x509Cert) throws IOException {
278 Range r = expireRange.getRange("x509", x509Cert.getNotAfter());
280 CSV.Writer cw = writerList.get(r.name());
282 x509.row(cw,x509Cert);
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())) {
296 if(current.isEmpty()) {
297 trans.warn().log(ns,"has no current owners");
301 List<String> email = new ArrayList<>();
302 for(UserRole ur : current) {
307 id = org.getIdentity(trans, ur.user());
310 email.add(id.email());
312 id = id.responsibleTo();
320 } catch (OrganizationException e) {
321 trans.error().log(e);
325 return email.toArray(new String[email.size()]);
330 protected void _close(AuthzTrans trans) {
332 for(CSV.Writer cw : writerList.values()) {