From 71037c39a37d3549dcfe31926832a657744fbe05 Mon Sep 17 00:00:00 2001 From: Instrumental Date: Mon, 26 Mar 2018 13:51:48 -0700 Subject: AT&T 2.0.19 Code drop, stage 3 Issue-ID: AAF-197 Change-Id: I8b02cb073ccba318ccaf6ea0276446bdce88fb82 Signed-off-by: Instrumental --- .../src/main/java/org/onap/aaf/auth/Batch.java | 524 +++++++++++++++++++++ .../java/org/onap/aaf/auth/BatchException.java | 51 ++ .../java/org/onap/aaf/auth/BatchPrincipal.java | 41 ++ .../src/main/java/org/onap/aaf/auth/CassBatch.java | 78 +++ .../java/org/onap/aaf/auth/actions/Action.java | 29 ++ .../java/org/onap/aaf/auth/actions/ActionDAO.java | 73 +++ .../org/onap/aaf/auth/actions/ActionPuntDAO.java | 72 +++ .../java/org/onap/aaf/auth/actions/CacheTouch.java | 53 +++ .../java/org/onap/aaf/auth/actions/CredDelete.java | 55 +++ .../java/org/onap/aaf/auth/actions/CredPrint.java | 56 +++ .../java/org/onap/aaf/auth/actions/CredPunt.java | 70 +++ .../main/java/org/onap/aaf/auth/actions/Email.java | 220 +++++++++ .../java/org/onap/aaf/auth/actions/EmailPrint.java | 98 ++++ .../org/onap/aaf/auth/actions/FuturePrint.java | 41 ++ .../main/java/org/onap/aaf/auth/actions/Key.java | 26 + .../java/org/onap/aaf/auth/actions/Message.java | 53 +++ .../java/org/onap/aaf/auth/actions/NSACreate.java | 58 +++ .../java/org/onap/aaf/auth/actions/NSADelete.java | 58 +++ .../org/onap/aaf/auth/actions/NSDescUpdate.java | 58 +++ .../java/org/onap/aaf/auth/actions/PermCreate.java | 69 +++ .../java/org/onap/aaf/auth/actions/PermDelete.java | 64 +++ .../java/org/onap/aaf/auth/actions/PermModify.java | 141 ++++++ .../java/org/onap/aaf/auth/actions/RoleCreate.java | 66 +++ .../java/org/onap/aaf/auth/actions/RoleDelete.java | 62 +++ .../java/org/onap/aaf/auth/actions/RoleModify.java | 152 ++++++ .../main/java/org/onap/aaf/auth/actions/URAdd.java | 57 +++ .../java/org/onap/aaf/auth/actions/URDelete.java | 59 +++ .../org/onap/aaf/auth/actions/URFutureApprove.java | 111 +++++ .../onap/aaf/auth/actions/URFutureApproveExec.java | 108 +++++ .../org/onap/aaf/auth/actions/URFuturePrint.java | 41 ++ .../java/org/onap/aaf/auth/actions/URModify.java | 80 ++++ .../java/org/onap/aaf/auth/actions/URPrint.java | 42 ++ .../java/org/onap/aaf/auth/actions/URPunt.java | 70 +++ .../auth/entryConverters/AafEntryConverter.java | 46 ++ .../auth/entryConverters/CredEntryConverter.java | 48 ++ .../aaf/auth/entryConverters/NsEntryConverter.java | 46 ++ .../auth/entryConverters/PermEntryConverter.java | 43 ++ .../auth/entryConverters/RoleEntryConverter.java | 42 ++ .../entryConverters/UserRoleEntryConverter.java | 45 ++ .../java/org/onap/aaf/auth/helpers/Approval.java | 309 ++++++++++++ .../java/org/onap/aaf/auth/helpers/Approver.java | 62 +++ .../org/onap/aaf/auth/helpers/CacheChange.java | 63 +++ .../java/org/onap/aaf/auth/helpers/Creator.java | 41 ++ .../main/java/org/onap/aaf/auth/helpers/Cred.java | 306 ++++++++++++ .../java/org/onap/aaf/auth/helpers/Future.java | 200 ++++++++ .../java/org/onap/aaf/auth/helpers/History.java | 178 +++++++ .../org/onap/aaf/auth/helpers/InputIterator.java | 69 +++ .../java/org/onap/aaf/auth/helpers/Loader.java | 26 + .../java/org/onap/aaf/auth/helpers/MiscID.java | 188 ++++++++ .../java/org/onap/aaf/auth/helpers/MonthData.java | 121 +++++ .../main/java/org/onap/aaf/auth/helpers/NS.java | 168 +++++++ .../org/onap/aaf/auth/helpers/Notification.java | 209 ++++++++ .../java/org/onap/aaf/auth/helpers/NsAttrib.java | 107 +++++ .../main/java/org/onap/aaf/auth/helpers/Perm.java | 172 +++++++ .../main/java/org/onap/aaf/auth/helpers/Role.java | 175 +++++++ .../java/org/onap/aaf/auth/helpers/UserRole.java | 282 +++++++++++ .../org/onap/aaf/auth/reports/ExpiringNext.java | 143 ++++++ .../java/org/onap/aaf/auth/update/Expiring.java | 503 ++++++++++++++++++++ .../java/org/onap/aaf/auth/update/ExpiringP2.java | 158 +++++++ .../org/onap/aaf/auth/update/NotifyApprovals.java | 236 ++++++++++ .../onap/aaf/auth/update/NotifyCredExpiring.java | 321 +++++++++++++ 61 files changed, 7143 insertions(+) create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/Batch.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchException.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchPrincipal.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/CassBatch.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Action.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionDAO.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionPuntDAO.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CacheTouch.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredDelete.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPrint.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPunt.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Email.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/EmailPrint.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/FuturePrint.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Key.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Message.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSACreate.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSADelete.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSDescUpdate.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermCreate.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermDelete.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermModify.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleCreate.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleDelete.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleModify.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URAdd.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URDelete.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApprove.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApproveExec.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFuturePrint.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URModify.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPrint.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPunt.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/AafEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/CredEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/NsEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/PermEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/RoleEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/UserRoleEntryConverter.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approval.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approver.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/CacheChange.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Creator.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Cred.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Future.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/History.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/InputIterator.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Loader.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MiscID.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MonthData.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NS.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Notification.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NsAttrib.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Perm.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Role.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/UserRole.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/reports/ExpiringNext.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/update/Expiring.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/update/ExpiringP2.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyApprovals.java create mode 100644 auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyCredExpiring.java (limited to 'auth/auth-batch/src/main/java/org') diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/Batch.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/Batch.java new file mode 100644 index 00000000..6d9252e2 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/Batch.java @@ -0,0 +1,524 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TimeZone; + +import org.apache.log4j.Logger; +import org.onap.aaf.auth.common.Define; +import org.onap.aaf.auth.dao.CassAccess; +import org.onap.aaf.auth.dao.cass.RoleDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.hl.Question; +import org.onap.aaf.auth.env.AuthzEnv; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.Organization; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.auth.org.OrganizationFactory; +import org.onap.aaf.auth.org.Organization.Identity; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.StaticSlot; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.impl.Log4JLogTarget; +import org.onap.aaf.misc.env.log4j.LogFileNamer; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.Statement; + +public abstract class Batch { + + private static String ROOT_NS; + + private static StaticSlot ssargs; + + protected static final String STARS = "*****"; + + protected final Cluster cluster; + protected static AuthzEnv env; + protected static Session session; + protected static Logger aspr; + protected static Set specialNames; + protected static boolean dryRun; + protected static String batchEnv; + + public static final String CASS_ENV = "CASS_ENV"; + public static final String LOG_DIR = "LOG_DIR"; + protected final static String PUNT="punt"; + protected final static String MAX_EMAILS="MAX_EMAILS"; + protected final static String VERSION="VERSION"; + public final static String GUI_URL="GUI_URL"; + + protected final static String ORA_URL="ora_url"; + protected final static String ORA_PASSWORD="ora_password"; + protected final Organization org; + + + + protected Batch(AuthzEnv env) throws APIException, IOException, OrganizationException { + // Be able to change Environments + // load extra properties, i.e. + // PERF.cassandra.clusters=.... + batchEnv = env.getProperty(CASS_ENV); + if(batchEnv != null) { + batchEnv = batchEnv.trim(); + env.info().log("Redirecting to ",batchEnv,"environment"); + String str; + for(String key : new String[]{ + CassAccess.CASSANDRA_CLUSTERS, + CassAccess.CASSANDRA_CLUSTERS_PORT, + CassAccess.CASSANDRA_CLUSTERS_USER_NAME, + CassAccess.CASSANDRA_CLUSTERS_PASSWORD, + VERSION,GUI_URL,PUNT,MAX_EMAILS, + LOG_DIR, + "SPECIAL_NAMES" + }) { + if((str = env.getProperty(batchEnv+'.'+key))!=null) { + env.setProperty(key, str); + } + } + } + + // Setup for Dry Run + cluster = CassAccess.cluster(env,batchEnv); + env.info().log("cluster name - ",cluster.getClusterName()); + String dryRunStr = env.getProperty( "DRY_RUN" ); + if ( dryRunStr == null || dryRunStr.trim().equals("false") ) { + dryRun = false; + } else { + dryRun = true; + env.info().log("dryRun set to TRUE"); + } + + org = OrganizationFactory.init(env); + org.setTestMode(dryRun); + + // Special names to allow behaviors beyond normal rules + specialNames = new HashSet(); + String names = env.getProperty( "SPECIAL_NAMES" ); + if ( names != null ) + { + env.info().log("Loading SPECIAL_NAMES"); + for (String s :names.split(",") ) + { + env.info().log("\tspecial: " + s ); + specialNames.add( s.trim() ); + } + } + } + + protected abstract void run(AuthzTrans trans); + protected abstract void _close(AuthzTrans trans); + + public String[] args() { + return (String[])env.get(ssargs); + } + + public boolean isDryRun() + { + return dryRun; + } + + public boolean isSpecial(String user) { + if (specialNames != null && specialNames.contains(user)) { + env.info().log("specialName: " + user); + + return (true); + } else { + return (false); + } + } + + public boolean isMechID(String user) { + if (user.matches("m[0-9][0-9][0-9][0-9][0-9]")) { + return (true); + } else { + return (false); + } + } + + protected PrintStream fallout(PrintStream _fallout, String logType) + throws IOException { + PrintStream fallout = _fallout; + if (fallout == null) { + File dir = new File("logs"); + if (!dir.exists()) { + dir.mkdirs(); + } + + File f = null; + // String os = System.getProperty("os.name").toLowerCase(); + long uniq = System.currentTimeMillis(); + + f = new File(dir, getClass().getSimpleName() + "_" + logType + "_" + + uniq + ".log"); + + fallout = new PrintStream(new FileOutputStream(f, true)); + } + return fallout; + } + + public Organization getOrgFromID(AuthzTrans trans, String user) { + Organization org; + try { + org = OrganizationFactory.obtain(trans.env(),user.toLowerCase()); + } catch (OrganizationException e1) { + trans.error().log(e1); + org=null; + } + + if (org == null) { + PrintStream fallout = null; + + try { + fallout = fallout(fallout, "Fallout"); + fallout.print("INVALID_ID,"); + fallout.println(user); + } catch (Exception e) { + env.error().log("Could not write to Fallout File", e); + } + return (null); + } + + return (org); + } + + public static Row executeDeleteQuery(Statement stmt) { + Row row = null; + if (!dryRun) { + row = session.execute(stmt).one(); + } + + return (row); + + } + + public static int acquireRunLock(String className) { + Boolean testEnv = true; + String envStr = env.getProperty("AFT_ENVIRONMENT"); + + if (envStr != null) { + if (envStr.equals("AFTPRD")) { + testEnv = false; + } + } else { + env.fatal() + .log("AFT_ENVIRONMENT property is required and was not found. Exiting."); + System.exit(1); + } + + if (testEnv) { + env.info().log("TESTMODE: skipping RunLock"); + return (1); + } + + String hostname = null; + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + e.printStackTrace(); + env.warn().log("Unable to get hostname"); + return (0); + } + + ResultSet existing = session.execute(String.format( + "select * from authz.run_lock where class = '%s'", className)); + + for (Row row : existing) { + long curr = System.currentTimeMillis(); + ByteBuffer lastRun = row.getBytesUnsafe(2); // Can I get this field + // by name? + + long interval = (1 * 60 * 1000); // @@ Create a value in props file + // for this + long prev = lastRun.getLong(); + + if ((curr - prev) <= interval) { + env.warn().log( + String.format("Too soon! Last run was %d minutes ago.", + ((curr - prev) / 1000) / 60)); + env.warn().log( + String.format("Min time between runs is %d minutes ", + (interval / 1000) / 60)); + env.warn().log( + String.format("Last ran on machine: %s at %s", + row.getString("host"), row.getDate("start"))); + return (0); + } else { + env.info().log("Delete old lock"); + deleteLock(className); + } + } + + GregorianCalendar current = new GregorianCalendar(); + + // We want our time in UTC, hence "+0000" + SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+0000"); + fmt.setTimeZone(TimeZone.getTimeZone("UTC")); + + String cql = String + .format("INSERT INTO authz.run_lock (class,host,start) VALUES ('%s','%s','%s') IF NOT EXISTS", + className, hostname, fmt.format(current.getTime())); + + env.info().log(cql); + + Row row = session.execute(cql).one(); + if (!row.getBool("[applied]")) { + env.warn().log("Lightweight Transaction failed to write lock."); + env.warn().log( + String.format("host with lock: %s, running at %s", + row.getString("host"), row.getDate("start"))); + return (0); + } + return (1); + } + + private static void deleteLock( String className) { + Row row = session.execute( String.format( "DELETE FROM authz.run_lock WHERE class = '%s' IF EXISTS", className ) ).one(); + if (! row.getBool("[applied]")) { + env.info().log( "delete failed" ); + } + } + + private static void transferVMProps(AuthzEnv env, String ... props) { + String value; + for(String key : props) { + if((value = System.getProperty(key))!=null) { + env.setProperty(key, value); + } + } + } + + // IMPORTANT! VALIDATE Organization isUser method + protected void checkOrganizationAcccess(AuthzTrans trans, Question q) throws APIException, OrganizationException { + Set testUsers = new HashSet(); + Result> rrd = q.roleDAO.readNS(trans, ROOT_NS); + if(rrd.isOK()) { + for(RoleDAO.Data r : rrd.value) { + Result> rur = q.userRoleDAO.readByRole(trans, r.fullName()); + if(rur.isOK()) { + for(UserRoleDAO.Data udd : rur.value) { + testUsers.add(udd.user); + } + } + } + } + if(testUsers.size()<2) { + throw new APIException("Not enough Users in Roles for " + ROOT_NS + " to Validate"); + } + + Identity iden; + for(String user : testUsers) { + if((iden=org.getIdentity(trans,user))==null) { + throw new APIException("Failed Organization Entity Validation Check: " + user); + } else { + trans.info().log("Organization Validation Check: " + iden.id()); + } + } + } + + protected static String logDir() { + String ld = env.getProperty(LOG_DIR); + if(ld==null) { + if(batchEnv==null) { // Deployed Batch doesn't use different ENVs, and a common logdir + ld = "logs/"; + } else { + ld = "logs/"+batchEnv; + } + } + return ld; + } + protected int count(String str, char c) { + int count=str==null||str.isEmpty()?0:1; + for(int i=str.indexOf(c);i>=0;i=str.indexOf(c,i+1)) { + ++count; + } + return count; + } + + public final void close(AuthzTrans trans) { + _close(trans); + cluster.close(); + } + + public static void main(String[] args) { + PropAccess access = new PropAccess(args); + InputStream is = null; + String filename; + String propLoc; + try { + Define.set(access); + ROOT_NS=Define.ROOT_NS(); + + File f = new File("etc/authzBatch.props"); + try { + if (f.exists()) { + filename = f.getAbsolutePath(); + is = new FileInputStream(f); + propLoc = f.getPath(); + } else { + URL rsrc = ClassLoader.getSystemResource("authBatch.props"); + filename = rsrc.toString(); + is = rsrc.openStream(); + propLoc = rsrc.getPath(); + } + access.load(is); + } finally { + if (is == null) { + System.err.println("authBatch.props must exist in etc dir, or in Classpath"); + System.exit(1); + } + is.close(); + } + + env = new AuthzEnv(access); + + transferVMProps(env, CASS_ENV, "DRY_RUN", "NS", "Organization"); + + // Flow all Env Logs to Log4j, with ENV + + LogFileNamer lfn; + if ((batchEnv = env.getProperty(CASS_ENV)) == null) { + lfn = new LogFileNamer(logDir()).noPID(); + } else { + lfn = new LogFileNamer(logDir()).noPID(); + } + + lfn.setAppender("authz-batch"); + lfn.setAppender("aspr|ASPR"); + lfn.setAppender("sync"); + lfn.setAppender("jobchange"); + lfn.setAppender("validateuser"); + aspr = Logger.getLogger("aspr"); + Log4JLogTarget.setLog4JEnv("authz-batch", env); + if (filename != null) { + env.init().log("Instantiated properties from", filename); + } + + // Log where Config found + env.info().log("Configuring from", propLoc); + propLoc = null; + + Batch batch = null; + // setup ATTUser and Organization Slots before starting this: + // TODO redo this + // env.slot(ATT.ATT_USERSLOT); + // + // OrganizationFactory.setDefaultOrg(env, ATT.class.getName()); + AuthzTrans trans = env.newTrans(); + + TimeTaken tt = trans.start("Total Run", Env.SUB); + try { + int len = args.length; + if (len > 0) { + String toolName = args[0]; + len -= 1; + if (len < 0) + len = 0; + String nargs[] = new String[len]; + if (len > 0) { + System.arraycopy(args, 1, nargs, 0, len); + } + + env.put(ssargs = env.staticSlot("ARGS"), nargs); + + /* + * Add New Batch Programs (inherit from Batch) here + */ + + // Might be a Report, Update or Temp Batch + Class cls; + String classifier = ""; + try { + cls = ClassLoader.getSystemClassLoader().loadClass("org.onap.aaf.auth.update." + toolName); + classifier = "Update:"; + } catch (ClassNotFoundException e) { + try { + cls = ClassLoader.getSystemClassLoader().loadClass("org.onap.aaf.auth.reports." + toolName); + classifier = "Report:"; + } catch (ClassNotFoundException e2) { + try { + cls = ClassLoader.getSystemClassLoader() + .loadClass("org.onap.aaf.auth.temp." + toolName); + classifier = "Temp Utility:"; + } catch (ClassNotFoundException e3) { + cls = null; + } + } + } + if (cls != null) { + Constructor cnst = cls.getConstructor(new Class[] { AuthzTrans.class }); + batch = (Batch) cnst.newInstance(trans); + env.info().log("Begin", classifier, toolName); + } + + + if (batch == null) { + trans.error().log("No Batch named", toolName, "found"); + } + /* + * End New Batch Programs (inherit from Batch) here + */ + + } + if (batch != null) { + batch.run(trans); + } + } finally { + tt.done(); + if (batch != null) { + batch.close(trans); + } + StringBuilder sb = new StringBuilder("Task Times\n"); + trans.auditTrail(4, sb, AuthzTrans.SUB, AuthzTrans.REMOTE); + trans.info().log(sb); + } + } catch (Exception e) { + e.printStackTrace(System.err); + // Exceptions thrown by DB aren't stopping the whole process. + System.exit(1); + } + } + +} + diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchException.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchException.java new file mode 100644 index 00000000..4ed0940a --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchException.java @@ -0,0 +1,51 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth; + +public class BatchException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -3877245367723491192L; + + public BatchException() { + } + + public BatchException(String message) { + super(message); + } + + public BatchException(Throwable cause) { + super(cause); + } + + public BatchException(String message, Throwable cause) { + super(message, cause); + } + + public BatchException(String message, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchPrincipal.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchPrincipal.java new file mode 100644 index 00000000..6ca79018 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/BatchPrincipal.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ +package org.onap.aaf.auth; + +import org.onap.aaf.cadi.principal.TaggedPrincipal; + +public class BatchPrincipal extends TaggedPrincipal { + private final String name; + + public BatchPrincipal(final String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public String tag() { + return "Batch"; + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/CassBatch.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/CassBatch.java new file mode 100644 index 00000000..32e8f85d --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/CassBatch.java @@ -0,0 +1,78 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.impl.Log4JLogTarget; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.exceptions.InvalidQueryException; + +public abstract class CassBatch extends Batch { + + protected CassBatch(AuthzTrans trans, String log4JName) throws APIException, IOException, OrganizationException { + super(trans.env()); + // Flow all Env Logs to Log4j + Log4JLogTarget.setLog4JEnv(log4JName, env); + + TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE); + try { + session = cluster.connect(); + } finally { + tt.done(); + } + } + + @Override + protected void _close(AuthzTrans trans) { + session.close(); + trans.info().log("Closed Session"); + } + + public ResultSet executeQuery(String cql) { + return executeQuery(cql,""); + } + + public ResultSet executeQuery(String cql, String extra) { + if(isDryRun() && !cql.startsWith("SELECT")) { + if(extra!=null)env.info().log("Would query" + extra + ": " + cql); + } else { + if(extra!=null)env.info().log("query" + extra + ": " + cql); + try { + return session.execute(cql); + } catch (InvalidQueryException e) { + if(extra==null) { + env.info().log("query: " + cql); + } + throw e; + } + } + return null; + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Action.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Action.java new file mode 100644 index 00000000..ad3a447d --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Action.java @@ -0,0 +1,29 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; + +public interface Action { + public Result exec(AuthzTrans trans, D data, T t); +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionDAO.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionDAO.java new file mode 100644 index 00000000..90400015 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionDAO.java @@ -0,0 +1,73 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.CassAccess; +import org.onap.aaf.auth.dao.hl.Function; +import org.onap.aaf.auth.dao.hl.Question; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; + +public abstract class ActionDAO implements Action { + protected final Question q; + protected final Function f; + private boolean clean; + protected final boolean dryRun; + + public ActionDAO(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + q = new Question(trans, cluster, CassAccess.KEYSPACE, false); + f = new Function(trans,q); + clean = true; + this.dryRun = dryRun; + } + + public ActionDAO(AuthzTrans trans, ActionDAO predecessor) { + q = predecessor.q; + f = new Function(trans,q); + clean = false; + dryRun = predecessor.dryRun; + } + + public Session getSession(AuthzTrans trans) throws APIException, IOException { + return q.historyDAO.getSession(trans); + } + + public Question question() { + return q; + } + + public Function function() { + return f; + } + + public void close(AuthzTrans trans) { + if(clean) { + q.close(trans); + } + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionPuntDAO.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionPuntDAO.java new file mode 100644 index 00000000..332d2509 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/ActionPuntDAO.java @@ -0,0 +1,72 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public abstract class ActionPuntDAO extends ActionDAO { +// private static final SecureRandom random = new SecureRandom(); + private int months; +// private int range; + protected static final Date now = new Date(); + + public ActionPuntDAO(AuthzTrans trans, Cluster cluster, int months, int range, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + this.months = months; +// this.range = range; + } + + public ActionPuntDAO(AuthzTrans trans, ActionDAO predecessor, int months, int range) { + super(trans, predecessor); + this.months = months; +// this.range = range; + } + + + protected Date puntDate(Date current) { + GregorianCalendar temp = new GregorianCalendar(); + temp.setTime(current); + temp.add(GregorianCalendar.MONTH, months); + + /* + * This method Randomized date. This is no longer needed. Just add the Punt Months. + temp.setTime(now); + temp.add(GregorianCalendar.MONTH, months); + if(range>0) { + int forward = Math.abs(random.nextInt()%range); + if(forward>1) { + temp.add(GregorianCalendar.MONTH, forward); + temp.add(GregorianCalendar.DAY_OF_MONTH, (random.nextInt()%30)-15); + } + } + */ + return temp.getTime(); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CacheTouch.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CacheTouch.java new file mode 100644 index 00000000..8261c477 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CacheTouch.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class CacheTouch extends ActionDAO { + + public CacheTouch(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public CacheTouch(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, String table, String text) { + if(dryRun) { + trans.info().printf("Would mark %s cache in DB for clearing: %s",table, text); + return Result.ok(); + } else { + Result rv = q.clearCache(trans, table); + trans.info().printf("Set DB Cache %s for clearing: %s",table, text); + return rv; + } + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredDelete.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredDelete.java new file mode 100644 index 00000000..700aaaea --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredDelete.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class CredDelete extends ActionDAO { + + public CredDelete(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public CredDelete(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, CredDAO.Data cred, String text) { + if(dryRun) { + trans.info().log("Would Delete:",text,cred.id,CredPrint.type(cred.type),Chrono.dateOnlyStamp(cred.expires)); + return Result.ok(); + } else { + Result rv = q.credDAO.delete(trans, cred, true); // need to read for undelete + trans.info().log("Deleted:",text,cred.id,CredPrint.type(cred.type),Chrono.dateOnlyStamp(cred.expires)); + return rv; + } + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPrint.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPrint.java new file mode 100644 index 00000000..10407ce4 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPrint.java @@ -0,0 +1,56 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.util.Chrono; + +public class CredPrint implements Action { + private String info; + + public CredPrint(String text) { + this.info = text; + } + + @Override + public Result exec(AuthzTrans trans, CredDAO.Data cred, String text) { + trans.info().log(info,cred.id,text, type(cred.type),Chrono.dateOnlyStamp(cred.expires)); + return Result.ok(); + } + + + public static String type(int type) { + switch(type) { + case CredDAO.BASIC_AUTH: // 1 + return "OLD"; + case CredDAO.BASIC_AUTH_SHA256: // 2 + return "U/P"; + case CredDAO.CERT_SHA256_RSA: // 200 + return "Cert"; + default: + return "Unknown"; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPunt.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPunt.java new file mode 100644 index 00000000..78c1f892 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/CredPunt.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.Date; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class CredPunt extends ActionPuntDAO { + + public CredPunt(AuthzTrans trans, Cluster cluster, int months, int range, boolean dryRun) throws IOException, APIException { + super(trans,cluster,months,range,dryRun); + } + + public CredPunt(AuthzTrans trans, ActionDAO adao, int months, int range) throws IOException { + super(trans, adao, months,range); + } + + public Result exec(AuthzTrans trans, CredDAO.Data cdd,String text) { + Result rv = null; + Result> read = q.credDAO.read(trans, cdd); + if(read.isOKhasData()) { + for(CredDAO.Data data : read.value) { + Date from = data.expires; + data.expires = puntDate(from); + if(data.expires.compareTo(from)<=0) { + trans.debug().printf("Error: %s is before %s", Chrono.dateOnlyStamp(data.expires), Chrono.dateOnlyStamp(from)); + } else { + if(dryRun) { + trans.info().log("Would Update Cred",cdd.id, CredPrint.type(cdd.type), "from",Chrono.dateOnlyStamp(from),"to",Chrono.dateOnlyStamp(data.expires)); + } else { + trans.info().log("Updated Cred",cdd.id, CredPrint.type(cdd.type), "from",Chrono.dateOnlyStamp(from),"to",Chrono.dateOnlyStamp(data.expires)); + rv = q.credDAO.update(trans, data); + } + } + } + } + if(rv==null) { + rv=Result.err(read); + } + return rv; + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Email.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Email.java new file mode 100644 index 00000000..346e517f --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Email.java @@ -0,0 +1,220 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.Organization; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.auth.org.Organization.Identity; +import org.onap.aaf.misc.env.util.Chrono; + +public class Email implements Action{ + protected final List toList; + protected final List ccList; + private final String[] defaultCC; + protected String subject; + private String preamble; + private Message msg; + private String sig; + protected String lineIndent=" "; + private long lastSent=0L; + + + public Email(String ... defaultCC) { + toList = new ArrayList(); + this.defaultCC = defaultCC; + ccList = new ArrayList(); + clear(); + } + + public Email clear() { + toList.clear(); + ccList.clear(); + for(String s: defaultCC) { + ccList.add(s); + } + return this; + } + + + public void indent(String indent) { + lineIndent = indent; + } + + public void preamble(String format, Object ... args) { + preamble = String.format(format, args); + } + + public Email addTo(Identity id) { + if(id!=null) { + if(!toList.contains(id.email())) { + toList.add(id.email()); + } + } + return this; + } + + public Email addTo(Collection users) { + for(String u : users) { + addTo(u); + } + return this; + } + + public Email addTo(String email) { + if(!toList.contains(email)) { + toList.add(email); + } + return this; + } + + public Email addCC(Identity id) { + if(id!=null) { + if(!ccList.contains(id.email())) { + ccList.add(id.email()); + } + } + return this; + } + + public Email addCC(String email) { + if(!ccList.contains(email)) { + ccList.add(email); + } + return this; + } + + + public Email add(Identity id, boolean toSuper) throws OrganizationException { + Identity responsible = id.responsibleTo(); + if(toSuper) { + addTo(responsible.email()); + addCC(id.email()); + } else { + addCC(responsible.email()); + addTo(id.email()); + } + return this; + } + + public Email subject(String format, Object ... args) { + if(format.contains("%s")) { + subject = String.format(format, args); + } else { + subject = format; + } + return this; + } + + + public Email signature(String format, Object ... args) { + sig = String.format(format, args); + return this; + } + + public void msg(Message msg) { + this.msg = msg; + } + + @Override + public Result exec(AuthzTrans trans, Organization org, String text) { + StringBuilder sb = new StringBuilder(); + if(preamble!=null) { + sb.append(lineIndent); + sb.append(preamble); + sb.append("\n\n"); + } + + if(msg!=null) { + msg.msg(sb,lineIndent); + sb.append("\n"); + } + + if(sig!=null) { + sb.append(sig); + sb.append("\n"); + } + + long ct = System.currentTimeMillis(); + long wait = ct-lastSent; + lastSent = ct; + if(wait < 100) { // 10 per second + try { + Thread.sleep(wait); + } catch (InterruptedException e) { + } + } + return exec(trans,org,sb); + } + + protected Result exec(AuthzTrans trans, Organization org, StringBuilder sb) { + try { + /* int status = */ + org.sendEmail(trans, + toList, + ccList, + subject, + sb.toString(), + false); + } catch (Exception e) { + return Result.err(Result.ERR_ActionNotCompleted,e.getMessage()); + } + return Result.ok(); + + } + + public void log(PrintStream ps, String text) { + ps.print(Chrono.dateTime()); + boolean first = true; + for(String s : toList) { + if(first) { + first = false; + ps.print(": "); + } else { + ps.print(", "); + } + ps.print(s); + } + if(!ccList.isEmpty()) { + first=true; + for(String s : ccList) { + if(first) { + first = false; + ps.print(" ["); + } else { + ps.print(", "); + } + ps.print(s); + } + ps.print(']'); + } + + ps.print(' '); + ps.println(text); + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/EmailPrint.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/EmailPrint.java new file mode 100644 index 00000000..dba02426 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/EmailPrint.java @@ -0,0 +1,98 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.PrintStream; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.Organization; + +public class EmailPrint extends Email { + + private static final int LINE_LENGTH = 100; + + public EmailPrint(String... defaultCC) { + super(defaultCC); + } + + /* (non-Javadoc) + * @see org.onap.aaf.auth.actions.Email#exec(org.onap.aaf.auth.org.test.Organization, java.lang.StringBuilder) + */ + @Override + protected Result exec(AuthzTrans trans, Organization org, StringBuilder msg) { + PrintStream out = System.out; + boolean first = true; + out.print("To: "); + for(String s: toList) { + if(first) {first = false;} + else {out.print(',');} + out.print(s); + } + out.println(); + + first = true; + out.print("CC: "); + for(String s: ccList) { + if(first) {first = false;} + else {out.print(',');} + out.print(s); + } + out.println(); + + out.print("Subject: "); + out.println(subject); + out.println(); + boolean go = true; + + for(int start=0, end=LINE_LENGTH;go;start=end,end=Math.min(msg.length(), start+LINE_LENGTH)) { + int ret = msg.indexOf("\n",start+1); + switch(ret) { + case -1: + out.println(msg.substring(start,end)); + break; + case 0: + end=start+1; + out.println(); + break; + default: + if(retstart && ret { + private String info; + + public FuturePrint(String text) { + this.info = text; + } + + @Override + public Result exec(AuthzTrans trans, Future f, String text) { + trans.info().log(info,f.id(),f.memo(),"expiring on",Chrono.dateOnlyStamp(f.expires())); + return Result.ok(); + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Key.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Key.java new file mode 100644 index 00000000..8c39e47d --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Key.java @@ -0,0 +1,26 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +public interface Key { + public String key(HELPER H); +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Message.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Message.java new file mode 100644 index 00000000..98fc0054 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/Message.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.util.ArrayList; +import java.util.List; + +public class Message { + public final List lines; + + public Message() { + lines = new ArrayList(); + } + + public void clear() { + lines.clear(); + } + + public String line(String format, Object ... args) { + String rv=String.format(format, args); + lines.add(rv); + return rv; + } + + public void msg(StringBuilder sb, String lineIndent) { + if(lines.size()>0) { + for(String line : lines) { + sb.append(lineIndent); + sb.append(line); + sb.append('\n'); + } + } + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSACreate.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSACreate.java new file mode 100644 index 00000000..3d215871 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSACreate.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.NsAttrib; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class NSACreate extends ActionDAO { + public NSACreate(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public NSACreate(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, NsAttrib nsa, String text) { + if(dryRun) { + trans.info().printf("Would Create %s Attrib '%s=%s' in %s",text,nsa.key,nsa.value,nsa.ns); + return Result.ok(); + } else { + Result rv = q.nsDAO.dao().attribAdd(trans, nsa.ns, nsa.key, nsa.value); + if(rv.isOK()) { + trans.info().printf("%s - Created Attrib '%s=%s' in %s",text,nsa.key,nsa.value,nsa.ns); + } else { + trans.error().printf("Error Creating Attrib '%s=%s' in %s - %s",nsa.key,nsa.value,nsa.ns,rv.details); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSADelete.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSADelete.java new file mode 100644 index 00000000..4b976822 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSADelete.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.NsAttrib; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class NSADelete extends ActionDAO { + public NSADelete(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public NSADelete(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, NsAttrib nsa, String text) { + if(dryRun) { + trans.info().printf("Would Delete %s Attrib '%s' in %s",text,nsa.key,nsa.ns); + return Result.ok(); + } else { + Result rv = q.nsDAO.dao().attribRemove(trans, nsa.ns, nsa.key); + if(rv.isOK()) { + trans.info().printf("%s - Deleted Attrib '%s' in %s",text,nsa.key,nsa.value,nsa.ns); + } else { + trans.error().printf("Error Deleting Attrib '%s' in %s - %s",nsa.key,nsa.value,nsa.ns,rv.details); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSDescUpdate.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSDescUpdate.java new file mode 100644 index 00000000..368c8452 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/NSDescUpdate.java @@ -0,0 +1,58 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.NS; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class NSDescUpdate extends ActionDAO { + public NSDescUpdate(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public NSDescUpdate(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, NS ns, String desc) { + if(dryRun) { + trans.info().printf("Would Update '%s' Description to '%s'",ns,desc); + return Result.ok(); + } else { + Result rv = q.nsDAO.dao().addDescription(trans, ns.name, desc); + if(rv.isOK()) { + trans.info().printf("Updated '%s' Description to '%s'",ns,desc); + } else { + trans.error().printf("Error Updating '%s' Description to '%s' - %s",ns,desc,rv.details); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermCreate.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermCreate.java new file mode 100644 index 00000000..5f3ab202 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermCreate.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.PermDAO; +import org.onap.aaf.auth.dao.cass.PermDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Perm; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + + +public class PermCreate extends ActionDAO { + public PermCreate(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public PermCreate(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, Perm p,String text) { + PermDAO.Data pdd = new PermDAO.Data(); + pdd.ns = p.ns; + pdd.type = p.type; + pdd.instance = p.instance; + pdd.action = p.action; + pdd.description = p.description; + pdd.roles = p.roles; + + if(dryRun) { + trans.info().log("Would Create Perm:",text,p.fullType()); + return Result.ok(pdd); + } else { + Result rv = q.permDAO.create(trans, pdd); // need to read for undelete + if(rv.isOK()) { + trans.info().log("Created Perm:",text,p.fullType()); + } else { + trans.error().log("Error Creating Role -",rv.details,":",p.fullType()); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermDelete.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermDelete.java new file mode 100644 index 00000000..02fd3c6c --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermDelete.java @@ -0,0 +1,64 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.PermDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Perm; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class PermDelete extends ActionDAO { + public PermDelete(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public PermDelete(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, Perm p,String text) { + PermDAO.Data pdd = new PermDAO.Data(); + pdd.ns = p.ns; + pdd.type = p.type; + pdd.instance = p.instance; + pdd.action = p.action; + if(dryRun) { + trans.info().log("Would Delete Perm:",text,p.fullType()); + return Result.ok(); + } else { + Result rv = q.permDAO.delete(trans, pdd, true); // need to read for undelete + if(rv.isOK()) { + trans.info().log("Deleted Perm:",text,p.fullType()); + } else { + trans.error().log("Error Deleting Perm -",rv.details,":",p.fullType()); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermModify.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermModify.java new file mode 100644 index 00000000..9b60cee1 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/PermModify.java @@ -0,0 +1,141 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.PermDAO; +import org.onap.aaf.auth.dao.cass.RoleDAO; +import org.onap.aaf.auth.dao.cass.Status; +import org.onap.aaf.auth.dao.cass.PermDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Perm; +import org.onap.aaf.auth.helpers.Role; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class PermModify extends ActionDAO { + public PermModify(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public PermModify(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, final Perm p, final Modify modify) { + Result> rr = q.permDAO.read(trans, p.ns,p.type,p.instance,p.action); + if(dryRun) { + if(rr.isOKhasData()) { + return Result.ok(rr.value.get(0)); + } else { + return Result.err(Result.ERR_NotFound, "Data not Found " + p.toString()); + } + } else { + Result rv = null; + if(rr.isOKhasData()) { + for(final Data d : rr.value) { + modify.change(d); + if(d.ns.equals(p.ns) && d.type.equals(p.type) && d.instance.equals(p.instance) && d.action.equals(p.action)) { + // update for fields + // In either case, adjust Permissions + for(String r : d.roles) { + if(!p.roles.contains(r)) { + q.permDAO.dao().addRole(trans, d, r); + } + } + for(String r : p.roles) { + if(!d.roles.contains(r)) { + q.permDAO.dao().delRole(trans, d, r); + } + } + rv = Result.ok(d); + } else { + for(String r : d.roles) { + Role role = Role.keys.get(r); + if(role.perms.contains(p.encode())) { + modify.roleModify().exec(trans, role, new RoleModify.Modify() { + @Override + public PermModify permModify() { + return PermModify.this; + } + + @Override + public void change(RoleDAO.Data rdd) { + rdd.perms.remove(p.encode()); + rdd.perms.add(d.encode()); + } + }); + } + } + + rv = q.permDAO.create(trans, d); + if(rv.isOK()) { + PermDAO.Data pdd = new PermDAO.Data(); + pdd.ns = p.ns; + pdd.type = p.type; + pdd.instance = p.instance; + pdd.action = p.action; + q.permDAO.delete(trans, pdd, false); + trans.info().printf("Updated %s|%s|%s|%s to %s|%s|%s|%s\n", + p.ns, p.type, p.instance, p.action, + d.ns, d.type, d.instance, d.action); + } else { + trans.info().log(rv.errorString()); + } + } + + } + } else { + rv = Result.err(rr); + } + if(rv==null) { + rv = Result.err(Status.ERR_General,"Never get to this code"); + } + + return rv; + } + } + + public static interface Modify { + void change(PermDAO.Data ur); + RoleModify roleModify(); + } + + public Result delete(AuthzTrans trans, Perm p) { + if(dryRun) { + return Result.ok(); + } else { + PermDAO.Data data = new PermDAO.Data(); + data.ns=p.ns; + data.type = p.type; + data.instance = p.instance; + data.action = p.action; + return q.permDAO.delete(trans,data,false); + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleCreate.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleCreate.java new file mode 100644 index 00000000..50d163ab --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleCreate.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.RoleDAO; +import org.onap.aaf.auth.dao.cass.RoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Role; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class RoleCreate extends ActionDAO { + public RoleCreate(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public RoleCreate(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, Role r,String text) { + RoleDAO.Data rdd = new RoleDAO.Data(); + rdd.ns = r.ns; + rdd.name = r.name; + rdd.description = r.description; + rdd.perms = r.perms; + + if(dryRun) { + trans.info().log("Would Create Role:",text,r.fullName()); + return Result.ok(rdd); + } else { + Result rv = q.roleDAO.create(trans, rdd); // need to read for undelete + if(rv.isOK()) { + trans.info().log("Created Role:",text,r.fullName()); + } else { + trans.error().log("Error Creating Role -",rv.details,":",r.fullName()); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleDelete.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleDelete.java new file mode 100644 index 00000000..cbe3c1c5 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleDelete.java @@ -0,0 +1,62 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.RoleDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Role; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class RoleDelete extends ActionDAO { + public RoleDelete(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public RoleDelete(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, Role r,String text) { + if(dryRun) { + trans.info().log("Would Delete Role:",text,r.fullName()); + return Result.ok(); + } else { + RoleDAO.Data rdd = new RoleDAO.Data(); + rdd.ns = r.ns; + rdd.name = r.name; + Result rv = q.roleDAO.delete(trans, rdd, true); // need to read for undelete + if(rv.isOK()) { + trans.info().log("Deleted Role:",text,r.fullName()); + } else { + trans.error().log("Error Deleting Role -",rv.details,":",r.fullName()); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleModify.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleModify.java new file mode 100644 index 00000000..c72a9d8f --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/RoleModify.java @@ -0,0 +1,152 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.PermDAO; +import org.onap.aaf.auth.dao.cass.RoleDAO; +import org.onap.aaf.auth.dao.cass.Status; +import org.onap.aaf.auth.dao.cass.RoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Perm; +import org.onap.aaf.auth.helpers.Role; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class RoleModify extends ActionDAO { + public RoleModify(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster, dryRun); + } + + public RoleModify(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(final AuthzTrans trans, final Role r,final RoleModify.Modify modify) { + Result> rr = q.roleDAO.read(trans, r.ns,r.name); + if(dryRun) { + if(rr.isOKhasData()) { + return Result.ok(rr.value.get(0)); + } else { + return Result.err(Result.ERR_NotFound, "Data not Found " + r.toString()); + } + } else { + Result rv = null; + if(rr.isOKhasData()) { + for(final Data d : rr.value) { + modify.change(d); + if(d.ns.equals(r.ns) && d.name.equals(r.name)) { + // update for fields + // In either case, adjust Roles + for(String p : d.perms) { + if(!r.perms.contains(p)) { + Result rpdd = PermDAO.Data.decode(trans, q, p); + if(rpdd.isOKhasData()) { + q.roleDAO.dao().addPerm(trans, d, rpdd.value); + } + } + } + for(String p : r.perms) { + if(!d.perms.contains(p)) { + Result rpdd = PermDAO.Data.decode(trans, q, p); + if(rpdd.isOKhasData()) { + q.roleDAO.dao().delPerm(trans, d, rpdd.value); + } + } + } + rv = Result.ok(d); + } else { + for(String p : d.perms) { + Perm perm = Perm.keys.get(p); + if(perm!=null) { + if(perm.roles.contains(r.encode())) { + modify.permModify().exec(trans, perm, new PermModify.Modify() { + @Override + public RoleModify roleModify() { + return RoleModify.this; + } + + @Override + public void change(PermDAO.Data pdd) { + pdd.roles.remove(r.encode()); + pdd.roles.add(d.encode()); + } + }); + } + } + } + Result> preexist = q.roleDAO.read(trans, d); + if(preexist.isOKhasData()) { + Data rdd = preexist.value.get(0); + for(String p : d.perms) { + Result perm = PermDAO.Data.decode(trans, q, p); + if(perm.isOKhasData()) { + q.roleDAO.dao().addPerm(trans,rdd, perm.value); + } + } + rv = Result.ok(rdd); + } else { + rv = q.roleDAO.create(trans, d); + } + if(rv.isOK()) { + trans.info().printf("Updating %s|%s to %s|%s", r.ns, r.name, d.ns, d.name); + RoleDAO.Data rmme = new RoleDAO.Data(); + rmme.ns=r.ns; + rmme.name=r.name; + q.roleDAO.delete(trans, rmme, false); + + } else { + trans.info().log(rv.errorString()); + } + } + } + } else { + rv = Result.err(rr); + } + if(rv==null) { + rv = Result.err(Status.ERR_General,"Never get to this code"); + } + return rv; + } + } + + public static interface Modify { + void change(RoleDAO.Data ur); + PermModify permModify(); + } + + public Result delete(AuthzTrans trans, Role r) { + if(dryRun) { + return Result.ok(); + } else { + RoleDAO.Data data = new RoleDAO.Data(); + data.ns=r.ns; + data.name = r.name; + return q.roleDAO.delete(trans,data,false); + } + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URAdd.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URAdd.java new file mode 100644 index 00000000..50a5a8f0 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URAdd.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class URAdd extends ActionDAO { + public URAdd(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public URAdd(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur, String text) { + if(dryRun) { + trans.info().log("Would Add:",text,ur.role(),ur.user(),"on",Chrono.dateOnlyStamp(ur.expires())); + return Result.ok(ur.urdd()); + } else { + Result rv = q.userRoleDAO.create(trans, ur.urdd()); + trans.info().log("Added:",text,ur.role(),ur.user(),"on",Chrono.dateOnlyStamp(ur.expires())); + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URDelete.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URDelete.java new file mode 100644 index 00000000..9bc7da49 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URDelete.java @@ -0,0 +1,59 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class URDelete extends ActionDAO { + public URDelete(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public URDelete(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur,String text) { + if(dryRun) { + trans.info().log("Would Delete UserRole:",text,ur.user(),ur.role(),"on",Chrono.dateOnlyStamp(ur.expires())); + return Result.ok(); + } else { + Result rv = q.userRoleDAO.delete(trans,ur.urdd(), true); // need to read for undelete + if(rv.isOK()) { + trans.info().log("Deleted UserRole:",text,ur.user(),ur.role(),"on",Chrono.dateOnlyStamp(ur.expires())); + } else { + trans.error().log("Error Deleting User Role -",rv.details,":",ur.user(),ur.role(),"on",Chrono.dateOnlyStamp(ur.expires()) ); + } + return rv; + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApprove.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApprove.java new file mode 100644 index 00000000..17d9cc01 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApprove.java @@ -0,0 +1,111 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.onap.aaf.auth.dao.cass.FutureDAO; +import org.onap.aaf.auth.dao.cass.NsDAO; +import org.onap.aaf.auth.dao.hl.Function; +import org.onap.aaf.auth.dao.hl.Question; +import org.onap.aaf.auth.dao.hl.Function.FUTURE_OP; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Approval; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.Organization.Expiration; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class URFutureApprove extends ActionDAO implements Action, Key { + private final Date start, expires; + + public URFutureApprove(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans,cluster, dryRun); + GregorianCalendar gc = new GregorianCalendar(); + start = gc.getTime(); + expires = trans.org().expiration(gc, Expiration.Future).getTime(); + } + + public URFutureApprove(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + GregorianCalendar gc = new GregorianCalendar(); + start = gc.getTime(); + expires = trans.org().expiration(gc, Expiration.Future).getTime(); + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur,String text) { + if(dryRun) { + return Result.ok(text); + } else { + Result rns = q.deriveNs(trans, ur.ns()); + if(rns.isOK()) { + + FutureDAO.Data data = new FutureDAO.Data(); + data.id=null; // let Create function assign UUID + data.target=Function.FOP_USER_ROLE; + + data.memo = key(ur); + data.start = start; + data.expires = ur.expires(); + try { + data.construct = ur.urdd().bytify(); + } catch (IOException e) { + return Result.err(e); + } + Result rfuture = f.createFuture(trans, data, Function.FOP_USER_ROLE, ur.user(), rns.value, FUTURE_OP.A); + if(rfuture.isOK()) { + trans.info().log(rfuture.value, text, ur.user(), data.memo); + } else { + trans.error().log(rfuture.details, text); + } + return rfuture; + } else { + return Result.err(rns); + } + } + } + + @Override + public String key(UserRole ur) { + String expire; + if(expires.before(start)) { + expire = "' - EXPIRED "; + } else { + expire = "' - expiring "; + } + + if(Question.OWNER.equals(ur.rname())) { + return Approval.RE_VALIDATE_OWNER + ur.ns() + expire + Chrono.dateOnlyStamp(ur.expires()); + } else if(Question.ADMIN.equals(ur.rname())) { + return Approval.RE_VALIDATE_ADMIN + ur.ns() + expire + Chrono.dateOnlyStamp(ur.expires()); + } else { + return Approval.RE_APPROVAL_IN_ROLE + ur.role() + expire + Chrono.dateOnlyStamp(ur.expires()); + } + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApproveExec.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApproveExec.java new file mode 100644 index 00000000..6cf2c53e --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFutureApproveExec.java @@ -0,0 +1,108 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.ApprovalDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.cass.ApprovalDAO.Data; +import org.onap.aaf.auth.dao.hl.Function.FUTURE_OP; +import org.onap.aaf.auth.dao.hl.Function.Lookup; +import org.onap.aaf.auth.dao.hl.Function.OP_STATUS; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Approval; +import org.onap.aaf.auth.helpers.Future; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class URFutureApproveExec extends ActionDAO, OP_STATUS, Future> { + + public URFutureApproveExec(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans,cluster, dryRun); + } + + public URFutureApproveExec(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, List app, Future future) { + if(dryRun) { + return Result.err(Result.ERR_ActionNotCompleted,"Not Executed"); + } else { + // Save on Lookups + final List apprs = new ArrayList(); + final List urs = new ArrayList(); + for(Approval a : app) { + apprs.add(a.add); + UserRole ur = UserRole.get(a.add.user, future.role); + if(ur!=null) { + urs.add(ur.urdd()); + } + } + Result rv = f.performFutureOp(trans, FUTURE_OP.A, future.fdd, + new Lookup>() { + @Override + public List get(AuthzTrans trans, Object ... noop) { + return apprs; + } + }, + new Lookup() { + @Override + public UserRoleDAO.Data get(AuthzTrans trans, Object ... keys) { + List lur = UserRole.byUser.get(keys[0]); + if(lur!=null) { + for(UserRole ur : lur) { + if(ur.role().equals(keys[1])) { + return ur.urdd(); + } + } + } + return null; + } + }); + if(rv.isOK()) { + switch(rv.value) { + case D: + trans.info().printf("Denied %s on %s", future.memo(),future.fdd.target); + break; + case E: + trans.info().printf("Completed %s on %s", future.memo(),future.fdd.target); + break; + case L: + trans.info().printf("Future %s on %s has lapsed", future.memo(),future.fdd.target); + break; + default: + } + } else { + trans.error().log("Error completing",future.memo(),rv.errorString()); + } + return rv; + } + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFuturePrint.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFuturePrint.java new file mode 100644 index 00000000..83a24c21 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URFuturePrint.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.util.Chrono; + + +public class URFuturePrint implements Action { + private String info; + + public URFuturePrint(String text) { + this.info = text; + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur, String text) { + trans.info().log(info,text,ur.user(),"to",ur.role(),"on",Chrono.dateOnlyStamp(ur.expires())); + return Result.ok(info); + }} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URModify.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URModify.java new file mode 100644 index 00000000..3f65a6a4 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URModify.java @@ -0,0 +1,80 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.Status; +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; + +import com.datastax.driver.core.Cluster; + +public class URModify extends ActionDAO { + public URModify(AuthzTrans trans, Cluster cluster, boolean dryRun) throws APIException, IOException { + super(trans, cluster,dryRun); + } + + public URModify(AuthzTrans trans, ActionDAO adao) { + super(trans, adao); + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur,Modify modify) { + if(dryRun) { + trans.info().printf("Would Update %s %s", ur.user(), ur.role()); + return Result.ok(); + } else { + Result> rr = q.userRoleDAO.read(trans, ur.user(),ur.role()); + if(rr.notOKorIsEmpty()) { + return Result.err(rr); + } + for(Data d : rr.value) { + modify.change(d); + if(!(ur.expires().equals(d.expires))) { + ur.expires(d.expires); + } + if(ur.user().equals(d.user) && ur.role().equals(d.role)){ + Result rv = q.userRoleDAO.update(trans, d); + if(rv.isOK()) { + trans.info().printf("Updated %s %s to %s", ur.user(), ur.role(), d.toString()); + } else { + trans.info().log(rv.errorString()); + } + } else { + return Result.err(Status.ERR_Denied, "You cannot change the key of this Data"); + } + } + return Result.err(Status.ERR_UserRoleNotFound,"No User Role with %s %s",ur.user(),ur.role()); + } + } + + public static interface Modify { + void change(UserRoleDAO.Data ur); + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPrint.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPrint.java new file mode 100644 index 00000000..a9bdf9ca --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPrint.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.util.Chrono; + +public class URPrint implements Action { + private String info; + + public URPrint(String text) { + this.info = text; + } + + @Override + public Result exec(AuthzTrans trans, UserRole ur, String text) { + trans.info().log(info,text,ur.user(),"to",ur.role(),"expiring on",Chrono.dateOnlyStamp(ur.expires())); + return Result.ok(); + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPunt.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPunt.java new file mode 100644 index 00000000..8676ef33 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/actions/URPunt.java @@ -0,0 +1,70 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.actions; + +import java.io.IOException; +import java.util.Date; +import java.util.List; + +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.Cluster; + +public class URPunt extends ActionPuntDAO { + public URPunt(AuthzTrans trans, Cluster cluster, int months, int range, boolean dryRun) throws APIException, IOException { + super(trans,cluster, months, range,dryRun); + } + + public URPunt(AuthzTrans trans, ActionDAO adao, int months, int range) { + super(trans, adao, months, range); + } + + public Result exec(AuthzTrans trans, UserRole ur, String text) { + if(dryRun) { + trans.info().log("Would Update User",ur.user(),"and Role", ur.role(), text); + return Result.ok(); + } else { + Result> read = q.userRoleDAO.read(trans, ur.user(), ur.role()); + if(read.isOK()) { + for(UserRoleDAO.Data data : read.value) { + Date from = data.expires; + data.expires = puntDate(from); + if(data.expires.compareTo(from)<=0) { + trans.debug().printf("Error: %s is same or before %s", Chrono.dateOnlyStamp(data.expires), Chrono.dateOnlyStamp(from)); + } else { + trans.info().log("Updating User",ur.user(),"and Role", ur.role(), "from",Chrono.dateOnlyStamp(from),"to",Chrono.dateOnlyStamp(data.expires), text); + q.userRoleDAO.update(trans, data); + } + } + return Result.ok(); + } else { + return Result.err(read); + } + } + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/AafEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/AafEntryConverter.java new file mode 100644 index 00000000..637ee569 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/AafEntryConverter.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import java.util.Set; + +public abstract class AafEntryConverter { + + protected String formatSet(Set set) { + if (set==null || set.isEmpty()) return ""; + StringBuilder sb = new StringBuilder(); + int curr = 0; + sb.append("{"); + for (String s : set) { + sb.append("'"); + sb.append(s); + sb.append("'"); + if (set.size() != curr + 1) { + sb.append(","); + } + curr++; + } + sb.append("}"); + return sb.toString(); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/CredEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/CredEntryConverter.java new file mode 100644 index 00000000..6153e75e --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/CredEntryConverter.java @@ -0,0 +1,48 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import org.onap.aaf.auth.dao.cass.CredDAO; + +import com.datastax.driver.core.utils.Bytes; +import com.googlecode.jcsv.writer.CSVEntryConverter; + +public class CredEntryConverter extends AafEntryConverter implements CSVEntryConverter { + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ssZ"; + + @Override + public String[] convertEntry(CredDAO.Data cd) { + String[] columns = new String[5]; + + columns[0] = cd.id; + columns[1] = String.valueOf(cd.type); + DateFormat df = new SimpleDateFormat(DATE_FORMAT); + columns[2] = df.format(cd.expires); + columns[3] = Bytes.toHexString(cd.cred); + columns[4] = (cd.ns==null)?"":cd.ns; + + return columns; + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/NsEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/NsEntryConverter.java new file mode 100644 index 00000000..b2767ab4 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/NsEntryConverter.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import org.onap.aaf.auth.dao.cass.NsDAO; + +import com.googlecode.jcsv.writer.CSVEntryConverter; + +public class NsEntryConverter extends AafEntryConverter implements CSVEntryConverter { + + @Override + public String[] convertEntry(NsDAO.Data nsd) { + String[] columns = new String[5]; + + columns[0] = nsd.name; + // Jonathan changed from "scope" to "type" + columns[1] = String.valueOf(nsd.type); + //TODO Chris: need to look at this +// columns[2] = formatSet(nsd.admin); +// columns[3] = formatSet(nsd.responsible); +// columns[4] = nsd.description==null?"":nsd.description; + columns[5] = nsd.description==null?"":nsd.description; + + return columns; + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/PermEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/PermEntryConverter.java new file mode 100644 index 00000000..12995f68 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/PermEntryConverter.java @@ -0,0 +1,43 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import org.onap.aaf.auth.dao.cass.PermDAO; + +import com.googlecode.jcsv.writer.CSVEntryConverter; + +public class PermEntryConverter extends AafEntryConverter implements CSVEntryConverter { + + @Override + public String[] convertEntry(PermDAO.Data pd) { + String[] columns = new String[6]; + + columns[0] = pd.ns; + columns[1] = pd.type; + columns[2] = pd.instance; + columns[3] = pd.action; + columns[4] = formatSet(pd.roles); + columns[5] = pd.description==null?"":pd.description; + + return columns; + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/RoleEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/RoleEntryConverter.java new file mode 100644 index 00000000..e236f3c3 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/RoleEntryConverter.java @@ -0,0 +1,42 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import org.onap.aaf.auth.dao.cass.RoleDAO; + +import com.googlecode.jcsv.writer.CSVEntryConverter; + +public class RoleEntryConverter extends AafEntryConverter implements CSVEntryConverter { + + @Override + public String[] convertEntry(RoleDAO.Data rd) { + String[] columns = new String[4]; + + columns[0] = rd.ns; + columns[1] = rd.name; + columns[2] = formatSet(rd.perms); + columns[3] = rd.description==null?"":rd.description; + + return columns; + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/UserRoleEntryConverter.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/UserRoleEntryConverter.java new file mode 100644 index 00000000..8730f945 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/entryConverters/UserRoleEntryConverter.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.entryConverters; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import org.onap.aaf.auth.dao.cass.UserRoleDAO; + +import com.googlecode.jcsv.writer.CSVEntryConverter; + +public class UserRoleEntryConverter extends AafEntryConverter implements CSVEntryConverter { + private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ssZ"; + + @Override + public String[] convertEntry(UserRoleDAO.Data urd) { + String[] columns = new String[3]; + + columns[0] = urd.user; + columns[1] = urd.role; + DateFormat df = new SimpleDateFormat(DATE_FORMAT); + columns[2] = df.format(urd.expires); + + return columns; + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approval.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approval.java new file mode 100644 index 00000000..0bd9397c --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approval.java @@ -0,0 +1,309 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TreeMap; +import java.util.UUID; + +import org.onap.aaf.auth.dao.cass.ApprovalDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class Approval implements CacheChange.Data { + public static final String RE_APPROVAL_IN_ROLE = "Re-Approval in Role '"; + public static final String RE_VALIDATE_ADMIN = "Re-Validate as Administrator for AAF Namespace '"; + public static final String RE_VALIDATE_OWNER = "Re-Validate Ownership for AAF Namespace '"; + + public static TreeMap> byApprover = new TreeMap>(); + public static TreeMap> byUser = new TreeMap>(); + public static TreeMap> byTicket = new TreeMap>(); + private final static CacheChange cache = new CacheChange(); + + public final ApprovalDAO.Data add; + private String role; + + public Approval(UUID id, UUID ticket, String approver, Date last_notified, + String user, String memo, String operation, String status, String type, long updated) { + add = new ApprovalDAO.Data(); + add.id = id; + add.ticket = ticket; + add.approver = approver; + add.last_notified = last_notified; + add.user = user; + add.memo = memo; + add.operation = operation; + add.status = status; + add.type = type; + add.updated = new Date(updated); + role = roleFromMemo(memo); + } + + public static String roleFromMemo(String memo) { + if(memo==null) { + return null; + } + int first = memo.indexOf('\''); + if(first>=0) { + int second = memo.indexOf('\'', ++first); + if(second>=0) { + String role = memo.substring(first, second); + if(memo.startsWith(RE_VALIDATE_ADMIN)) { + return role + ".admin"; + } else if(memo.startsWith(RE_VALIDATE_OWNER)) { + return role + ".owner"; + } else if(memo.startsWith(RE_APPROVAL_IN_ROLE)) { + return role; + } + } + } + return null; + } + + public static void load(Trans trans, Session session, Creator creator ) { + trans.info().log( "query: " + creator.select() ); + TimeTaken tt = trans.start("Load Notify", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement(creator.select()); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + tt = trans.start("Process Notify", Env.SUB); + + try { + List ln; + for(Row row : results.all()) { + ++count; + try { + Approval app = creator.create(row); + String person = app.getApprover(); + if(person!=null) { + ln = byApprover.get(person); + if(ln==null) { + ln = new ArrayList(); + byApprover.put(app.getApprover(), ln); + } + ln.add(app); + } + + + person = app.getUser(); + if(person!=null) { + ln = byUser.get(person); + if(ln==null) { + ln = new ArrayList(); + byUser.put(app.getUser(), ln); + } + ln.add(app); + } + UUID ticket = app.getTicket(); + if(ticket!=null) { + ln = byTicket.get(ticket); + if(ln==null) { + ln = new ArrayList(); + byTicket.put(app.getTicket(), ln); + } + ln.add(app); + } + } finally { + tt.done(); + } + } + } finally { + tt.done(); + trans.info().log("Found",count,"Approval Records"); + } + } + + @Override + public void expunge() { + List la = byApprover.get(getApprover()); + if(la!=null) { + la.remove(this); + } + + la = byUser.get(getUser()); + if(la!=null) { + la.remove(this); + } + UUID ticket = this.add==null?null:this.add.ticket; + if(ticket!=null) { + la = byTicket.get(this.add.ticket); + if(la!=null) { + la.remove(this); + } + } + } + + public void update(AuthzTrans trans, ApprovalDAO apprDAO, boolean dryRun) { + if(dryRun) { + trans.info().printf("Would update Approval %s, %s, last_notified %s",add.id,add.status,add.last_notified); + } else { + trans.info().printf("Update Approval %s, %s, last_notified %s",add.id,add.status,add.last_notified); + apprDAO.update(trans, add); + } + } + + public static Creator v2_0_17 = new Creator() { + @Override + public Approval create(Row row) { + return new Approval(row.getUUID(0), row.getUUID(1), row.getString(2), row.getTimestamp(3), + row.getString(4),row.getString(5),row.getString(6),row.getString(7),row.getString(8) + ,row.getLong(9)/1000); + } + + @Override + public String select() { + return "select id,ticket,approver,last_notified,user,memo,operation,status,type,WRITETIME(status) from authz.approval"; + } + }; + + /** + * @return the lastNotified + */ + public Date getLast_notified() { + return add.last_notified; + } + /** + * @param lastNotified the lastNotified to set + */ + public void setLastNotified(Date last_notified) { + add.last_notified = last_notified; + } + /** + * @return the status + */ + public String getStatus() { + return add.status; + } + /** + * @param status the status to set + */ + public void setStatus(String status) { + add.status = status; + } + /** + * @return the id + */ + public UUID getId() { + return add.id; + } + /** + * @return the ticket + */ + public UUID getTicket() { + return add.ticket; + } + /** + * @return the approver + */ + public String getApprover() { + return add.approver; + } + /** + * @return the user + */ + public String getUser() { + return add.user; + } + /** + * @return the memo + */ + public String getMemo() { + return add.memo; + } + /** + * @return the operation + */ + public String getOperation() { + return add.operation; + } + /** + * @return the type + */ + public String getType() { + return add.type; + } + public void lapsed() { + add.ticket=null; + add.status="lapsed"; + } + + public String getRole() { + return role; + } + + public String toString() { + return getUser() + ' ' + getMemo(); + } + + public void delayDelete(AuthzTrans trans, ApprovalDAO ad, boolean dryRun, String text) { + if(dryRun) { + trans.info().log(text,"- Would Delete: Approval",getId(),"on ticket",getTicket(),"for",getApprover()); + } else { + Result rv = ad.delete(trans, add, false); + if(rv.isOK()) { + trans.info().log(text,"- Deleted: Approval",getId(),"on ticket",getTicket(),"for",getApprover()); + cache.delayedDelete(this); + } else { + trans.info().log(text,"- Failed to Delete Approval",getId()); + } + } + } + + + public static void resetLocalData() { + cache.resetLocalData(); + } + + public static int sizeForDeletion() { + return cache.cacheSize(); + } + + public static void delayDelete(AuthzTrans noAvg, ApprovalDAO apprDAO, boolean dryRun, List list, String text) { + if(list!=null) { + for(Approval a : list) { + a.delayDelete(noAvg, apprDAO, dryRun,text); + } + } + } + + public static boolean pendingDelete(Approval a) { + return cache.contains(a); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approver.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approver.java new file mode 100644 index 00000000..6043e436 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Approver.java @@ -0,0 +1,62 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.HashMap; +import java.util.Map; + +import org.onap.aaf.auth.actions.Message; +import org.onap.aaf.auth.org.Organization; + +public class Approver { + public String name; + public Organization org; + public Map userRequests; + + public Approver(String approver, Organization org) { + this.name = approver; + this.org = org; + userRequests = new HashMap(); + } + + public void addRequest(String user) { + if (userRequests.get(user) == null) { + userRequests.put(user, 1); + } else { + Integer curCount = userRequests.remove(user); + userRequests.put(user, curCount+1); + } + } + + /** + * @param sb + * @return + */ + public void build(Message msg) { + msg.clear(); + msg.line("You have %d total pending approvals from the following users:", userRequests.size()); + for (Map.Entry entry : userRequests.entrySet()) { + msg.line(" %s (%d)",entry.getKey(),entry.getValue()); + } + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/CacheChange.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/CacheChange.java new file mode 100644 index 00000000..02f34d28 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/CacheChange.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.List; + +public class CacheChange { + private List removed; + + public CacheChange() { + removed = new ArrayList(); + } + + interface Data { + public abstract void expunge(); + } + + public final void delayedDelete(T t) { + removed.add(t); + } + + public final List getRemoved() { + return removed; + } + + public final void resetLocalData() { + if(removed==null || removed.isEmpty()) { + return; + } + for(T t : removed) { + t.expunge(); + } + removed.clear(); + } + + public int cacheSize() { + return removed.size(); + } + + public boolean contains(T t) { + return removed.contains(t); + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Creator.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Creator.java new file mode 100644 index 00000000..da6d558c --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Creator.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import com.datastax.driver.core.Row; + +public abstract class Creator { + public abstract T create(Row row); + public abstract String select(); + + public String query(String where) { + StringBuilder sb = new StringBuilder(select()); + if(where!=null) { + sb.append(" WHERE "); + sb.append(where); + } + sb.append(';'); + return sb.toString(); + } + + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Cred.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Cred.java new file mode 100644 index 00000000..58af03b5 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Cred.java @@ -0,0 +1,306 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; + +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.dao.hl.Question; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class Cred { + public static final TreeMap data = new TreeMap(); + public static final TreeMap> byNS = new TreeMap>(); + + public final String id; + public final List instances; + public final String ns; + + public Cred(String id) { + this.id = id; + instances = new ArrayList(); + ns=Question.domain2ns(id); + } + + public static class Instance { + public final int type; + public final Date expires,written; + public final Integer other; + + public Instance(int type, Date expires, Integer other, long written) { + this.type = type; + this.expires = expires; + this.other = other; + this.written = new Date(written); + } + } + + public Date last(final int ... types) { + Date last = null; + for(Instance i : instances) { + if(types.length>0) { // filter by types, if requested + boolean quit = true; + for(int t : types) { + if(t==i.type) { + quit=false; + break; + } + } + if(quit) { + continue; + } + } + if(last==null || i.expires.after(last)) { + last = i.expires; + } + } + return last; + } + + + public Set types() { + Set types = new HashSet(); + for(Instance i : instances) { + types.add(i.type); + } + return types; + } + + public static void load(Trans trans, Session session, int ... types ) { + load(trans, session,"select id, type, expires, other, writetime(cred) from authz.cred;",types); + + } + + public static void loadOneNS(Trans trans, Session session, String ns,int ... types ) { + load(trans, session,"select id, type, expires, other, writetime(cred) from authz.cred WHERE ns='" + ns + "';"); + } + + private static void load(Trans trans, Session session, String query, int ...types) { + + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Read Creds", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + try { + Iterator iter = results.iterator(); + Row row; + int type; // for filtering + String id; + tt = trans.start("Load Credentials", Env.SUB); + try { + while(iter.hasNext()) { + ++count; + row = iter.next(); + id = row.getString(0); + type = row.getInt(1); + if(types.length>0) { // filter by types, if requested + boolean quit = true; + for(int t : types) { + if(t==type) { + quit=false; + break; + } + } + if(quit) { + continue; + } + } + Cred cred = data.get(id); + if(cred==null) { + cred = new Cred(id); + data.put(id, cred); + } + cred.instances.add(new Instance(type, row.getTimestamp(2), row.getInt(3), row.getLong(4)/1000)); + + List lscd = byNS.get(cred.ns); + if(lscd==null) { + byNS.put(cred.ns, (lscd=new ArrayList())); + } + boolean found = false; + for(Cred c : lscd) { + if(c.id.equals(cred.id)) { + found=true; + break; + } + } + if(!found) { + lscd.add(cred); + } + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",count,"creds"); + } + } + + /** + * Count entries in Cred data. + * Note, as opposed to other methods, need to load the whole cred table for the Types. + * @param numbuckets + * @return + */ + public static CredCount count(int numbuckets) { + CredCount cc = new CredCount(numbuckets); + for(Cred c : data.values()) { + for (Instance ci : c.instances) { + cc.inc(ci.type,ci.written, ci.expires); + } + } + return cc; +// String query = "select count(*) from authz.cred LIMIT 1000000;"; +// trans.info().log( "query: " + query ); +// TimeTaken tt = trans.start("Count Credentials", Env.REMOTE); +// ResultSet results; +// try { +// Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000); +// results = session.execute(stmt); +// return results.one().getLong(0); +// } finally { +// tt.done(); +// } + } + + public static class CredCount { + public int raw[]; + public int basic_auth[]; + public int basic_auth_256[]; + public int cert[]; + public int x509Added[]; + public int x509Expired[]; + public Date dates[]; + + public CredCount(int numbuckets) { + raw = new int[numbuckets]; + basic_auth = new int[numbuckets]; + basic_auth_256 = new int[numbuckets]; + cert = new int[numbuckets]; + x509Added = new int[numbuckets]; + x509Expired = new int[numbuckets]; + dates = new Date[numbuckets]; + GregorianCalendar gc = new GregorianCalendar(); + dates[0]=gc.getTime(); // now + gc.set(GregorianCalendar.DAY_OF_MONTH, 1); + gc.set(GregorianCalendar.HOUR, 0); + gc.set(GregorianCalendar.MINUTE, 0); + gc.set(GregorianCalendar.SECOND,0); + gc.set(GregorianCalendar.MILLISECOND,0); + gc.add(GregorianCalendar.MILLISECOND, -1); // last milli of month + for(int i=1;i { + public static final Map data = new TreeMap(); + public static final Map> byRole = new TreeMap>(); + + public final FutureDAO.Data fdd; + public final String role; // derived + private final static CacheChange cache = new CacheChange(); + + + public final UUID id() { + return fdd.id; + } + + public final String memo() { + return fdd.memo; + } + + public final String target() { + return fdd.target; + } + + public final Date start() { + return fdd.start; + } + + public final Date expires() { + return fdd.expires; + } + + + public Future(UUID id, String memo, String target, Date start, Date expires, ByteBuffer construct) { + fdd = new FutureDAO.Data(); + fdd.id = id; + fdd.memo = memo; + fdd.target = target; + fdd.start = start; + fdd.expires = expires; + fdd.construct = construct; + role = Approval.roleFromMemo(memo); + } + + public static void load(Trans trans, Session session, Creator creator) { + trans.info().log( "query: " + creator.select() ); + ResultSet results; + TimeTaken tt = trans.start("Load Futures", Env.REMOTE); + try { + Statement stmt = new SimpleStatement(creator.select()); + results = session.execute(stmt); + } finally { + tt.done(); + } + + int count = 0; + tt = trans.start("Process Futures", Env.SUB); + try { + for(Row row : results.all()) { + ++count; + Future f = creator.create(row); + data.put(f.fdd.id,f); + if(f.role!=null) { + List lf = byRole.get(f.role); + if(lf==null) { + byRole.put(f.role,lf = new ArrayList()); + } + lf.add(f); + } + } + } finally { + tt.done(); + trans.info().log("Found",count,"Futures"); + } + } + + public static Creator v2_0_17 = new Creator() { + @Override + public Future create(Row row) { + return new Future(row.getUUID(0),row.getString(1),row.getString(2), + row.getTimestamp(3),row.getTimestamp(4), null); + } + + @Override + public String select() { + return "select id,memo,target,start,expires from authz.future"; + } + }; + + public static Creator withConstruct = new Creator() { + @Override + public String select() { + return "select id,memo,target,start,expires,construct from authz.future"; + } + + @Override + public Future create(Row row) { + return new Future(row.getUUID(0),row.getString(1),row.getString(2), + row.getTimestamp(3),row.getTimestamp(4), row.getBytes(5)); + } + + }; + + public Result delayedDelete(AuthzTrans trans, FutureDAO fd, boolean dryRun, String text) { + Result rv; + if(dryRun) { + trans.info().log(text,"- Would Delete: ",fdd.id,fdd.memo,"expiring on",Chrono.dateOnlyStamp(fdd.expires)); + rv = Result.ok(); + } else { + rv = fd.delete(trans, fdd, true); // need to read for undelete + if(rv.isOK()) { + trans.info().log(text, "- Deleted:",fdd.id,fdd.memo,"expiring on",Chrono.dateOnlyStamp(fdd.expires)); + cache.delayedDelete(this); + } else { + if(rv.status!=6) { + trans.info().log(text,"- Failed to Delete Future", fdd.id); + } + } + } + return rv; + } + + /* (non-Javadoc) + * @see org.onap.aaf.auth.helpers.CacheChange.Data#resetLocalData() + */ + @Override + public void expunge() { + data.remove(fdd.id); + if(role!=null) { + List lf = byRole.get(role); + if(lf!=null) { + lf.remove(this); + } + } + } + + @Override + public int compareTo(Future o) { + if(o==null) { + return -1; + } + return fdd.id.compareTo(o.fdd.id); + } + + public static void resetLocalData() { + cache.resetLocalData(); + } + + public static int sizeForDeletion() { + return cache.cacheSize(); + } + + public static boolean pendingDelete(Future f) { + return cache.contains(f); + } + + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/History.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/History.java new file mode 100644 index 00000000..f153c06b --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/History.java @@ -0,0 +1,178 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.UUID; + +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class History { + public final UUID id; + public final String action; + public final String memo; + public final String reconstruct; + public final String subject; + public final String target; + public final String user; + public final int yr_mon; + + public History(UUID id, String action, String memo, String subject, String target, String user, int yr_mon) { + this.id = id; + this.action = action; + this.memo = memo; + this.reconstruct = null; + this.subject = subject; + this.target = target; + this.user = user; + this.yr_mon = yr_mon; + } + + public History(UUID id, String action, String memo, String reconstruct, String subject, String target, String user, int yr_mon) { + this.id = id; + this.action = action; + this.memo = memo; + this.reconstruct = reconstruct; + this.subject = subject; + this.target = target; + this.user = user; + this.yr_mon = yr_mon; + } + + public static void load(Trans trans, Session session, Creator creator, Loader loader) { + trans.info().log( "query: " + creator.select() ); + TimeTaken tt = trans.start("Read History", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement( creator.select() ).setReadTimeoutMillis(240000); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + try { + Iterator iter = results.iterator(); + Row row; + tt = trans.start("Load History", Env.SUB); + try { + while(iter.hasNext()) { + ++count; + row = iter.next(); + loader.exec(creator.create(row)); + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",count,"histories"); + } + } + + public String toString() { + return String.format("%s %d %s, %s, %s, %s, %s", + id.toString(), + yr_mon, + user, + target, + action, + subject, + memo); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return id.hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + return id.equals(obj); + } + + public static Creator sansConstruct = new Creator () { + @Override + public History create(Row row) { + return new History( + row.getUUID(0), + row.getString(1), + row.getString(2), + row.getString(3), + row.getString(4), + row.getString(5), + row.getInt(6)); + } + + @Override + public String select() { + return "SELECT id, action, memo, subject, target, user, yr_mon from authz.history LIMIT 10000000 "; + } + }; + + public static Creator avecConstruct = new Creator () { + private final StringBuilder sb = new StringBuilder(); + + @Override + public History create(Row row) { + ByteBuffer bb = row.getBytes(3); + sb.setLength(0); + + if(bb!=null && bb.hasRemaining()) { + sb.append("0x"); + while(bb.hasRemaining()) { + sb.append(String.format("%02x",bb.get())); + } + bb.flip(); + } + return new History( + row.getUUID(0), + row.getString(1), + row.getString(2), + sb.toString(), + row.getString(4), + row.getString(5), + row.getString(6), + row.getInt(7)); + } + + @Override + public String select() { + return "SELECT id, action, memo, reconstruct, subject, target, user, yr_mon from authz.history LIMIT 10000000 "; + } + }; + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/InputIterator.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/InputIterator.java new file mode 100644 index 00000000..cb0bfa6a --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/InputIterator.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Iterator; + +public class InputIterator implements Iterable { + private BufferedReader in; + private final PrintStream out; + private final String prompt, instructions; + + public InputIterator(BufferedReader in, PrintStream out, String prompt, String instructions) { + this.in = in; + this.out = out; + this.prompt = prompt; + this.instructions = instructions; + } + + @Override + public Iterator iterator() { + out.println(instructions); + return new Iterator() { + String input; + @Override + public boolean hasNext() { + out.append(prompt); + try { + input = in.readLine(); + } catch (IOException e) { + input = null; + return false; + } + return input.length()>0; + } + + @Override + public String next() { + return input; + } + + @Override + public void remove() { + } + }; + } +} + diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Loader.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Loader.java new file mode 100644 index 00000000..6d27f648 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Loader.java @@ -0,0 +1,26 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +public interface Loader { + public void exec(T t); +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MiscID.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MiscID.java new file mode 100644 index 00000000..1438ffdb --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MiscID.java @@ -0,0 +1,188 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.Map; +import java.util.TreeMap; + +import org.onap.aaf.auth.BatchException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class MiscID { + public static final TreeMap data = new TreeMap(); + /* + Sample Record + aad890|mj9030|20040902|20120207 + + **** Field Definitions **** + MISCID - AT&T Miscellaneous ID - Non-User ID (Types: Internal Mechanized ID, External Mechanized ID, Datagate ID, Customer ID, Vendor ID, Exchange Mail ID, CLEC ID, Specialized ID, Training ID) + SPONSOR_ATTUID - ATTUID of MiscID Sponsor (Owner) + CREATE_DATE - Date when MiscID was created + LAST_RENEWAL_DATE - Date when MiscID Sponsorship was last renewed + */ + public String id,sponsor,created,renewal; + + private static final String fieldString = "id,created,sponsor,renewal"; + + /** + * Load a Row of Strings (from CSV file). + * + * Be CAREFUL that the Row lists match the Fields above!!! If this changes, change + * 1) This Object + * 2) DB "suits.cql" + * 3) Alter existing Tables + * @param row + * @throws BatchException + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + public void set(String row []) throws BatchException { + if(row.length<4) {throw new BatchException("Row of MiscID_XRef is too short");} + id = row[0]; + sponsor = row[1]; + created = row[2]; + renewal = row[3]; + } + + public void set(Row row) { + id = row.getString(0); + sponsor = row.getString(1); + created = row.getString(2); + renewal = row.getString(3); + } + + + public static void load(Trans trans, Session session ) { + load(trans, session,"SELECT " + fieldString + " FROM authz.miscid;",data); + } + + public static void load(Trans trans, Session session, Map map ) { + load(trans, session,"SELECT " + fieldString + " FROM authz.miscid;",map); + } + + public static void loadOne(Trans trans, Session session, String id ) { + load(trans, session,"SELECT " + fieldString + " FROM authz.miscid WHERE id ='" + id + "';", data); + } + + public static void load(Trans trans, Session session, String query, Map map) { + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Read MiscID", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + try { + tt = trans.start("Load Map", Env.SUB); + try { + for( Row row : results.all()) { + MiscID miscID = new MiscID(); + miscID.set(row); + data.put(miscID.id,miscID); + ++count; + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",count,"miscID records"); + } + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return id.hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if(obj!=null && obj instanceof MiscID) { + return id.equals(((MiscID)obj).id); + } + return false; + } + + public StringBuilder insertStmt() throws IllegalArgumentException, IllegalAccessException { + StringBuilder sb = new StringBuilder("INSERT INTO authz.miscid ("); + sb.append(fieldString); + sb.append(") VALUES ('"); + sb.append(id); + sb.append("','"); + sb.append(sponsor); + sb.append("','"); + sb.append(created); + sb.append("','"); + sb.append(renewal); + sb.append("')"); + return sb; + } + + public StringBuilder updateStmt(MiscID source) { + StringBuilder sb = null; + if(id.equals(source.id)) { + sb = addField(sb,"sponser",sponsor,source.sponsor); + sb = addField(sb,"created",created,source.created); + sb = addField(sb,"renewal",renewal,source.renewal); + } + if(sb!=null) { + sb.append(" WHERE id='"); + sb.append(id); + sb.append('\''); + } + return sb; + } + + private StringBuilder addField(StringBuilder sb, String name, String a, String b) { + if(!a.equals(b)) { + if(sb==null) { + sb = new StringBuilder("UPDATE authz.miscid SET "); + } else { + sb.append(','); + } + sb.append(name); + sb.append("='"); + sb.append(b); + sb.append('\''); + } + return sb; + } + + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MonthData.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MonthData.java new file mode 100644 index 00000000..13a4c923 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/MonthData.java @@ -0,0 +1,121 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; + +import org.onap.aaf.misc.env.util.Split; + +import java.util.Set; +import java.util.TreeMap; + +public class MonthData { + public final Map> data = + new TreeMap>(); + private File f; + + public MonthData(String env) throws IOException { + f = new File("Monthly"+env+".dat"); + + if(f.exists()) { + BufferedReader br = new BufferedReader(new FileReader(f)); + try { + String line; + String[] split; + while((line=br.readLine())!=null) { + if(!line.startsWith("#")) { + split = Split.split(',', line); + if(split.length==5) { + add(Integer.parseInt(split[0]),split[1], + Integer.parseInt(split[2]), + Integer.parseInt(split[3]), + Integer.parseInt(split[4]) + ); + } + } + } + } finally { + br.close(); + } + } + } + + public void add(int yr_mon, String target, long total, long adds, long drops) { + Set row = data.get(yr_mon); + if(row==null) { + data.put(yr_mon, (row=new HashSet())); + } + row.add(new Row(target,total,adds,drops)); + } + + public boolean notExists(int yr_mon) { + return data.get(yr_mon)==null; + } + + public static class Row implements Comparable { + public final String target; + public final long total; + public final long adds; + public final long drops; + + public Row(String t, long it, long a, long d) { + target = t; + total = it; + adds = a; + drops = d; + } + + @Override + public int compareTo(Row o) { + return target.compareTo(o.target); + } + + public String toString() { + return target + '|' + total + '|' + drops + '|' + adds; + } + } + + public void write() throws IOException { + if(f.exists()) { + File bu = new File(f.getName()+".bak"); + f.renameTo(bu); + } + PrintStream ps = new PrintStream(f); + try { + for( Entry> rows : data.entrySet()) { + for(Row row : rows.getValue()) { + ps.printf("%d,%s,%d,%d,%d\n",rows.getKey(),row.target,row.total,row.adds,row.drops); + } + } + } finally { + ps.close(); + } + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NS.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NS.java new file mode 100644 index 00000000..5dde8895 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NS.java @@ -0,0 +1,168 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.Iterator; +import java.util.Map; +import java.util.TreeMap; + +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class NS implements Comparable { + public final static Map data = new TreeMap(); + + public final String name, description, parent; + public final int scope,type; + + public NS(String name, String description, String parent, int type, int scope) { + this.name = name; + this.description = description; + this.parent = parent; + this.scope = scope; + this.type = type; + } + + public static void load(Trans trans, Session session, Creator creator) { + load(trans,session, + "select name, description, parent, type, scope from authz.ns;" + ,creator); + } + + public static void loadOne(Trans trans, Session session, Creator creator, String ns) { + load(trans,session, + ("select name, description, parent, type, scope from authz.ns WHERE name='"+ns+"';") + ,creator + ); + } + + private static void load(Trans trans, Session session, String query, Creator creator) { + trans.info().log( "query: " + query ); + ResultSet results; + TimeTaken tt; + + tt = trans.start("Read Namespaces", Env.REMOTE); + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + + + try { + Iterator iter = results.iterator(); + Row row; + tt = trans.start("Load Namespaces", Env.SUB); + try { + while(iter.hasNext()) { + row = iter.next(); + NS ns = creator.create(row); + data.put(ns.name,ns); + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",data.size(),"Namespaces"); + } + + } + + public static long count(Trans trans, Session session) { + String query = "select count(*) from authz.ns LIMIT 1000000;"; + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Count Namespaces", Env.REMOTE); + ResultSet results; + try { + Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000); + results = session.execute(stmt); + return results.one().getLong(0); + } finally { + tt.done(); + } + } + + public String toString() { + return name; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + return name.equals(obj); + } + + @Override + public int compareTo(NS o) { + return name.compareTo(o.name); + } + + public static class NSSplit { + public String ns; + public String other; + public NSSplit(String s, int dot) { + ns = s.substring(0,dot); + other = s.substring(dot+1); + } + } + public static NSSplit deriveParent(String dotted) { + if(dotted==null)return null; + for(int idx = dotted.lastIndexOf('.');idx>=0; idx=dotted.lastIndexOf('.',idx-1)) { + if(data.get(dotted.substring(0, idx))!=null) { + return new NSSplit(dotted,idx); + } + } + return null; + } + + public static Creator v2_0_11 = new Creator () { + @Override + public NS create(Row row) { + return new NS(row.getString(0),row.getString(1), row.getString(2),row.getInt(3),row.getInt(4)); + } + + @Override + public String select() { + return "SELECT name, description, parent, type, scope FROM authz.ns "; + } + }; + + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Notification.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Notification.java new file mode 100644 index 00000000..9614bb19 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Notification.java @@ -0,0 +1,209 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TreeMap; + +import org.onap.aaf.auth.actions.Message; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.org.Organization; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class Notification { + public enum TYPE { + OA("Owner Approval",1),SA("Supervisor Approval",2),CN("Credential Expiration",20); + + private String desc; + private int type; + + private TYPE(String desc,int type) { + this.desc = desc; + this.type = type; + } + + public String desc() { + return desc; + } + + public int idx() { + return type; + } + + public static TYPE get(int idx) { + for(TYPE nt : TYPE.values()) { + if(idx==nt.type) { + return nt; + } + } + return null; + } + } + + + public static final TreeMap> data = new TreeMap>(); + public static final Date now = new Date(); + + public final String user; + public final TYPE type; + public Date last; + public int checksum; + public Message msg; + private int current; + public Organization org; + public int count; + + private Notification(String user, TYPE nt, Date last, int checksum) { + this.user = user; + this.type = nt; + this.last = last; + this.checksum = checksum; + current = 0; + count = 0; + } + + public static void load(Trans trans, Session session, Creator creator ) { + trans.info().log( "query: " + creator.select() ); + TimeTaken tt = trans.start("Load Notify", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement(creator.select()); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + tt = trans.start("Process Notify", Env.SUB); + + try { + for(Row row : results.all()) { + ++count; + try { + Notification not = creator.create(row); + List ln = data.get(not.user); + if(ln==null) { + ln = new ArrayList(); + data.put(not.user, ln); + } + ln.add(not); + } finally { + tt.done(); + } + } + } finally { + tt.done(); + trans.info().log("Found",count,"Notify Records"); + } + } + + public static Notification get(String user, TYPE type) { + List ln = data.get(user); + if(ln!=null) { + for(Notification n : ln) { + if(type.equals(n.type)) { + return n; + } + } + } + return null; + } + + public static Notification create(String user, TYPE type) { + return new Notification(user,type,null,0); + } + + public static Creator v2_0_18 = new Creator() { + @Override + public Notification create(Row row) { + int idx =row.getInt(1); + TYPE type = TYPE.get(idx); + if(type==null) { + return null; + } + return new Notification(row.getString(0), type, row.getTimestamp(2), row.getInt(3)); + } + + @Override + public String select() { + return "SELECT user,type,last,checksum FROM authz.notify LIMIT 100000"; + } + }; + + + public void set(Message msg) { + this.msg = msg; + } + + public int checksum() { + if(msg==null) { + current=0; + } else if(current==0) { + for(String l : msg.lines) { + for(byte b : l.getBytes()) { + current+=b; + } + } + } + return current; + } + + public boolean update(AuthzTrans trans, Session session, boolean dryRun) { + checksum(); + if(last==null || current==0 || current!=checksum) { + last = now; + current = checksum(); + String update = "UPDATE authz.notify SET " + + "last = '" + Chrono.utcStamp(last) + + "', checksum=" + + current + + " WHERE user='" + + user + + "' AND type=" + + type.idx() + + ";"; + if(dryRun) { + trans.info().log("Would",update); + } else { + session.execute(update); + } + return true; + } + return false; + } + + public String toString() { + return "\"" + user + "\",\"" + type.name() + "\",\"" + + Chrono.dateTime(last)+ "\", " + checksum; + } +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NsAttrib.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NsAttrib.java new file mode 100644 index 00000000..bb76c34c --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/NsAttrib.java @@ -0,0 +1,107 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.List; +import java.util.TreeMap; + +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class NsAttrib { + public static final List data = new ArrayList(); + public static final TreeMap> byKey = new TreeMap>(); + public static final TreeMap> byNS = new TreeMap>(); + + public final String ns,key,value; + + public NsAttrib(String ns, String key, String value) { + this.ns = ns; + this.key = key; + this.value = value; + } + + public static void load(Trans trans, Session session, Creator creator ) { + trans.info().log( "query: " + creator.select() ); + ResultSet results; + TimeTaken tt = trans.start("Load NsAttributes", Env.REMOTE); + try { + Statement stmt = new SimpleStatement(creator.select()); + results = session.execute(stmt); + } finally { + tt.done(); + } + int count = 0; + tt = trans.start("Process NsAttributes", Env.SUB); + + try { + for(Row row : results.all()) { + ++count; + NsAttrib ur = creator.create(row); + data.add(ur); + + List lna = byKey.get(ur.key); + if(lna==null) { + lna = new ArrayList(); + byKey.put(ur.key, lna); + } + lna.add(ur); + + lna = byNS.get(ur.ns); + if(lna==null) { + lna = new ArrayList(); + byNS.put(ur.ns, lna); + } + lna.add(ur); + } + } finally { + tt.done(); + trans.info().log("Found",count,"NS Attributes"); + } + } + + public static Creator v2_0_11 = new Creator() { + @Override + public NsAttrib create(Row row) { + return new NsAttrib(row.getString(0), row.getString(1), row.getString(2)); + } + + @Override + public String select() { + return "select ns,key,value from authz.ns_attrib"; + } + }; + + + public String toString() { + return '"' + ns + "\",\"" + key + "\",\"" + value +'"'; + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Perm.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Perm.java new file mode 100644 index 00000000..51a7098e --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Perm.java @@ -0,0 +1,172 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; + +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class Perm implements Comparable { + public static final TreeMap> data = new TreeMap>(); + public static final TreeMap keys = new TreeMap(); + private static List deletePerms = new ArrayList(); + + public final String ns, type, instance, action,description; + private String fullType = null, fullPerm = null, encode = null; + public final Set roles; + + public String encode() { + if(encode == null) { + encode = ns + '|' + type + '|' + instance + '|' + action; + } + return encode; + } + + public String fullType() { + if(fullType==null) { + fullType = ns + '.' + type; + } + return fullType; + } + + public String fullPerm() { + if(fullPerm==null) { + fullPerm = ns + '.' + type + '|' + instance + '|' + action; + } + return fullPerm; + } + + public Perm(String ns, String type, String instance, String action, String description, Set roles) { + this.ns = ns; + this.type = type; + this.instance = instance; + this.action = action; + this.description = description; + // 2.0.11 +// this.full = encode();//ns+'.'+type+'|'+instance+'|'+action; + this.roles = roles; + } + + public static void load(Trans trans, Session session) { + load(trans, session, "select ns, type, instance, action, description, roles from authz.perm;"); + } + + public static void loadOneNS(Trans trans, Session session, String ns) { + load(trans, session, "select ns, type, instance, action, description, roles from authz.perm WHERE ns='" + ns + "';"); + + } + + private static void load(Trans trans, Session session, String query) { + // + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Read Perms", Env.REMOTE); + ResultSet results; + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + + try { + Iterator iter = results.iterator(); + Row row; + tt = trans.start("Load Perms", Env.SUB); + try { + while(iter.hasNext()) { + row = iter.next(); + Perm pk = new Perm(row.getString(0),row.getString(1),row.getString(2),row.getString(3), row.getString(4), row.getSet(5,String.class)); + keys.put(pk.encode(), pk); + data.put(pk,pk.roles); + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",data.size(),"perms"); + } + } + + public static long count(Trans trans, Session session) { + String query = "select count(*) from authz.perm LIMIT 1000000;"; + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Count Namespaces", Env.REMOTE); + ResultSet results; + try { + Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000); + results = session.execute(stmt); + return results.one().getLong(0); + } finally { + tt.done(); + } + } + + public String toString() { + return encode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return encode().hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + return encode().equals(obj); + } + + @Override + public int compareTo(Perm o) { + return encode().compareTo(o.encode()); + } + + public static void stageRemove(Perm p) { + deletePerms.add(p); + } + + public static void executeRemove() { + for(Perm p : deletePerms) { + keys.remove(p.encode); + data.remove(p); + } + deletePerms.clear(); + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Role.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Role.java new file mode 100644 index 00000000..f48544b1 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/Role.java @@ -0,0 +1,175 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeMap; + +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class Role implements Comparable { + public static final TreeMap> data = new TreeMap>(); + public static final TreeMap keys = new TreeMap(); + public static final TreeMap byName = new TreeMap(); + private static List deleteRoles = new ArrayList(); + + public final String ns, name, description; + private String full, encode; + public final Set perms; + + public Role(String full) { + ns = name = description = ""; + this.full = full; + perms = new HashSet(); + } + + public Role(String ns, String name, String description,Set perms) { + this.ns = ns; + this.name = name; + this.description = description; + this.full = null; + this.encode = null; + this.perms = perms; + } + + public String encode() { + if(encode==null) { + encode = ns + '|' + name; + } + return encode; + } + + public String fullName() { + if(full==null) { + full = ns + '.' + name; + } + return full; + } + + public static void load(Trans trans, Session session ) { + load(trans,session,"select ns, name, description, perms from authz.role;"); + } + + public static void loadOneNS(Trans trans, Session session, String ns ) { + load(trans,session,"select ns, name, description, perms from authz.role WHERE ns='" + ns + "';"); + } + + private static void load(Trans trans, Session session, String query) { + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Read Roles", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + + try { + Iterator iter = results.iterator(); + Row row; + tt = trans.start("Load Roles", Env.SUB); + try { + while(iter.hasNext()) { + row = iter.next(); + Role rk =new Role(row.getString(0),row.getString(1), row.getString(2),row.getSet(3,String.class)); + keys.put(rk.encode(), rk); + data.put(rk,rk.perms); + byName.put(rk.fullName(), rk); + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Found",data.size(),"roles"); + } + } + + public static long count(Trans trans, Session session) { + String query = "select count(*) from authz.role LIMIT 1000000;"; + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Count Namespaces", Env.REMOTE); + ResultSet results; + try { + Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000); + results = session.execute(stmt); + return results.one().getLong(0); + } finally { + tt.done(); + } + } + + public String toString() { + return encode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return encode().hashCode(); + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + return encode().equals(obj); + } + + @Override + public int compareTo(Role o) { + return encode().compareTo(o.encode()); + } + + public static String fullName(String role) { + return role.replace('|', '.'); + } + + public static void stageRemove(Role r) { + deleteRoles.add(r); + } + + public static void executeRemove() { + for(Role p : deleteRoles) { + keys.remove(p.encode); + data.remove(p); + } + deleteRoles.clear(); + } + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/UserRole.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/UserRole.java new file mode 100644 index 00000000..d990bb11 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/helpers/UserRole.java @@ -0,0 +1,282 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.helpers; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; + +import org.onap.aaf.auth.actions.URDelete; +import org.onap.aaf.auth.dao.cass.UserRoleDAO; +import org.onap.aaf.auth.dao.cass.UserRoleDAO.Data; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; +import org.onap.aaf.misc.env.util.Chrono; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.Statement; + +public class UserRole implements Cloneable, CacheChange.Data { + public static final List data = new ArrayList(); + public static final TreeMap> byUser = new TreeMap>(); + public static final TreeMap> byRole = new TreeMap>(); + private final static CacheChange cache = new CacheChange(); + private static PrintStream urDelete=System.out,urRecover=System.err; + private static int totalLoaded; + private static int deleted; + + private Data urdd; + + public UserRole(String user, String ns, String rname, Date expires) { + urdd = new UserRoleDAO.Data(); + urdd.user = user; + urdd.role = ns + '.' + rname; + urdd.ns = ns; + urdd.rname = rname; + urdd.expires = expires; + } + + public UserRole(String user, String role, String ns, String rname, Date expires) { + urdd = new UserRoleDAO.Data(); + urdd.user = user; + urdd.role = role; + urdd.ns = ns; + urdd.rname = rname; + urdd.expires = expires; + } + + public static void load(Trans trans, Session session, Creator creator ) { + load(trans,session,creator,null); + } + + public static void loadOneRole(Trans trans, Session session, Creator creator, String role) { + load(trans,session,creator,"role='" + role +"' ALLOW FILTERING;"); + } + + public static void loadOneUser(Trans trans, Session session, Creator creator, String user ) { + load(trans,session,creator,"role='"+ user +"';"); + } + + private static void load(Trans trans, Session session, Creator creator, String where) { + String query = creator.query(where); + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Read UserRoles", Env.REMOTE); + + ResultSet results; + try { + Statement stmt = new SimpleStatement( query ); + results = session.execute(stmt); + } finally { + tt.done(); + } + try { + Iterator iter = results.iterator(); + Row row; + tt = trans.start("Load UserRole", Env.SUB); + try { + while(iter.hasNext()) { + ++totalLoaded; + row = iter.next(); + UserRole ur = creator.create(row); + data.add(ur); + + List lur = byUser.get(ur.urdd.user); + if(lur==null) { + lur = new ArrayList(); + byUser.put(ur.urdd.user, lur); + } + lur.add(ur); + + lur = byRole.get(ur.urdd.role); + if(lur==null) { + lur = new ArrayList(); + byRole.put(ur.urdd.role, lur); + } + lur.add(ur); + } + } finally { + tt.done(); + } + } finally { + trans.info().log("Loaded",totalLoaded,"UserRoles"); + } + } + + public int totalLoaded() { + return totalLoaded(); + } + + public int deleted() { + return deleted; + } + + @Override + public void expunge() { + data.remove(this); + + List lur = byUser.get(urdd.user); + if(lur!=null) { + lur.remove(this); + } + + lur = byRole.get(urdd.role); + if(lur!=null) { + lur.remove(this); + } + } + + public static void setDeleteStream(PrintStream ds) { + urDelete = ds; + } + + public static void setRecoverStream(PrintStream ds) { + urRecover = ds; + } + + public static long count(Trans trans, Session session) { + String query = "select count(*) from authz.user_role LIMIT 1000000;"; + trans.info().log( "query: " + query ); + TimeTaken tt = trans.start("Count Namespaces", Env.REMOTE); + ResultSet results; + try { + Statement stmt = new SimpleStatement(query).setReadTimeoutMillis(12000); + results = session.execute(stmt); + return results.one().getLong(0); + } finally { + tt.done(); + } + } + + + public static Creator v2_0_11 = new Creator() { + @Override + public UserRole create(Row row) { + return new UserRole(row.getString(0), row.getString(1), row.getString(2),row.getString(3),row.getTimestamp(4)); + } + + @Override + public String select() { + return "select user,role,ns,rname,expires from authz.user_role"; + } + }; + + public UserRoleDAO.Data urdd() { + return urdd; + } + + public String user() { + return urdd.user; + }; + + public String role() { + return urdd.role; + } + + public String ns() { + return urdd.ns; + } + + public String rname() { + return urdd.rname; + } + + public Date expires() { + return urdd.expires; + } + + public void expires(Date time) { + urdd.expires = time; + } + + + + public String toString() { + return "\"" + urdd.user + "\",\"" + urdd.role + "\",\"" + urdd.ns + "\",\"" + urdd.rname + "\",\""+ Chrono.dateOnlyStamp(urdd.expires); + } + + public static UserRole get(String u, String r) { + List lur = byUser.get(u); + if(lur!=null) { + for(UserRole ur : lur) { + if(ur.urdd.role.equals(r)) { + return ur; + } + } + } + return null; + } + + // CACHE Calling + private static final String logfmt = "%s UserRole - %s: %s-%s (%s, %s) expiring %s"; + private static final String replayfmt = "%s|%s|%s|%s|%s\n"; + private static final String deletefmt = "# %s\n"+replayfmt; + + // SAFETY - DO NOT DELETE USER ROLES DIRECTLY FROM BATCH FILES!!! + // We write to a file, and validate. If the size is iffy, we email Support + public void delayDelete(AuthzTrans trans, String text, boolean dryRun) { + String dt = Chrono.dateTime(urdd.expires); + if(dryRun) { + trans.info().printf(logfmt,text,"Would Delete",urdd.user,urdd.role,urdd.ns,urdd.rname,dt); + } else { + trans.info().printf(logfmt,text,"Staged Deletion",urdd.user,urdd.role,urdd.ns,urdd.rname,dt); + } + urDelete.printf(deletefmt,text,urdd.user,urdd.role,dt,urdd.ns,urdd.rname); + urRecover.printf(replayfmt,urdd.user,urdd.role,dt,urdd.ns,urdd.rname); + + cache.delayedDelete(this); + ++deleted; + } + + + /** + * Calls expunge() for all deleteCached entries + */ + public static void resetLocalData() { + cache.resetLocalData(); + } + + public static int sizeForDeletion() { + return cache.cacheSize(); + } + + public static boolean pendingDelete(UserRole ur) { + return cache.contains(ur); + } + + public static void actuateDeletionNow(AuthzTrans trans, URDelete directDel) { + for(UserRole ur : cache.getRemoved()) { + directDel.exec(trans, ur, "Actuating UserRole Deletion"); + } + cache.getRemoved().clear(); + cache.resetLocalData(); + } + + +} \ No newline at end of file diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/reports/ExpiringNext.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/reports/ExpiringNext.java new file mode 100644 index 00000000..2412f496 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/reports/ExpiringNext.java @@ -0,0 +1,143 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.reports; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; + +import org.onap.aaf.auth.Batch; +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Cred; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.helpers.Cred.Instance; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.util.Chrono; + +public class ExpiringNext extends Batch { + + public ExpiringNext(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + trans.info().log("Starting Connection Process"); + + TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB); + try { + TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE); + try { + session = cluster.connect(); + } finally { + tt.done(); + } + + UserRole.load(trans, session, UserRole.v2_0_11); + Cred.load(trans, session); + } finally { + tt0.done(); + } + } + + @Override + protected void run(AuthzTrans trans) { + GregorianCalendar gc = new GregorianCalendar(); + Date now = gc.getTime(); + gc.add(GregorianCalendar.WEEK_OF_MONTH, 2); + Date twoWeeks = gc.getTime(); + // Set time way off + gc.set(GregorianCalendar.YEAR, 3000); + Date earliestUR = gc.getTime(); + Date earliestCred = gc.getTime(); + // Run for Roles + List expiring = new ArrayList(); + + trans.info().log("Checking for Expired UserRoles"); + for(UserRole ur : UserRole.data) { + if(ur.expires().after(now)) { + if(ur.expires().before(twoWeeks)) { + expiring.add(Chrono.dateOnlyStamp(ur.expires()) + ":\t" + ur.user() + '\t' + ur.role()); + } + if(ur.expires().before(earliestUR)) { + earliestUR = ur.expires(); + } + } + } + + if(expiring.size()>0) { + Collections.sort(expiring,Collections.reverseOrder()); + for(String s : expiring) { + System.err.print('\t'); + System.err.println(s); + } + trans.info().printf("Earliest Expiring UR is %s\n\n", Chrono.dateOnlyStamp(earliestUR)); + } else { + trans.info().printf("No Expiring UserRoles within 2 weeks"); + } + + expiring.clear(); + + trans.info().log("Checking for Expired Credentials"); + for( Cred creds : Cred.data.values()) { + Instance lastInstance=null; + for(Instance inst : creds.instances) { + if(inst.type==CredDAO.BASIC_AUTH || inst.type==CredDAO.BASIC_AUTH_SHA256) { + if(lastInstance == null || inst.expires.after(lastInstance.expires)) { + lastInstance = inst; + } + } + } + if(lastInstance!=null) { + if(lastInstance.expires.after(now)) { + if(lastInstance.expires.before(twoWeeks)) { + expiring.add(Chrono.dateOnlyStamp(lastInstance.expires) + ": \t" + creds.id); + } + } + if(lastInstance.expires.before(earliestCred)) { + earliestCred = lastInstance.expires; + } + } + } + + if(expiring.size()>0) { + Collections.sort(expiring,Collections.reverseOrder()); + for(String s : expiring) { + System.err.print('\t'); + System.err.println(s); + } + trans.info().printf("Earliest Expiring Cred is %s\n\n", Chrono.dateOnlyStamp(earliestCred)); + } else { + trans.info().printf("No Expiring Creds within 2 weeks"); + } + + } + + @Override + protected void _close(AuthzTrans trans) { + session.close(); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/Expiring.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/Expiring.java new file mode 100644 index 00000000..d3b80d21 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/Expiring.java @@ -0,0 +1,503 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.update; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.UUID; + +import org.onap.aaf.auth.Batch; +import org.onap.aaf.auth.BatchPrincipal; +import org.onap.aaf.auth.actions.Action; +import org.onap.aaf.auth.actions.ActionDAO; +import org.onap.aaf.auth.actions.CacheTouch; +import org.onap.aaf.auth.actions.CredDelete; +import org.onap.aaf.auth.actions.CredPrint; +import org.onap.aaf.auth.actions.Email; +import org.onap.aaf.auth.actions.Message; +import org.onap.aaf.auth.actions.URDelete; +import org.onap.aaf.auth.actions.URFutureApprove; +import org.onap.aaf.auth.actions.URFutureApproveExec; +import org.onap.aaf.auth.actions.URPrint; +import org.onap.aaf.auth.dao.cass.ApprovalDAO; +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.dao.cass.FutureDAO; +import org.onap.aaf.auth.dao.hl.Function.FUTURE_OP; +import org.onap.aaf.auth.dao.hl.Function.OP_STATUS; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Approval; +import org.onap.aaf.auth.helpers.Cred; +import org.onap.aaf.auth.helpers.Future; +import org.onap.aaf.auth.helpers.NS; +import org.onap.aaf.auth.helpers.Role; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.helpers.Cred.Instance; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.auth.org.Organization.Identity; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.util.Chrono; + +public class Expiring extends Batch { + private CredPrint crPrint; + private URFutureApprove urFutureApprove; + private URFutureApproveExec urFutureApproveExec; + private CredDelete crDelete; + private URDelete urDelete; + private final CacheTouch cacheTouch; + private final AuthzTrans noAvg; + private final ApprovalDAO apprDAO; + private final FutureDAO futureDAO; + private final PrintStream urDeleteF,urRecoverF; + private final URPrint urPrint; + private Email email; + private File deletesFile; + + public Expiring(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + trans.info().log("Starting Connection Process"); + + noAvg = env.newTransNoAvg(); + noAvg.setUser(new BatchPrincipal("batch:Expiring")); + + TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB); + try { + crPrint = new CredPrint("Expired:"); + + TimeTaken tt = trans.start("Connect to Cluster with DAOs", Env.REMOTE); + try { + urFutureApprove = new URFutureApprove(trans, cluster,isDryRun()); + checkOrganizationAcccess(trans, urFutureApprove.question()); + urFutureApproveExec = new URFutureApproveExec(trans, urFutureApprove); + urPrint = new URPrint("User Roles:"); + crDelete = new CredDelete(trans, urFutureApprove); + urDelete = new URDelete(trans,urFutureApprove); + cacheTouch = new CacheTouch(trans, urFutureApprove); + + // Reusing... don't destroy + apprDAO = urFutureApprove.question().approvalDAO; + futureDAO = urFutureApprove.question().futureDAO; + + TimeTaken tt2 = trans.start("Connect to Cluster", Env.REMOTE); + try { + session = urFutureApprove.getSession(trans); + } finally { + tt2.done(); + } + } finally { + tt.done(); + } + + File data_dir = new File(env.getProperty("aaf_data_dir")); + if(!data_dir.exists() || !data_dir.canWrite() || !data_dir.canRead()) { + throw new IOException("Cannot read/write to Data Directory "+ data_dir.getCanonicalPath() + ": EXITING!!!"); + } + UserRole.setDeleteStream( + urDeleteF = new PrintStream(new FileOutputStream(deletesFile = new File(data_dir,"UserRoleDeletes.dat"),false))); + UserRole.setRecoverStream( + urRecoverF = new PrintStream(new FileOutputStream(new File(data_dir,"UserRoleRecover.dat"),false))); + UserRole.load(trans, session, UserRole.v2_0_11); + + Cred.load(trans, session); + NS.load(trans, session,NS.v2_0_11); + Future.load(trans,session,Future.withConstruct); + Approval.load(trans,session,Approval.v2_0_17); + Role.load(trans, session); + + email = new Email(); + email.subject("AAF Expiring Process Alert (ENV: %s)",batchEnv); + email.preamble("Expiring Process Alert for %s",batchEnv); + email.signature("Sincerely,\nAAF Expiring Batch Process\n"); + String address = env.getProperty("ALERT_TO_ADDRESS"); + if(address==null) { + throw new APIException("ALERT_TO_ADDRESS property is required"); + } + email.addTo(address); + + } catch (OrganizationException e) { + throw new APIException("Error getting valid Organization",e); + } finally { + tt0.done(); + } + } + + @Override + protected void run(AuthzTrans trans) { + // Setup Date boundaries + + final GregorianCalendar gc = new GregorianCalendar(); + final Date now = gc.getTime(); + + gc.add(GregorianCalendar.MONTH, 1); + Date future = gc.getTime(); +// Date earliest = null; + + // reset + gc.setTime(now); + gc.add(GregorianCalendar.DAY_OF_MONTH, -7); // save Expired Roles for 7 days. + Date tooLate = gc.getTime(); + + TimeTaken tt; + + // Clean out Approvals UserRoles are fixed up. + String memo; + for(List la : Approval.byUser.values()) { + for(Approval a : la ) { + memo = a.getMemo(); + if(memo!=null && (memo.contains("Re-Approval") || memo.contains("Re-Validate"))) { + String role = a.getRole(); + if(role!=null) { + UserRole ur = UserRole.get(a.getUser(), a.getRole()); + Future f=null; + if(ur!=null) { + if(ur.expires().after(future)) { // no need for Approval anymore + a.delayDelete(noAvg, apprDAO, dryRun, "User Role already Extended"); + UUID tkt = a.getTicket(); + if(tkt!=null) { + f = Future.data.get(tkt); + } + } + } else { + a.delayDelete(noAvg, apprDAO, dryRun, "User Role does not exist"); + f = Future.data.get(a.getTicket()); + } + if(f!=null) { + f.delayedDelete(noAvg, futureDAO, dryRun, "Approvals removed"); + } + } + } + } + } + try { + trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals"); + Future.resetLocalData(); + Approval.resetLocalData(); + } catch (Throwable t) { + t.printStackTrace(); + } + + // Run for Expired Futures + trans.info().log("Checking for Expired Approval/Futures"); + tt = trans.start("Delete old Futures", Env.REMOTE); + trans.info().log("### Running Future Execution on ",Future.data.size(), "Items"); + // Execute any Futures waiting + for(Future f : Future.data.values()) { + if(f.memo().contains("Re-Approval") || f.memo().contains("Re-Validate")) { + List la = Approval.byTicket.get(f.id()); + if(la!=null) { + Result ruf = urFutureApproveExec.exec(noAvg,la,f); + if(ruf.isOK()) { + switch(ruf.value) { + case P: + break; + case E: + case D: + case L: + f.delayedDelete(noAvg, futureDAO, dryRun,OP_STATUS.L.desc()); + Approval.delayDelete(noAvg, apprDAO, dryRun, la,OP_STATUS.L.desc()); + break; + } + } + } + } + } + try { + trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals"); + Future.resetLocalData(); + Approval.resetLocalData(); + } catch (Throwable t) { + t.printStackTrace(); + } + + + trans.info().log("### Remove Expired on ",Future.data.size(), "Items, or premature ones"); + // Remove Expired + String expiredBeforeNow = "Expired before " + tooLate; + String expiredAfterFuture = "Expired after " + future; + try { + for(Future f : Future.data.values()) { + if(f.expires().before(tooLate)) { + f.delayedDelete(noAvg,futureDAO,dryRun, expiredBeforeNow); + Approval.delayDelete(noAvg, apprDAO, dryRun, Approval.byTicket.get(f.id()), expiredBeforeNow); + } else if(f.expires().after(future)) { + f.delayedDelete(noAvg,futureDAO,dryRun, expiredAfterFuture); + Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), expiredAfterFuture); + } + } + try { + trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals"); + Future.resetLocalData(); + Approval.resetLocalData(); + } catch (Throwable t) { + t.printStackTrace(); + } + } finally { + tt.done(); + } + + trans.info().log("### Checking Approvals valid (",Approval.byApprover.size(),"Items)"); + // Make sure users of Approvals are still valid + for(List lapp : Approval.byTicket.values()) { + for(Approval app : lapp) { + Future f; + if(app.getTicket()==null) { + f = null; + } else { + f = Future.data.get(app.getTicket()); + if(Future.pendingDelete(f)) { + f=null; + } + } + String msg; + if(f!=null && app.getRole()!=null && Role.byName.get(app.getRole())==null) { + f.delayedDelete(noAvg,futureDAO,dryRun,msg="Role '" + app.getRole() + "' no longer exists"); + Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg); + continue; + } + + switch(app.getStatus()) { + case "pending": + if(f==null) { + app.delayDelete(noAvg,apprDAO, isDryRun(), "ticketDeleted"); + continue; + } + switch(app.getType()) { + case "owner": + boolean anOwner=false; + String approle = app.getRole(); + if(approle!=null) { + Role role = Role.byName.get(approle); + if(role==null) { + app.delayDelete(noAvg, apprDAO, dryRun, "Role No Longer Exists"); + continue; + } else { + // Make sure Owner Role exists + String owner = role.ns + ".owner"; + if(Role.byName.containsKey(owner)) { + List lur = UserRole.byRole.get(owner); + if(lur != null) { + for(UserRole ur : lur) { + if(ur.user().equals(app.getApprover())) { + anOwner = true; + break; + } + } + } + } + } + if(!anOwner) { + app.delayDelete(noAvg, apprDAO, dryRun, "No longer Owner"); + } + + } + break; + case "supervisor": + try { + Identity identity = org.getIdentity(noAvg, app.getUser()); + if(identity==null) { + if(f!=null) { + f.delayedDelete(noAvg,futureDAO,dryRun,msg = app.getUser() + " is no longer associated with " + org.getName()); + Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg); + } + } else { + if(!app.getApprover().equals(identity.responsibleTo().fullID())) { + if(f!=null) { + f.delayedDelete(noAvg,futureDAO,dryRun,msg = app.getApprover() + " is no longer a Supervisor of " + app.getUser()); + Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg); + } + } + } + } catch (OrganizationException e) { + e.printStackTrace(); + } + break; + } + break; + } + } + } + try { + trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals"); + Future.resetLocalData(); + Approval.resetLocalData(); + } catch (Throwable t) { + t.printStackTrace(); + } + + int count = 0, deleted=0, delayedURDeletes = 0; + + // Run for User Roles + trans.info().log("Checking for Expired User Roles"); + try { + for(UserRole ur : UserRole.data) { + if(org.getIdentity(noAvg, ur.user())==null) { // if not part of Organization; + if(isSpecial(ur.user())) { + trans.info().log(ur.user(),"is not part of organization, but may not be deleted"); + } else { + ur.delayDelete(noAvg, "Not Part of Organization", dryRun); + ++deleted; + ++delayedURDeletes; + } + } else { + if(NS.data.get(ur.ns())==null) { + ur.delayDelete(noAvg,"Namespace " + ur.ns() + " does not exist.",dryRun); + ++delayedURDeletes; + ++deleted; + } else if(!Role.byName.containsKey(ur.role())) { + ur.delayDelete(noAvg,"Role " + ur.role() + " does not exist.",dryRun); + ++deleted; + ++delayedURDeletes; + } else if(ur.expires().before(tooLate)) { + if("owner".equals(ur.rname())) { // don't delete Owners, even if Expired + urPrint.exec(noAvg,ur,"Owner Expired (but not deleted)"); + } else { + // In this case, when UR is expired, not dependent on other lookups, we delete straight out. + urDelete.exec(noAvg, ur,"Expired before " + tooLate); + ++deleted; + } + //trans.logAuditTrail(trans.info()); + } else if(ur.expires().before(future) && ur.expires().after(now)) { + ++count; + // Is there an Approval set already + boolean needNew = true; + if(ur.role()!=null && ur.user()!=null) { + List abm = Approval.byUser.get(ur.user()); + if(abm!=null) { + for(Approval a : abm) { + if(a.getOperation().equals(FUTURE_OP.A.name()) && ur.role().equals(a.getRole())) { + if(Future.data.get(a.getTicket())!=null) { + needNew = false; + break; + } + } + } + } + } + if(needNew) { + urFutureApprove.exec(noAvg, ur,""); + } + } + } + } + } catch (OrganizationException e) { + env.info().log(e,"Exiting ..."); + } finally { + env.info().log("Found",count,"user roles expiring before",future); + env.info().log("deleting",deleted,"user roles expiring before",tooLate); + } + + // Actualize UR Deletes, or send Email + if(UserRole.sizeForDeletion()>0) { + count+=UserRole.sizeForDeletion(); + double onePercent = 0.01; + if(((double)UserRole.sizeForDeletion())/UserRole.data.size() > onePercent) { + Message msg = new Message(); + try { + msg.line("Found %d of %d UserRoles marked for Deletion in file %s", + delayedURDeletes,UserRole.data.size(),deletesFile.getCanonicalPath()); + } catch (IOException e) { + msg.line("Found %d of %d UserRoles marked for Deletion.\n", + delayedURDeletes); + } + msg.line("Review the File. If data is ok, Use ExpiringP2 BatchProcess to complete the deletions"); + + email.msg(msg); + email.exec(trans, org, "Email Support"); + } else { + urDeleteF.flush(); + try { + BufferedReader br = new BufferedReader(new FileReader(deletesFile)); + try { + ExpiringP2.deleteURs(noAvg, br, urDelete, null /* don't touch Cache here*/); + } finally { + br.close(); + } + } catch (IOException io) { + noAvg.error().log(io); + } + } + } + if(count>0) { + String str = String.format("%d UserRoles modified or deleted", count); + cacheTouch.exec(trans, "user_role", str); + } + + // Run for Creds + trans.info().log("Checking for Expired Credentials"); + System.out.flush(); + count = 0; + try { + CredDAO.Data crd = new CredDAO.Data(); + Date last = null; + for( Cred creds : Cred.data.values()) { + crd.id = creds.id; + for(int type : creds.types()) { + crd.type = type; + for( Instance inst : creds.instances) { + if(inst.expires.before(tooLate)) { + crd.expires = inst.expires; + crDelete.exec(noAvg, crd,"Expired before " + tooLate); + } else if(last==null || inst.expires.after(last)) { + last = inst.expires; + } + } + if(last!=null) { + if(last.before(future)) { + crd.expires = last; + crPrint.exec(noAvg, crd,""); + ++count; + } + } + } + } + } finally { + String str = String.format("Found %d current creds expiring before %s", count, Chrono.dateOnlyStamp(future)); + if(count>0) { + cacheTouch.exec(trans, "cred", str); + } + } + + } + + @Override + protected void _close(AuthzTrans trans) { + aspr.info("End " + this.getClass().getSimpleName() + " processing" ); + for(Action action : new Action[] {crDelete}) { + if(action instanceof ActionDAO) { + ((ActionDAO)action).close(trans); + } + } + session.close(); + urDeleteF.close(); + urRecoverF.close(); + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/ExpiringP2.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/ExpiringP2.java new file mode 100644 index 00000000..f568b330 --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/ExpiringP2.java @@ -0,0 +1,158 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.update; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import org.onap.aaf.auth.Batch; +import org.onap.aaf.auth.BatchPrincipal; +import org.onap.aaf.auth.actions.Action; +import org.onap.aaf.auth.actions.ActionDAO; +import org.onap.aaf.auth.actions.CacheTouch; +import org.onap.aaf.auth.actions.URDelete; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.cadi.util.Split; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.util.Chrono; + +public class ExpiringP2 extends Batch { + private final URDelete urDelete; + private final CacheTouch cacheTouch; + private final AuthzTrans noAvg; + private final BufferedReader urDeleteF; + + public ExpiringP2(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + trans.info().log("Starting Connection Process"); + + noAvg = env.newTransNoAvg(); + noAvg.setUser(new BatchPrincipal("batch:ExpiringP2")); + + TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB); + try { + urDelete = new URDelete(trans, cluster,isDryRun()); + TimeTaken tt2 = trans.start("Connect to Cluster", Env.REMOTE); + try { + session = urDelete.getSession(trans); + } finally { + tt2.done(); + } + cacheTouch = new CacheTouch(trans,urDelete); + + File data_dir = new File(env.getProperty("aaf_data_dir")); + if(!data_dir.exists() || !data_dir.canWrite() || !data_dir.canRead()) { + throw new IOException("Cannot read/write to Data Directory "+ data_dir.getCanonicalPath() + ": EXITING!!!"); + } + urDeleteF = new BufferedReader(new FileReader(new File(data_dir,"UserRoleDeletes.dat"))); + + } finally { + tt0.done(); + } + } + + @Override + protected void run(AuthzTrans trans) { + deleteURs(noAvg, urDeleteF, urDelete, cacheTouch); + } + + public static void deleteURs(AuthzTrans trans, BufferedReader urDeleteF, URDelete urDelete, CacheTouch cacheTouch) { + String line,prev=""; + try { + UserRole ur; + Map tally = new HashMap(); + int count=0; + try { + while((line=urDeleteF.readLine())!=null) { + if(line.startsWith("#")) { + Count cnt = tally.get(line); + if(cnt==null) { + tally.put(line, cnt=new Count()); + } + cnt.inc(); + prev = line; + } else { + String[] l = Split.splitTrim('|', line); + try { + // Note: following default order from "COPY TO" + ur = new UserRole(l[0],l[1],l[3],l[4],Chrono.iso8601Fmt.parse(l[2])); + urDelete.exec(trans, ur, prev); + ++count; + } catch (ParseException e) { + trans.error().log(e); + } + } + } + + System.out.println("Tallies of UserRole Deletions"); + for(Entry es : tally.entrySet()) { + System.out.printf(" %6d\t%20s\n", es.getValue().cnt,es.getKey()); + } + } finally { + if(cacheTouch!=null && count>0) { + cacheTouch.exec(trans, "user_roles", "Removing UserRoles"); + } + } + } catch (IOException e) { + trans.error().log(e); + } + + } + private static class Count { + private int cnt=0; + + public /*synchonized*/ void inc() { + ++cnt; + } + + public String toString() { + return Integer.toString(cnt); + } + } + + @Override + protected void _close(AuthzTrans trans) { + aspr.info("End " + this.getClass().getSimpleName() + " processing" ); + for(Action action : new Action[] {urDelete,cacheTouch}) { + if(action instanceof ActionDAO) { + ((ActionDAO)action).close(trans); + } + } + session.close(); + try { + urDeleteF.close(); + } catch (IOException e) { + trans.error().log(e); + } + } + +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyApprovals.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyApprovals.java new file mode 100644 index 00000000..3314694e --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyApprovals.java @@ -0,0 +1,236 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.update; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.Map.Entry; + +import org.onap.aaf.auth.Batch; +import org.onap.aaf.auth.BatchPrincipal; +import org.onap.aaf.auth.actions.Email; +import org.onap.aaf.auth.actions.EmailPrint; +import org.onap.aaf.auth.actions.Message; +import org.onap.aaf.auth.dao.CassAccess; +import org.onap.aaf.auth.dao.cass.ApprovalDAO; +import org.onap.aaf.auth.dao.cass.FutureDAO; +import org.onap.aaf.auth.dao.cass.HistoryDAO; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Approval; +import org.onap.aaf.auth.helpers.Future; +import org.onap.aaf.auth.org.Organization; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.auth.org.OrganizationFactory; +import org.onap.aaf.auth.org.Organization.Identity; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.util.Chrono; + +public class NotifyApprovals extends Batch { + private static final String LINE = "----------------------------------------------------------------"; + private final HistoryDAO historyDAO; + private final ApprovalDAO apprDAO; + private final FutureDAO futureDAO; + private Email email; + private int maxEmails; + private final PrintStream ps; + private final AuthzTrans noAvg; + + public NotifyApprovals(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + + noAvg = env.newTransNoAvg(); + noAvg.setUser(new BatchPrincipal("batch:NotifyApprovals")); + + historyDAO = new HistoryDAO(trans, cluster, CassAccess.KEYSPACE); + session = historyDAO.getSession(trans); + apprDAO = new ApprovalDAO(trans, historyDAO); + futureDAO = new FutureDAO(trans, historyDAO); + if(isDryRun()) { + email = new EmailPrint(); + maxEmails=3; + } else { + email = new Email(); + maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3")); + } + email.subject("AAF Approval Notification (ENV: %s)",batchEnv); + email.preamble("AAF (MOTS 22830) is the AT&T Authorization System used by many AT&T Tools and Applications." + + "\n Your approval is required, which you may enter on the following page:" + + "\n\n\t%s/approve\n\n" + ,env.getProperty(GUI_URL)); + email.signature("Sincerely,\nAAF Team (Our MOTS# 22830)\n" + + "https://wiki.web.att.com/display/aaf/Contact+Us\n" + + "(Use 'Other Misc Requests (TOPS)')"); + + Approval.load(trans, session, Approval.v2_0_17); + Future.load(trans, session, Future.v2_0_17); // Skip the Construct Data + + ps = new PrintStream(new FileOutputStream(logDir() + "/email"+Chrono.dateOnlyStamp()+".log",true)); + ps.printf("### Approval Notify %s for %s%s\n",Chrono.dateTime(),batchEnv,dryRun?", DryRun":""); + } + + @Override + protected void run(AuthzTrans trans) { + GregorianCalendar gc = new GregorianCalendar(); + Date now = gc.getTime(); + String today = Chrono.dateOnlyStamp(now); + gc.add(GregorianCalendar.MONTH, -1); + gc=null; + + + Message msg = new Message(); + int emailCount = 0; + List pending = new ArrayList(); + boolean isOwner,isSupervisor; + for(Entry> es : Approval.byApprover.entrySet()) { + isOwner = isSupervisor = false; + String approver = es.getKey(); + if(approver.indexOf('@')<0) { + approver += org.getRealm(); + } + Date latestNotify=null, soonestExpire=null; + GregorianCalendar latest=new GregorianCalendar(); + GregorianCalendar soonest=new GregorianCalendar(); + pending.clear(); + + for(Approval app : es.getValue()) { + Future f = app.getTicket()==null?null:Future.data.get(app.getTicket()); + if(f==null) { // only Ticketed Approvals are valid.. the others are records. + // Approvals without Tickets are no longer valid. + if("pending".equals(app.getStatus())) { + app.setStatus("lapsed"); + app.update(noAvg,apprDAO,dryRun); // obeys dryRun + } + } else { + if((soonestExpire==null && f.expires()!=null) || (soonestExpire!=null && f.expires()!=null && soonestExpire.before(f.expires()))) { + soonestExpire=f.expires(); + } + + if("pending".equals(app.getStatus())) { + if(!isOwner) { + isOwner = "owner".equals(app.getType()); + } + if(!isSupervisor) { + isSupervisor = "supervisor".equals(app.getType()); + } + + if((latestNotify==null && app.getLast_notified()!=null) ||(latestNotify!=null && app.getLast_notified()!=null && latestNotify.before(app.getLast_notified()))) { + latestNotify=app.getLast_notified(); + } + pending.add(app); + } + } + } + + if(!pending.isEmpty()) { + boolean go = false; + if(latestNotify==null) { // never notified... make it so + go=true; + } else { + if(!today.equals(Chrono.dateOnlyStamp(latest))) { // already notified today + latest.setTime(latestNotify); + soonest.setTime(soonestExpire); + int year; + int days = soonest.get(GregorianCalendar.DAY_OF_YEAR)-latest.get(GregorianCalendar.DAY_OF_YEAR); + days+=((year=soonest.get(GregorianCalendar.YEAR))-latest.get(GregorianCalendar.YEAR))*365 + + (soonest.isLeapYear(year)?1:0); + if(days<7) { // If Expirations get within a Week (or expired), notify everytime. + go = true; + } + } + } + if(go) { + if(maxEmails>emailCount++) { + try { + Organization org = OrganizationFactory.obtain(env, approver); + Identity user = org.getIdentity(noAvg, approver); + if(user==null) { + ps.printf("Invalid Identity: %s\n", approver); + } else { + email.clear(); + msg.clear(); + email.addTo(user.email()); + msg.line(LINE); + msg.line("Why are you receiving this Notification?\n"); + if(isSupervisor) { + msg.line("%sYou are the supervisor of one or more employees who need access to tools which are protected by AAF. " + + "Your employees may ask for access to various tools and applications to do their jobs. ASPR requires " + + "that you are notified and approve their requests. The details of each need is provided when you click " + + "on webpage above.\n",isOwner?"1) ":""); + msg.line("Your participation in this process fulfills the ASPR requirement to re-authorize users in roles on a regular basis.\n\n"); + } + + if(isOwner) { + msg.line("%sYou are the listed owner of one or more AAF Namespaces. ASPR requires that those responsible for " + + "applications and their access review them regularly for accuracy. The AAF WIKI page for AT&T is https://wiki.web.att.com/display/aaf. " + + "More info regarding questions of being a Namespace Owner is available at https://wiki.web.att.com/pages/viewpage.action?pageId=594741363\n",isSupervisor?"2) ":""); + msg.line("Additionally, Credentials attached to the Namespace must be renewed regularly. While you may delegate certain functions to " + + "Administrators within your Namespace, you are ultimately responsible to make sure credentials do not expire.\n"); + msg.line("You may view the Namespaces you listed as Owner for in this AAF Env by viewing the following webpage:\n"); + msg.line(" %s/ns\n\n",env.getProperty(GUI_URL)); + + } + msg.line(" If you are unfamiliar with AAF, you might like to peruse the following links:" + + "\n\thttps://wiki.web.att.com/display/aaf/AAF+in+a+Nutshell" + + "\n\thttps://wiki.web.att.com/display/aaf/The+New+Person%%27s+Guide+to+AAF"); + msg.line("\n SPECIAL NOTE about SWM Management Groups: Understand that SWM management Groups correlate one-to-one to AAF Namespaces. " + + "(SWM uses AAF for the Authorization piece of Management Groups). You may be assigned the SWM Management Group by asking " + + "directly, or through any of the above stated automated processes. Auto-generated Namespaces typically look like 'com.att.44444.PROD' " + + "where '44444' is a MOTS ID, and 'PROD' is PROD|DEV|TEST, etc. For your convenience, the MOTS link is http://ebiz.sbc.com/mots.\n"); + msg.line(" Finally, realize that there are automated processes which create Machines and Resources via SWM, Kubernetes or other " + + "such tooling. If you or your predecessor requested them, you were set as the owner of the AAF Namespace created during " + + "that process.\n"); + msg.line(" For ALL QUESTIONS of why and how of SWM, and whether you or your reports can be removed, please contact SWM at " + + "https://wiki.web.att.com/display/swm/Support\n"); + + email.msg(msg); + email.exec(noAvg, org,""); + if(!isDryRun()) { + email.log(ps,"NotifyApprovals"); + for(Approval app : pending) { + app.setLastNotified(now); + app.update(noAvg, apprDAO, dryRun); + } + } + } + } catch (OrganizationException e) { + trans.info().log(e); + } + } + } + } + } + trans.info().printf("%d emails sent for %s", emailCount,batchEnv); + } + + @Override + protected void _close(AuthzTrans trans) { + futureDAO.close(trans); + apprDAO.close(trans); + historyDAO.close(trans); + ps.close(); + } +} diff --git a/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyCredExpiring.java b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyCredExpiring.java new file mode 100644 index 00000000..bdf8347c --- /dev/null +++ b/auth/auth-batch/src/main/java/org/onap/aaf/auth/update/NotifyCredExpiring.java @@ -0,0 +1,321 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.update; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.onap.aaf.auth.Batch; +import org.onap.aaf.auth.BatchPrincipal; +import org.onap.aaf.auth.actions.Email; +import org.onap.aaf.auth.actions.EmailPrint; +import org.onap.aaf.auth.actions.Message; +import org.onap.aaf.auth.dao.cass.CredDAO; +import org.onap.aaf.auth.dao.hl.Question; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.helpers.Cred; +import org.onap.aaf.auth.helpers.Notification; +import org.onap.aaf.auth.helpers.UserRole; +import org.onap.aaf.auth.helpers.Notification.TYPE; +import org.onap.aaf.auth.layer.Result; +import org.onap.aaf.auth.org.EmailWarnings; +import org.onap.aaf.auth.org.Organization; +import org.onap.aaf.auth.org.OrganizationException; +import org.onap.aaf.auth.org.OrganizationFactory; +import org.onap.aaf.auth.org.Organization.Identity; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.util.Chrono; + +import java.util.TreeMap; + + +public class NotifyCredExpiring extends Batch { + + private static final String UNKNOWN_ID = "unknown@deprecated.id"; + private static final String AAF_INSTANTIATED_MECHID = "AAF INSTANTIATED MECHID"; + private static final String EXPIRATION_DATE = "EXPIRATION DATE"; + private static final String QUICK_LINK = "QUICK LINK TO UPDATE PAGE"; + private static final String DASH_1 = "-----------------------"; + private static final String DASH_2 = "---------------"; + private static final String DASH_3 = "----------------------------------------------------"; + private static final String LINE = "\n----------------------------------------------------------------"; + private Email email; + private int maxEmails; + private final PrintStream ps; + private final AuthzTrans noAvg; + private String supportEmailAddr; + + public NotifyCredExpiring(AuthzTrans trans) throws APIException, IOException, OrganizationException { + super(trans.env()); + TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE); + try { + session = cluster.connect(); + } finally { + tt.done(); + } + + noAvg = env.newTransNoAvg(); + noAvg.setUser(new BatchPrincipal("batch:NotifyCredExpiring")); + + if((supportEmailAddr = env.getProperty("mailFromUserId"))==null) { + throw new APIException("mailFromUserId property must be set"); + } + if(isDryRun()) { + email = new EmailPrint(); + maxEmails=3; + maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3")); + } else { + email = new Email(); + maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3")); + } + + email.subject("AAF Password Expiration Notification (ENV: %s)",batchEnv); + email.preamble("AAF (MOTS 22830) is the AT&T Authorization System used by many AT&T Tools and Applications.\n\n" + + " The following Credentials are expiring on the dates shown. Failure to act before the expiration date " + + "will cause your App's Authentications to fail.\n"); + email.signature("Sincerely,\nAAF Team (Our MOTS# 22830)\n" + + "https://wiki.web.att.com/display/aaf/Contact+Us\n" + + "(Use 'Other Misc Requests (TOPS)')"); + + Cred.load(trans, session,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); + Notification.load(trans, session, Notification.v2_0_18); + UserRole.load(trans, session, UserRole.v2_0_11); + + ps = new PrintStream(new FileOutputStream(logDir() + "/email"+Chrono.dateOnlyStamp()+".log",true)); + ps.printf("### Approval Notify %s for %s%s\n",Chrono.dateTime(),batchEnv,dryRun?", DryRun":""); + } + + @Override + protected void run(AuthzTrans trans) { + + EmailWarnings ewp = org.emailWarningPolicy(); + long now = System.currentTimeMillis(); + Date early = new Date(now+(ewp.credExpirationWarning()*2)); // 2 months back + Date must = new Date(now+ewp.credExpirationWarning()); // 1 months back + Date critical = new Date(now+ewp.emailUrgentWarning()); // 1 week + Date within2Weeks = new Date(now+604800000 * 2); + Date withinLastWeek = new Date(now-604800000); + Date tooLate = new Date(now); + + // Temp structures + Map lastCred = new HashMap(); + Map> ownerCreds = new TreeMap>(); + Date last; + + + List noOwner = new ArrayList(); + ownerCreds.put(UNKNOWN_ID,noOwner); + + // Get a list of ONLY the ones needing email by Owner + for(Entry> es : Cred.byNS.entrySet()) { + lastCred.clear(); + for(Cred c : es.getValue()) { + last = c.last(CredDAO.BASIC_AUTH,CredDAO.BASIC_AUTH_SHA256); + if(last!=null && last.after(tooLate) && last.before(early)) { + List ownerURList = UserRole.byRole.get(es.getKey()+".owner"); + if(ownerURList!=null) { + for(UserRole ur:ownerURList) { + String owner = ur.user(); + List llc = ownerCreds.get(owner); + if(llc==null) { + ownerCreds.put(owner, (llc=new ArrayList())); + } + llc.add(new LastCred(c,last)); + } + } else { + noOwner.add(new LastCred(c,last)); + } + } + } + } + + boolean bCritical,bNormal,bEarly; + int emailCount=0; + Message msg = new Message(); + Notification ownNotf; + StringBuilder logMessage = new StringBuilder(); + for(Entry> es : ownerCreds.entrySet()) { + String owner = es.getKey(); + boolean header = true; + try { + Organization org = OrganizationFactory.obtain(env, owner); + Identity user = org.getIdentity(noAvg, owner); + if(!UNKNOWN_ID.equals(owner) && user==null) { + ps.printf("Invalid Identity: %s\n", owner); + } else { + logMessage.setLength(0); + if(maxEmails>emailCount) { + bCritical=bNormal=bEarly = false; + email.clear(); + msg.clear(); + email.addTo(user==null?supportEmailAddr:user.email()); + + ownNotf = Notification.get(es.getKey(),TYPE.CN); + if(ownNotf==null) { + ownNotf = Notification.create(user==null?UNKNOWN_ID:user.fullID(), TYPE.CN); + } + last = ownNotf.last; + // Get Max ID size for formatting purposes + int length = AAF_INSTANTIATED_MECHID.length(); + for(LastCred lc : es.getValue()) { + length = Math.max(length, lc.cred.id.length()); + } + String id_exp_fmt = "\t%-"+length+"s %15s %s"; + + Collections.sort(es.getValue(),LastCred.COMPARE); + for(LastCred lc : es.getValue()) { + if(lc.last.after(must) && lc.last.before(early) && + (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) { + if(!bEarly && header) { + msg.line("\tThe following are friendly 2 month reminders, just in case you need to schedule your updates early. " + + "You will be reminded next month\n"); + msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK); + msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3); + header = false; + } + bEarly = true; + } else if(lc.last.after(critical) && lc.last.before(must) && + (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) { + if(!bNormal) { + boolean last2wks = lc.last.before(within2Weeks); + if(last2wks) { + try { + Identity supvsr = user.responsibleTo(); + email.addCC(supvsr.email()); + } catch(OrganizationException e) { + trans.error().log(e, "Supervisor cannot be looked up"); + } + } + if(header) { + msg.line("\tIt is now important for you to update Passwords all all configurations using them for the following.\n" + + (last2wks?"\tNote: Your Supervisor is CCd\n":"\tNote: Your Supervisor will be notified if this is not being done before the last 2 weeks\n")); + msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK); + msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3); + } + header = false; + } + bNormal=true; + } else if(lc.last.after(tooLate) && lc.last.before(critical)) { // Email Every Day, with Supervisor + if(!bCritical && header) { + msg.line("\t!!! WARNING: These Credentials will expire in LESS THAN ONE WEEK !!!!\n" + + "\tYour supervisor is added to this Email\n"); + msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK); + msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3); + header = false; + } + bCritical = true; + try { + if(user!=null) { + Identity supvsr = user.responsibleTo(); + if(supvsr!=null) { + email.addCC(supvsr.email()); + supvsr = supvsr.responsibleTo(); + if(supvsr!=null) { + email.addCC(supvsr.email()); + } + } + } + } catch(OrganizationException e) { + trans.error().log(e, "Supervisor cannot be looked up"); + } + } + if(bEarly || bNormal || bCritical) { + if(logMessage.length()==0) { + logMessage.append("NotifyCredExpiring"); + } + logMessage.append("\n\t"); + logMessage.append(lc.cred.id); + logMessage.append('\t'); + logMessage.append(Chrono.dateOnlyStamp(lc.last)); + msg.line(id_exp_fmt, lc.cred.id, Chrono.dateOnlyStamp(lc.last)+" ",env.getProperty(GUI_URL)+"/creddetail?ns="+Question.domain2ns(lc.cred.id)); + } + } + + if(bEarly || bNormal || bCritical) { + msg.line(LINE); + msg.line("Why are you receiving this Notification?\n"); + msg.line("You are the listed owner of one or more AAF Namespaces. ASPR requires that those responsible for " + + "applications and their access review them regularly for accuracy. The AAF WIKI page for AT&T is https://wiki.web.att.com/display/aaf. " + + "You might like https://wiki.web.att.com/display/aaf/AAF+in+a+Nutshell. More detailed info regarding questions of being a Namespace Owner is available at https://wiki.web.att.com/pages/viewpage.action?pageId=594741363\n"); + msg.line("You may view the Namespaces you listed as Owner for in this AAF Env by viewing the following webpage:\n"); + msg.line(" %s/ns\n\n",env.getProperty(GUI_URL)); + email.msg(msg); + Result rv = email.exec(trans, org,""); + if(rv.isOK()) { + ++emailCount; + if(!isDryRun()) { + ownNotf.update(noAvg, session, false); + // SET LastNotification + } + email.log(ps,logMessage.toString()); + } else { + trans.error().log(rv.errorString()); + } + } + } + } + } catch (OrganizationException e) { + trans.info().log(e); + } + } + trans.info().printf("%d emails sent for %s", emailCount,batchEnv); + } + + private static class LastCred { + public Cred cred; + public Date last; + + public LastCred(Cred cred, Date last) { + this.cred = cred; + this.last = last; + } + + // Reverse Sort (Oldest on top) + public static Comparator COMPARE = new Comparator() { + @Override + public int compare(LastCred o1, LastCred o2) { + return o2.last.compareTo(o1.last); + } + }; + + public String toString() { + return Chrono.dateTime(last) + cred.toString(); + } + } + + @Override + protected void _close(AuthzTrans trans) { + session.close(); + ps.close(); + } +} -- cgit 1.2.3-korg