Add new JUnit Structure 21/92321/2
authorInstrumental <jonathan.gathman@att.com>
Tue, 30 Jul 2019 22:02:46 +0000 (17:02 -0500)
committerInstrumental <jonathan.gathman@att.com>
Tue, 30 Jul 2019 22:17:42 +0000 (17:17 -0500)
Issue-ID: AAF-902
Change-Id: I5d13132cedb6b0dae115c160c68c42f2d85277c3
Signed-off-by: Instrumental <jonathan.gathman@att.com>
auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java
auth/auth-gui/theme/onap/images/ONAP_LOGO.png
auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java
auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_BaseServiceImpl.java [new file with mode: 0644]
auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_ServiceImpl_createUserCred.java [new file with mode: 0644]

index 3b61da3..6b6c23b 100644 (file)
@@ -224,6 +224,31 @@ public class Question {
         
         alwaysSpecial = Boolean.parseBoolean(trans.getProperty("aaf_always_special", Boolean.FALSE.toString()));
     }
+    
+    /**
+     * Note: This Constructor created for JUNIT Purposes.  Do not use otherwise.
+     */
+    public Question(AuthzTrans trans, HistoryDAO historyDAO, CacheInfoDAO cacheInfoDAO,
+               CachedNSDAO nsDAO, CachedPermDAO permDAO, CachedRoleDAO roleDAO,
+               CachedUserRoleDAO userRoleDAO, CachedCredDAO credDAO, CachedCertDAO certDAO,
+               LocateDAO locateDAO,FutureDAO futureDAO, DelegateDAO delegateDAO,
+               ApprovalDAO approvalDAO ) {
+       this.historyDAO = historyDAO;
+       this.cacheInfoDAO = cacheInfoDAO;
+       this.nsDAO = nsDAO;
+       this.permDAO = permDAO;
+       this.roleDAO = roleDAO;
+       this.userRoleDAO = userRoleDAO;
+       this.credDAO = credDAO;
+       this.certDAO = certDAO;
+        this.locateDAO = locateDAO;
+        this.futureDAO = futureDAO;
+        this.delegateDAO = delegateDAO;
+        this.approvalDAO = approvalDAO;
+
+        cldays = Integer.parseInt(trans.getProperty(Config.AAF_CRED_WARN_DAYS, Config.AAF_CRED_WARN_DAYS_DFT));
+        alwaysSpecial = Boolean.parseBoolean(trans.getProperty("aaf_always_special", Boolean.FALSE.toString()));
+    }
 
     public void startTimers(AuthzEnv env) {
         // Only want to aggressively cleanse User related Caches... The others,
@@ -987,25 +1012,27 @@ public class Question {
     }
     
     public Result<Boolean> userCredCheck(AuthzTrans trans, CredDAO.Data orig, final byte[] raw) {
-            TimeTaken tt = trans.start("CheckCred Cred", Env.SUB);
-            try {
-                switch(orig.type) {
-                    case CredDAO.BASIC_AUTH_SHA256:
-                        ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + raw.length);
-                        bb.putInt(orig.other);
-                        bb.put(raw);
-                        return Result.ok(Hash.compareTo(orig.cred.array(),Hash.hashSHA256(bb.array()))==0);
-                    case CredDAO.BASIC_AUTH:
-                        return Result.ok( Hash.compareTo(orig.cred.array(), Hash.hashMD5(raw))==0);
-                    case CredDAO.FQI:
-                    default:
-                        return Result.ok(false);
-                }
-            } catch (NoSuchAlgorithmException e) {
-                return Result.err(Status.ERR_General,e.getLocalizedMessage());
-            } finally {
-                tt.done();
+       Result<Boolean> rv;
+        TimeTaken tt = trans.start("CheckCred Cred", Env.SUB);
+        try {
+            switch(orig.type) {
+                case CredDAO.BASIC_AUTH_SHA256:
+                    ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + raw.length);
+                    bb.putInt(orig.other);
+                    bb.put(raw);
+                    rv = Result.ok(Hash.compareTo(orig.cred.array(),Hash.hashSHA256(bb.array()))==0);
+                case CredDAO.BASIC_AUTH:
+                    rv= Result.ok( Hash.compareTo(orig.cred.array(), Hash.hashMD5(raw))==0);
+                case CredDAO.FQI:
+                default:
+                    rv = Result.ok(false);
             }
+        } catch (NoSuchAlgorithmException e) {
+            rv = Result.err(Status.ERR_General,e.getLocalizedMessage());
+        } finally {
+            tt.done();
+        }
+        return rv;
     }
 
     public static final String APPROVED = "APPROVE";
@@ -1214,7 +1241,7 @@ public class Question {
     }
     
     public boolean isOwner(AuthzTrans trans, String user, String ns) {
-        Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);
+        Result<List<UserRoleDAO.Data>> rur = userRoleDAO().read(trans, user,ns+DOT_OWNER);
         if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){
             Date now = new Date();
             if (urdd.expires.after(now)) {
@@ -1225,7 +1252,7 @@ public class Question {
     }
 
     public int countOwner(AuthzTrans trans, String ns) {
-        Result<List<UserRoleDAO.Data>> rur = userRoleDAO.readByRole(trans,ns+DOT_OWNER);
+        Result<List<UserRoleDAO.Data>> rur = userRoleDAO().readByRole(trans,ns+DOT_OWNER);
         Date now = new Date();
         int count = 0;
         if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){
index 458e320..55e3718 100644 (file)
Binary files a/auth/auth-gui/theme/onap/images/ONAP_LOGO.png and b/auth/auth-gui/theme/onap/images/ONAP_LOGO.png differ
index 295db4a..b57b070 100644 (file)
@@ -42,6 +42,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -2442,8 +2443,14 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                                    return Result.err(rb);
                                } else if (rb.value){
                                    return Result.err(Status.ERR_Policy, "Credential content cannot be reused.");
-                               } else if ((Chrono.dateOnlyStamp(curr.expires).equals(Chrono.dateOnlyStamp(rcred.value.expires)) && curr.type==rcred.value.type)) {
-                                   return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists");
+                               } else if(Chrono.dateOnlyStamp(curr.expires).equals(Chrono.dateOnlyStamp(rcred.value.expires)) 
+                                               && curr.type==rcred.value.type 
+                                               ) {
+                                       // Allow if expiring differential is greater than 1 day (for TEMP)
+                                       // Unless expiring in 1 day
+                                       if(System.currentTimeMillis() - rcred.value.expires.getTime() > TimeUnit.DAYS.toMillis(1)) {
+                                               return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists");
+                                       }
                                }
                        }
                     }    
@@ -2501,13 +2508,20 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                     case Status.ACC_Now:
                         try {
                             if (firstID) {
-    //                            && !nsr.value.get(0).isAdmin(trans.getUserPrincipal().getName())) {
-                                Result<List<String>> admins = func.getAdmins(trans, nsr.value.get(0).name, false);
-                                // OK, it's a first ID, and not by NS Admin, so let's set TempPassword length
-                                // Note, we only do this on First time, because of possibility of 
-                                // prematurely expiring a production id
-                                if (admins.isOKhasData() && !admins.value.contains(trans.user())) {
-                                    rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime();
+                                // OK, it's a first ID, and not by NS Owner
+                                if(!ques.isOwner(trans,trans.user(),cdd.ns)) {
+                                       // Admins are not allowed to set first Cred, but Org has already
+                                       // said entity MAY create, typically by Permission
+                                       // We can't know which reason they are allowed here, so we 
+                                       // have to assume that any with Special Permission would not be 
+                                       // an Admin.
+                                       if(ques.isAdmin(trans, trans.user(), cdd.ns)) {
+                                               return Result.err(Result.ERR_Denied, 
+                                                       "Only Owners may create first passwords in their Namespace. Admins may modify after one exists" );
+                                       } else {
+                                               // Allow IDs that AREN'T part of NS with Org Onboarding Permission  (see Org object) to create Temp Passwords.
+                                        rcred.value.expires = org.expiration(null, Expiration.TempPassword).getTime();
+                                       }
                                 }
                             }
                         } catch (Exception e) {
diff --git a/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_BaseServiceImpl.java b/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_BaseServiceImpl.java
new file mode 100644 (file)
index 0000000..c9ebc28
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * ============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.service.test;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.common.Define;
+import org.onap.aaf.auth.dao.cached.CachedCertDAO;
+import org.onap.aaf.auth.dao.cached.CachedCredDAO;
+import org.onap.aaf.auth.dao.cached.CachedNSDAO;
+import org.onap.aaf.auth.dao.cached.CachedPermDAO;
+import org.onap.aaf.auth.dao.cached.CachedRoleDAO;
+import org.onap.aaf.auth.dao.cached.CachedUserRoleDAO;
+import org.onap.aaf.auth.dao.cass.ApprovalDAO;
+import org.onap.aaf.auth.dao.cass.CacheInfoDAO;
+import org.onap.aaf.auth.dao.cass.DelegateDAO;
+import org.onap.aaf.auth.dao.cass.FutureDAO;
+import org.onap.aaf.auth.dao.cass.HistoryDAO;
+import org.onap.aaf.auth.dao.cass.LocateDAO;
+import org.onap.aaf.auth.dao.cass.NsDAO;
+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.service.AuthzCassServiceImpl;
+import org.onap.aaf.auth.service.mapper.Mapper_2_0;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.org.DefaultOrg;
+import org.onap.aaf.org.DefaultOrgIdentity;
+
+import aaf.v2_0.Approvals;
+import aaf.v2_0.Certs;
+import aaf.v2_0.Delgs;
+import aaf.v2_0.Error;
+import aaf.v2_0.History;
+import aaf.v2_0.Keys;
+import aaf.v2_0.Nss;
+import aaf.v2_0.Perms;
+import aaf.v2_0.Pkey;
+import aaf.v2_0.Request;
+import aaf.v2_0.Roles;
+import aaf.v2_0.UserRoles;
+import aaf.v2_0.Users;
+
+@RunWith(MockitoJUnitRunner.class)
+public abstract class JU_BaseServiceImpl {
+       protected AuthzCassServiceImpl<Nss, Perms, Pkey, Roles, Users, UserRoles, Delgs, Certs, Keys, Request, History, Error, Approvals> 
+               acsi;
+       protected Mapper_2_0 mapper;
+       
+    @Mock
+    protected DefaultOrg org;
+    @Mock
+    protected DefaultOrgIdentity orgIdentity;
+       
+    protected HistoryDAO historyDAO = mock(HistoryDAO.class);
+    protected CacheInfoDAO cacheInfoDAO = mock(CacheInfoDAO.class);
+    protected CachedNSDAO nsDAO = mock(CachedNSDAO.class);
+    protected CachedPermDAO permDAO = mock(CachedPermDAO.class);
+    protected CachedRoleDAO roleDAO = mock(CachedRoleDAO.class);
+    protected CachedUserRoleDAO userRoleDAO = mock(CachedUserRoleDAO.class);
+    protected CachedCredDAO credDAO = mock(CachedCredDAO.class);
+    protected CachedCertDAO certDAO = mock(CachedCertDAO.class);
+    protected LocateDAO locateDAO = mock(LocateDAO.class);
+    protected FutureDAO futureDAO = mock(FutureDAO.class);
+    protected DelegateDAO delegateDAO = mock(DelegateDAO.class);
+    protected ApprovalDAO approvalDAO = mock(ApprovalDAO.class);
+       
+    @Spy
+    protected static PropAccess access = new PropAccess();
+    
+    @Spy
+       protected static AuthzEnv env = new AuthzEnv(access);
+       
+    @Spy
+    protected static AuthzTrans trans = env.newTransNoAvg();
+    
+
+    @Spy
+    protected Question question = new Question(trans,historyDAO,cacheInfoDAO,nsDAO,permDAO,roleDAO,userRoleDAO,
+               credDAO,certDAO,locateDAO,futureDAO,delegateDAO,approvalDAO);
+    
+       public void setUp() throws Exception {
+           when(trans.org()).thenReturn(org);
+           when(org.getDomain()).thenReturn("org.onap");
+           Define.set(access);
+               access.setProperty(Config.CADI_LATITUDE, "38.0");
+               access.setProperty(Config.CADI_LONGITUDE, "-72.0");
+
+           mapper = new Mapper_2_0(question);
+               acsi = new AuthzCassServiceImpl<>(trans, mapper, question);
+       }
+       
+       //////////
+       //  Common Data Objects
+       /////////
+    protected List<NsDAO.Data> nsData(String name) {
+       NsDAO.Data ndd = new NsDAO.Data();
+       ndd.name=name;
+       int dot = name.lastIndexOf('.');
+       if(dot<0) {
+               ndd.parent=".";
+       } else {
+               ndd.parent=name.substring(0,dot);
+       }
+       List<NsDAO.Data> rv = new ArrayList<NsDAO.Data>();
+       rv.add(ndd);
+       return rv;
+    }
+    
+    protected UserRoleDAO.Data urData(String user, String ns, String rname, int days) {
+       UserRoleDAO.Data urdd = new UserRoleDAO.Data();
+       urdd.user = user;
+       urdd.ns = ns;
+       urdd.rname = rname;
+       urdd.role = ns + '.' + rname;
+       GregorianCalendar gc = new GregorianCalendar();
+       gc.add(GregorianCalendar.DAY_OF_YEAR, days);
+       urdd.expires = gc.getTime();
+       return urdd;
+    }
+
+
+    protected <T> List<T> listOf(T t) {
+       List<T> list = new ArrayList<>();
+       list.add(t);
+       return list;
+    }
+    
+    protected <T> List<T> emptyList(Class<T> cls) {
+       return new ArrayList<>();
+    }
+
+}
diff --git a/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_ServiceImpl_createUserCred.java b/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_ServiceImpl_createUserCred.java
new file mode 100644 (file)
index 0000000..1e4e971
--- /dev/null
@@ -0,0 +1,148 @@
+/**
+ * ============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.service.test;
+
+import static org.mockito.Mockito.*;
+
+import java.nio.ByteBuffer;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.dao.CachedDAO;
+import org.onap.aaf.auth.dao.cass.CredDAO;
+import org.onap.aaf.auth.dao.cass.UserRoleDAO;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.cadi.Hash;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.misc.env.Trans;
+
+import aaf.v2_0.CredRequest;
+import junit.framework.Assert;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_ServiceImpl_createUserCred extends JU_BaseServiceImpl  {
+       @Mock 
+    private Result<CredDAO.Data> rcdd; 
+       
+       @Before
+       public void setUp() throws Exception {
+           super.setUp();
+       }
+
+    @Test
+    public void validCreateNewIsOwner() throws OrganizationException {
+       CredRequest cr = credRequest1();
+       final String fqi = "bob@people.onap.org";
+       when(trans.user()).thenReturn(fqi);
+       when(org.isValidPassword(trans, cr.getId(),cr.getPassword())).thenReturn("");
+       when(org.isValidCred(trans, cr.getId())).thenReturn(true);
+       when(org.canHaveMultipleCreds(cr.getId())).thenReturn(true);
+               when(org.getIdentity(trans, cr.getId())).thenReturn(orgIdentity);
+               when(orgIdentity.isFound()).thenReturn(true);
+               final String ns = "org.onap.sample";
+           when(question.userRoleDAO().read(trans, fqi, ns+".owner")).thenReturn(Result.ok(listOf(urData(fqi,ns,"owner",100))));
+           when(question.nsDAO().read(trans, ns)).thenReturn(Result.ok(nsData(ns)));
+           when(question.credDAO().readID(trans, cr.getId())).thenReturn(Result.ok(emptyList(CredDAO.Data.class)));
+           when(question.credDAO().create(any(AuthzTrans.class), any(CredDAO.Data.class) )).thenReturn(Result.ok(credDataFound(cr,100)));
+           when(question.credDAO().readNS(trans, ns)).thenReturn(Result.ok(listOf(credDataFound(cr,100))));
+           Result<?> result = acsi.createUserCred(trans,cr);
+           // Owner may do FIRST Creds
+       Assert.assertEquals(Result.OK,result.status);
+    }
+
+    @Test
+    public void validCreateNewOnlyAdmin() throws OrganizationException {
+       CredRequest cr = credRequest1();
+       final String fqi = "bob@people.onap.org";
+       when(trans.user()).thenReturn(fqi);
+       when(org.isValidPassword(trans, cr.getId(),cr.getPassword())).thenReturn("");
+       when(org.isValidCred(trans, cr.getId())).thenReturn(true);
+       when(org.canHaveMultipleCreds(cr.getId())).thenReturn(true);
+               when(org.getIdentity(trans, cr.getId())).thenReturn(orgIdentity);
+               when(orgIdentity.isFound()).thenReturn(true);
+               final String ns = "org.onap.sample";
+           when(question.userRoleDAO().read(trans, fqi, ns+".owner")).thenReturn(Result.ok(emptyList(UserRoleDAO.Data.class)));
+           when(question.userRoleDAO().read(trans, fqi, ns+".admin")).thenReturn(Result.ok(listOf(urData(fqi,ns,"admin",100))));
+           when(question.nsDAO().read(trans, ns)).thenReturn(Result.ok(nsData(ns)));
+           when(question.credDAO().readID(trans, cr.getId())).thenReturn(Result.ok(emptyList(CredDAO.Data.class)));
+           when(question.credDAO().create(any(AuthzTrans.class), any(CredDAO.Data.class) )).thenReturn(Result.ok(credDataFound(cr,100)));
+           when(question.credDAO().readNS(trans, ns)).thenReturn(Result.ok(listOf(credDataFound(cr,100))));
+           Result<?> result = acsi.createUserCred(trans,cr);
+           // Admins may not do FIRST Creds
+       Assert.assertEquals(Result.ERR_Denied,result.status);
+    }
+
+    @Test
+    public void validCreateExisting() throws OrganizationException {
+       CredRequest cr = credRequest1();
+       when(org.isValidPassword(trans, cr.getId(),cr.getPassword())).thenReturn("");
+       when(org.isValidCred(trans, cr.getId())).thenReturn(true);
+       when(org.canHaveMultipleCreds(cr.getId())).thenReturn(true);
+               when(org.getIdentity(trans, cr.getId())).thenReturn(orgIdentity);
+               when(orgIdentity.isFound()).thenReturn(true);
+               String ns = "org.onap.sample";
+           when(question.nsDAO().read(trans, ns)).thenReturn(Result.ok(nsData(ns)));
+           
+           CredDAO.Data cdd = credDataFound(cr,100);
+           when(question.credDAO().create(any(AuthzTrans.class), any(CredDAO.Data.class) )).thenReturn(Result.ok(cdd));
+           when(question.credDAO().readID(trans, cr.getId())).thenReturn(Result.ok(listOf(cdd)));
+
+           Result<?> result = acsi.createUserCred(trans,cr);
+       Assert.assertEquals(Result.OK,result.status);
+    }
+
+    private CredRequest credRequest1() {
+       CredRequest cr = new CredRequest();
+       cr.setId("m12345@sample.onap.org");
+       cr.setPassword("BobAndWeave");
+       cr.setType(CredDAO.RAW);
+       return cr;
+    }
+    
+   private CredDAO.Data credDataFound(CredRequest cr, int days) {
+       CredDAO.Data cdd = new CredDAO.Data();
+       cdd.id = cr.getId();
+       cdd.ns = FQI.reverseDomain(cr.getId());
+       cdd.other = 12345;
+       cdd.tag = "1355434";
+       cdd.type = CredDAO.BASIC_AUTH_SHA256;
+       try {
+                       cdd.cred = ByteBuffer.wrap(Hash.hashSHA256(cr.getPassword().getBytes()));
+               } catch (NoSuchAlgorithmException e) {
+                       Assert.fail(e.getMessage());
+               }
+       GregorianCalendar gc = new GregorianCalendar();
+       gc.add(GregorianCalendar.DAY_OF_YEAR, days);
+       cdd.expires = gc.getTime();
+       return cdd;
+    }
+    
+}
\ No newline at end of file