Update project structure to org.onap.aaf
[aaf/authz.git] / authz-defOrg / src / main / java / org / onap / aaf / osaaf / defOrg / DefaultOrg.java
diff --git a/authz-defOrg/src/main/java/org/onap/aaf/osaaf/defOrg/DefaultOrg.java b/authz-defOrg/src/main/java/org/onap/aaf/osaaf/defOrg/DefaultOrg.java
new file mode 100644 (file)
index 0000000..0352a1a
--- /dev/null
@@ -0,0 +1,596 @@
+/*******************************************************************************\r
+ * ============LICENSE_START====================================================\r
+ * * org.onap.aaf\r
+ * * ===========================================================================\r
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * * ===========================================================================\r
+ * * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * * you may not use this file except in compliance with the License.\r
+ * * You may obtain a copy of the License at\r
+ * * \r
+ *  *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * * \r
+ *  * Unless required by applicable law or agreed to in writing, software\r
+ * * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * * See the License for the specific language governing permissions and\r
+ * * limitations under the License.\r
+ * * ============LICENSE_END====================================================\r
+ * *\r
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
+ * *\r
+ ******************************************************************************/\r
+package org.onap.aaf.osaaf.defOrg;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.GregorianCalendar;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Set;\r
+\r
+import javax.mail.Address;\r
+import javax.mail.Message;\r
+import javax.mail.MessagingException;\r
+import javax.mail.Session;\r
+import javax.mail.Transport;\r
+import javax.mail.internet.InternetAddress;\r
+import javax.mail.internet.MimeMessage;\r
+\r
+import org.onap.aaf.authz.env.AuthzEnv;\r
+import org.onap.aaf.authz.env.AuthzTrans;\r
+import org.onap.aaf.authz.org.EmailWarnings;\r
+import org.onap.aaf.authz.org.Executor;\r
+import org.onap.aaf.authz.org.Organization;\r
+import org.onap.aaf.authz.org.OrganizationException;\r
+import org.onap.aaf.osaaf.defOrg.Identities.Data;\r
+\r
+public class DefaultOrg implements Organization {\r
+       private static final String PROPERTY_IS_REQUIRED = " property is Required";\r
+       private static final String DOMAIN = "osaaf.com";\r
+       private static final String REALM = "com.osaaf";\r
+       private static final String NAME = "Default Organization";\r
+       private static final String NO_PASS = NAME + " does not support Passwords.  Use AAF";\r
+       private final String mailHost,mailFromUserId,supportAddress;\r
+       private String SUFFIX;\r
+       // Possible ID Pattern\r
+       private static final String ID_PATTERN = "a-z[a-z0-9]{5-8}@.*";\r
+\r
+       public DefaultOrg(AuthzEnv env) throws OrganizationException {\r
+               String s;\r
+               mailHost = env.getProperty(s=(REALM + ".mailHost"), null);\r
+               if(mailHost==null) {\r
+                       throw new OrganizationException(s + PROPERTY_IS_REQUIRED);\r
+               }\r
+               supportAddress = env.getProperty(s=(REALM + ".supportEmail"), null);\r
+               if(supportAddress==null) {\r
+                       throw new OrganizationException(s + PROPERTY_IS_REQUIRED);\r
+               }\r
+               \r
+               String temp = env.getProperty(s=(REALM + ".mailFromUserId"), null);\r
+               mailFromUserId = temp==null?supportAddress:temp;\r
+\r
+               System.getProperties().setProperty("mail.smtp.host",mailHost);\r
+               System.getProperties().setProperty("mail.user", mailFromUserId);\r
+               // Get the default Session object.\r
+               session = Session.getDefaultInstance(System.getProperties());\r
+\r
+               SUFFIX='.'+getDomain();\r
+               \r
+               try {\r
+                       String defFile;\r
+                       temp=env.getProperty(defFile = (getClass().getName()+".file"));\r
+                       File fIdentities=null;\r
+                       if(temp==null) {\r
+                               temp = env.getProperty("aaf_data_dir");\r
+                               if(temp!=null) {\r
+                                       env.warn().log(defFile, "is not defined. Using default: ",temp+"/identities.dat");\r
+                                       File dir = new File(temp);\r
+                                       fIdentities=new File(dir,"identities.dat");\r
+                                       if(!fIdentities.exists()) {\r
+                                               env.warn().log("No",fIdentities.getCanonicalPath(),"exists.  Creating.");\r
+                                               if(!dir.exists()) {\r
+                                                       dir.mkdirs();\r
+                                               }\r
+                                               fIdentities.createNewFile();\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               fIdentities = new File(temp);\r
+                               if(!fIdentities.exists()) {\r
+                                       String dataDir = env.getProperty("aaf_data_dir");\r
+                                       if(dataDir!=null) {\r
+                                               fIdentities = new File(dataDir,temp);\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       if(fIdentities!=null && fIdentities.exists()) {\r
+                               identities = new Identities(fIdentities);\r
+                       } else {\r
+                               throw new OrganizationException(fIdentities.getCanonicalPath() + " does not exist.");\r
+                       }\r
+               } catch (IOException e) {\r
+                       throw new OrganizationException(e);\r
+               }\r
+       }\r
+       \r
+       // Implement your own Delegation System\r
+       static final List<String> NULL_DELEGATES = new ArrayList<String>();\r
+\r
+       public Identities identities;\r
+       private boolean dryRun;\r
+       private Session session;\r
+       public enum Types {Employee, Contractor, Application, NotActive};\r
+       private final static Set<String> typeSet;\r
+       \r
+       static {\r
+               typeSet = new HashSet<String>();\r
+               for(Types t : Types.values()) {\r
+                       typeSet.add(t.name());\r
+               }\r
+       }\r
+       \r
+       private static final EmailWarnings emailWarnings = new DefaultOrgWarnings();\r
+\r
+       @Override\r
+       public String getName() {\r
+               return NAME;\r
+       }\r
+\r
+       @Override\r
+       public String getRealm() {\r
+               return REALM;\r
+       }\r
+\r
+       @Override\r
+       public String getDomain() {\r
+               return DOMAIN;\r
+       }\r
+\r
+       @Override\r
+       public DefaultOrgIdentity getIdentity(AuthzTrans trans, String id) throws OrganizationException {\r
+               return new DefaultOrgIdentity(trans,id,this);\r
+       }\r
+\r
+       // Note: Return a null if found; return a String Message explaining why not found. \r
+       @Override\r
+       public String isValidID(String id) {\r
+               Data data;\r
+               try {\r
+                       data = identities.find(id, identities.reuse());\r
+               } catch (IOException e) {\r
+                       return getName() + " could not lookup " + id + ": " + e.getLocalizedMessage();\r
+               }\r
+               return data==null?id + "is not an Identity in " + getName():null;\r
+       }\r
+\r
+       @Override\r
+       public String isValidPassword(String user, String password, String... prev) {\r
+               // If you have an Organization user/Password scheme, use here, otherwise, just use AAF\r
+               return NO_PASS;\r
+       }\r
+\r
+       @Override\r
+       public Set<String> getIdentityTypes() {\r
+               return typeSet;\r
+       }\r
+\r
+       @Override\r
+       public Response notify(AuthzTrans trans, Notify type, String url, String[] identities, String[] ccs, String summary, Boolean urgent) {\r
+               String system = trans.getProperty("CASS_ENV", "");\r
+\r
+               ArrayList<String> toList = new ArrayList<String>();\r
+               Identity identity;\r
+               if (identities != null) {\r
+                       for (String user : identities) {\r
+                               try {\r
+                                       identity = getIdentity(trans, user);\r
+                                       if (identity == null) {\r
+                                               trans.error().log(\r
+                                                               "Failure to obtain User " + user + " for "\r
+                                                                               + getName());\r
+                                       } else {\r
+                                               toList.add(identity.email());\r
+                                       }\r
+                               } catch (Exception e) {\r
+                                       trans.error().log(\r
+                                                       e,\r
+                                                       "Failure to obtain User " + user + " for "\r
+                                                                       + getName());\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (toList.isEmpty()) {\r
+                       trans.error().log("No Users listed to email");\r
+                       return Response.ERR_NotificationFailure;\r
+               }\r
+\r
+               ArrayList<String> ccList = new ArrayList<String>();\r
+\r
+               // If we're sending an urgent email, CC the user's supervisor\r
+               //\r
+               if (urgent) {\r
+                       trans.info().log("urgent msg for: " + identities[0]);\r
+                       try {\r
+                               List<Identity> supervisors = getApprovers(trans, identities[0]);\r
+                               for (Identity us : supervisors) {\r
+                                       trans.info().log("supervisor: " + us.email());\r
+                                       ccList.add(us.email());\r
+                               }\r
+                       } catch (Exception e) {\r
+                               trans.error().log(e,\r
+                                               "Failed to find supervisor for  " + identities[0]);\r
+                       }\r
+               }\r
+\r
+               if (ccs != null) {\r
+                       for (String user : ccs) {\r
+                               try {\r
+                                       identity = getIdentity(trans, user);\r
+                                       ccList.add(identity.email());\r
+                               } catch (Exception e) {\r
+                                       trans.error().log(\r
+                                                       e,\r
+                                                       "Failure to obtain User " + user + " for "\r
+                                                                       + getName());\r
+                               }\r
+                       }\r
+               }\r
+\r
+               if (summary == null) {\r
+                       summary = "";\r
+               }\r
+\r
+               switch (type) {\r
+               case Approval:\r
+                       try {\r
+                               sendEmail(trans, toList, ccList,\r
+                                               "AAF Approval Notification "\r
+                                                               + (system.length() == 0 ? "" : "(ENV: "\r
+                                                                               + system + ")"),\r
+                                               "AAF is the "\r
+                                               + NAME\r
+                                               + "System for Fine-Grained Authorizations.  You are being asked to Approve"\r
+                                                               + (system.length() == 0 ? "" : " in the "\r
+                                                                               + system + " environment")\r
+                                                               + " before AAF Actions can be taken.\n\n"\r
+                                                               + "Please follow this link: \n\n\t" + url\r
+                                                               + "\n\n" + summary, urgent);\r
+                       } catch (Exception e) {\r
+                               trans.error().log(e, "Failure to send Email");\r
+                               return Response.ERR_NotificationFailure;\r
+                       }\r
+                       break;\r
+               case PasswordExpiration:\r
+                       try {\r
+                               sendEmail(trans,\r
+                                               toList,\r
+                                               ccList,\r
+                                               "AAF Password Expiration Warning "\r
+                                                               + (system.length() == 0 ? "" : "(ENV: "\r
+                                                                               + system + ")"),\r
+                                               "AAF is the "\r
+                                               + NAME\r
+                                               + " System for Authorizations.\n\nOne or more passwords will expire soon or have expired"\r
+                                                               + (system.length() == 0 ? "" : " in the "\r
+                                                                               + system + " environment")\r
+                                                               + ".\n\nPasswords expired for more than 30 days without action are subject to deletion.\n\n"\r
+                                                               + "Please follow each link to add a New Password with Expiration Date. Either are valid until expiration. "\r
+                                                               + "Use this time to change the passwords on your system. If issues, reply to this email.\n\n"\r
+                                                               + summary, urgent);\r
+                       } catch (Exception e) {\r
+                               trans.error().log(e, "Failure to send Email");\r
+                               return Response.ERR_NotificationFailure;\r
+                       }\r
+                       break;\r
+\r
+               case RoleExpiration:\r
+                       try {\r
+                               sendEmail(\r
+                                               trans,\r
+                                               toList,\r
+                                               ccList,\r
+                                               "AAF Role Expiration Warning "\r
+                                                               + (system.length() == 0 ? "" : "(ENV: "\r
+                                                                               + system + ")"),\r
+                                               "AAF is the "\r
+                                               + NAME\r
+                                               + " System for Authorizations. One or more roles will expire soon"\r
+                                                               + (system.length() == 0 ? "" : " in the "\r
+                                                                               + system + " environment")\r
+                                                               + ".\n\nRoles expired for more than 30 days are subject to deletion."\r
+                                                               + "Please follow this link the GUI Command line, and either 'extend' or 'del' the user in the role.\n"\r
+                                                               + "If issues, reply to this email.\n\n\t" + url\r
+                                                               + "\n\n" + summary, urgent);\r
+                       } catch (Exception e) {\r
+                               trans.error().log(e, "Failure to send Email");\r
+                               return Response.ERR_NotificationFailure;\r
+                       }\r
+                       break;\r
+               default:\r
+                       return Response.ERR_NotImplemented;\r
+               }\r
+               return Response.OK;\r
+       }\r
+\r
+       @Override\r
+       public int sendEmail(AuthzTrans trans, List<String> toList, List<String> ccList, String subject, String body,\r
+                       Boolean urgent) throws OrganizationException {\r
+               int status = 1;\r
+               \r
+               List<String> to = new ArrayList<String>();\r
+               for(String em : toList) {\r
+                       if(em.indexOf('@')<0) {\r
+                               to.add(new DefaultOrgIdentity(trans, em, this).email());\r
+                       } else {\r
+                               to.add(em);\r
+                       }\r
+               }\r
+               \r
+               List<String> cc = new ArrayList<String>();\r
+               if(ccList!=null && !ccList.isEmpty()) {\r
+                       for(String em : ccList) {\r
+                               if(em.indexOf('@')<0) {\r
+                                       cc.add(new DefaultOrgIdentity(trans, em, this).email());\r
+                               } else {\r
+                                       cc.add(em);\r
+                               }\r
+                       }\r
+               }\r
+               \r
+       \r
+               // for now, I want all emails so we can see what goes out. Remove later\r
+               if (!ccList.contains(supportAddress)) {\r
+                       ccList.add(supportAddress);\r
+               }\r
+\r
+               try {\r
+                       // Create a default MimeMessage object.\r
+                       MimeMessage message = new MimeMessage(session);\r
+\r
+                       // Set From: header field of the header.\r
+                       message.setFrom(new InternetAddress(mailFromUserId));\r
+\r
+                       if (!dryRun) {\r
+                               // Set To: header field of the header. This is a required field\r
+                               // and calling module should make sure that it is not null or\r
+                               // blank\r
+                               message.addRecipients(Message.RecipientType.TO,\r
+                                               getAddresses(to));\r
+\r
+                               // Set CC: header field of the header.\r
+                               if ((ccList != null) && (ccList.size() > 0)) {\r
+                                       message.addRecipients(Message.RecipientType.CC,\r
+                                                       getAddresses(cc));\r
+                               }\r
+\r
+                               // Set Subject: header field\r
+                               message.setSubject(subject);\r
+\r
+                               if (urgent) {\r
+                                       message.addHeader("X-Priority", "1");\r
+                               }\r
+\r
+                               // Now set the actual message\r
+                               message.setText(body);\r
+                       } else {\r
+                               // override recipients\r
+                               message.addRecipients(Message.RecipientType.TO,\r
+                                               InternetAddress.parse(supportAddress));\r
+\r
+                               // Set Subject: header field\r
+                               message.setSubject("[TESTMODE] " + subject);\r
+\r
+                               if (urgent) {\r
+                                       message.addHeader("X-Priority", "1");\r
+                               }\r
+\r
+                               ArrayList<String> newBody = new ArrayList<String>();\r
+\r
+                               Address temp[] = getAddresses(to);\r
+                               String headerString = "TO:\t" + InternetAddress.toString(temp)\r
+                                               + "\n";\r
+\r
+                               temp = getAddresses(cc);\r
+                               headerString += "CC:\t" + InternetAddress.toString(temp) + "\n";\r
+\r
+                               newBody.add(headerString);\r
+\r
+                               newBody.add("Text: \n");\r
+\r
+                               newBody.add(body);\r
+                               String outString = "";\r
+                               for (String s : newBody) {\r
+                                       outString += s + "\n";\r
+                               }\r
+\r
+                               message.setText(outString);\r
+                       }\r
+                       // Send message\r
+                       Transport.send(message);\r
+                       status = 0;\r
+\r
+               } catch (MessagingException mex) {\r
+                       throw new OrganizationException("Exception send email message "\r
+                                       + mex.getMessage());\r
+               }\r
+\r
+               return status;  \r
+       }\r
+\r
+       /**\r
+        * Default Policy is to set to 6 Months for Notification Types.\r
+        * add others/change as required\r
+        */\r
+       @Override\r
+       public Date whenToValidate(Notify type, Date lastValidated) {\r
+               switch(type) {\r
+                       case Approval:\r
+                       case PasswordExpiration:\r
+                               return null;\r
+                       default:\r
+                               GregorianCalendar gc = new GregorianCalendar();\r
+                               gc.setTime(lastValidated);\r
+                               gc.add(GregorianCalendar.MONTH, 6);  // 6 month policy\r
+                               return gc.getTime();\r
+               }\r
+       }\r
+\r
+       @Override\r
+       public GregorianCalendar expiration(GregorianCalendar gc, Expiration exp, String... extra) {\r
+        GregorianCalendar rv = gc==null?new GregorianCalendar():(GregorianCalendar)gc.clone();\r
+               switch (exp) {\r
+                       case ExtendPassword:\r
+                               // Extending Password give 5 extra days\r
+                               rv.add(GregorianCalendar.DATE, 5);\r
+                               break;\r
+                       case Future:\r
+                               // Future Requests last 15 days before subject to deletion.\r
+                               rv.add(GregorianCalendar.DATE, 15);\r
+                               break;\r
+                       case Password:\r
+                               // Passwords expire in 90 days\r
+                               rv.add(GregorianCalendar.DATE, 90);\r
+                               break;\r
+                       case TempPassword:\r
+                               // Temporary Passwords last for 12 hours.\r
+                               rv.add(GregorianCalendar.HOUR, 12);\r
+                               break;\r
+                       case UserDelegate:\r
+                               // Delegations expire max in 2 months\r
+                               rv.add(GregorianCalendar.MONTH, 2);\r
+                               break;\r
+                       case UserInRole:\r
+                               // Roles expire in 6 months\r
+                               rv.add(GregorianCalendar.MONTH, 6);\r
+                               break;\r
+                       default:\r
+                               // Unless other wise set, 6 months is default\r
+                               rv.add(GregorianCalendar.MONTH, 6);\r
+                               break;\r
+               }\r
+               return rv;\r
+       }\r
+\r
+       @Override\r
+       public EmailWarnings emailWarningPolicy() {\r
+               return emailWarnings;\r
+       }\r
+\r
+       /**\r
+        * Assume the Supervisor is the Approver.\r
+        */\r
+       @Override\r
+       public List<Identity> getApprovers(AuthzTrans trans, String user) throws OrganizationException {\r
+               Identity orgIdentity = getIdentity(trans, user);\r
+               List<Identity> orgIdentitys = new ArrayList<Identity>();\r
+               if(orgIdentity!=null) {\r
+                       String supervisorID = orgIdentity.responsibleTo();\r
+                       if (supervisorID.indexOf('@') < 0) {\r
+                           supervisorID += getDomain();\r
+                       }\r
+                       Identity supervisor = getIdentity(trans, supervisorID);\r
+                       orgIdentitys.add(supervisor);\r
+               }\r
+               return orgIdentitys;    \r
+       }\r
+\r
+       @Override\r
+       public String getApproverType() {\r
+               return "supervisor";\r
+       }\r
+\r
+       @Override\r
+       public int startOfDay() {\r
+               // TODO Auto-generated method stub\r
+               return 0;\r
+       }\r
+\r
+       @Override\r
+       public boolean canHaveMultipleCreds(String id) {\r
+               // External entities are likely mono-password... if you change it, it is a global change.\r
+               // This is great for people, but horrible for Applications.  \r
+               //\r
+               // AAF's Password can have multiple Passwords, each with their own Expiration Date.\r
+               // For Default Org, we'll assume true for all, but when you add your external\r
+               // Identity stores, you need to return "false" if they cannot support multiple Passwords like AAF\r
+               return true;\r
+       }\r
+\r
+       @Override\r
+       public boolean isValidCred(String id) {\r
+               if(id.endsWith(SUFFIX)) {\r
+                       return true;\r
+               }\r
+               return id.matches(ID_PATTERN);\r
+       }\r
+\r
+       @Override\r
+       public String validate(AuthzTrans trans, Policy policy, Executor executor, String... vars) throws OrganizationException {\r
+               switch(policy) {\r
+                       case OWNS_MECHID:\r
+                       case CREATE_MECHID:\r
+                               if(vars.length>0) {\r
+                                       Identity requestor = getIdentity(trans, trans.user());\r
+                                       if(requestor!=null) {\r
+                                               Identity mechid = getIdentity(trans, vars[0]);\r
+                                               if(requestor.equals(mechid.owner())) {\r
+                                                       return null;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               return trans.user() + " is not the Sponsor of MechID " + vars[0];\r
+                               \r
+                       case CREATE_MECHID_BY_PERM_ONLY:\r
+                               return getName() + " only allows sponsors to create MechIDs";\r
+                               \r
+                       default:\r
+                               return policy.name() + " is unsupported at " + getName();\r
+               }       \r
+       }\r
+\r
+       @Override\r
+       public boolean isTestEnv() {\r
+               return false;\r
+       }\r
+\r
+       @Override\r
+       public void setTestMode(boolean dryRun) {\r
+               this.dryRun = dryRun;\r
+       }\r
+\r
+       /**\r
+        * Convert the delimiter String into Internet addresses with the default\r
+        * delimiter of ";"\r
+        * @param strAddress\r
+        * @return\r
+        */\r
+       private Address[] getAddresses(List<String> strAddress) throws OrganizationException {\r
+               return this.getAddresses(strAddress,";");\r
+       }\r
+       /**\r
+        * Convert the delimiter String into Internet addresses with the \r
+        * delimiter of provided\r
+        * @param strAddress\r
+        * @param delimiter\r
+        * @return\r
+        */\r
+       private Address[] getAddresses(List<String> strAddresses, String delimiter) throws OrganizationException {\r
+               Address[] addressArray = new Address[strAddresses.size()];\r
+               int count = 0;\r
+               for (String addr : strAddresses)\r
+               {\r
+            try{\r
+               addressArray[count] = new InternetAddress(addr);\r
+               count++;\r
+            }catch(Exception e){\r
+               throw new OrganizationException("Failed to parse the email address "+ addr +": "+e.getMessage());\r
+            }\r
+        }\r
+        return addressArray;\r
+       }\r
+}\r