From b3814beaec2b6f439ffb7af1594e70b5339a9e5f Mon Sep 17 00:00:00 2001 From: Instrumental Date: Tue, 30 Jul 2019 17:02:46 -0500 Subject: Add new JUnit Structure Issue-ID: AAF-902 Change-Id: I5d13132cedb6b0dae115c160c68c42f2d85277c3 Signed-off-by: Instrumental --- .../java/org/onap/aaf/auth/dao/hl/Question.java | 67 ++++++--- auth/auth-gui/theme/onap/images/ONAP_LOGO.png | Bin 11349 -> 24268 bytes .../aaf/auth/service/AuthzCassServiceImpl.java | 32 ++-- .../aaf/auth/service/test/JU_BaseServiceImpl.java | 162 +++++++++++++++++++++ .../test/JU_ServiceImpl_createUserCred.java | 148 +++++++++++++++++++ 5 files changed, 380 insertions(+), 29 deletions(-) create mode 100644 auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_BaseServiceImpl.java create mode 100644 auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_ServiceImpl_createUserCred.java diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java index 3b61da31..6b6c23bf 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java @@ -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 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 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> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER); + Result> 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> rur = userRoleDAO.readByRole(trans,ns+DOT_OWNER); + Result> rur = userRoleDAO().readByRole(trans,ns+DOT_OWNER); Date now = new Date(); int count = 0; if (rur.isOKhasData()) {for (UserRoleDAO.Data urdd : rur.value){ diff --git a/auth/auth-gui/theme/onap/images/ONAP_LOGO.png b/auth/auth-gui/theme/onap/images/ONAP_LOGO.png index 458e320c..55e37188 100644 Binary files a/auth/auth-gui/theme/onap/images/ONAP_LOGO.png and b/auth/auth-gui/theme/onap/images/ONAP_LOGO.png differ diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java index 295db4ac..b57b0708 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java @@ -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 TimeUnit.DAYS.toMillis(1)) { + return Result.err(Status.ERR_ConflictAlreadyExists, "Credential with same Expiration Date exists"); + } } } } @@ -2501,13 +2508,20 @@ public class AuthzCassServiceImpl > 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 index 00000000..c9ebc281 --- /dev/null +++ b/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_BaseServiceImpl.java @@ -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 + 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 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 rv = new ArrayList(); + 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 List listOf(T t) { + List list = new ArrayList<>(); + list.add(t); + return list; + } + + protected List emptyList(Class 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 index 00000000..1e4e9719 --- /dev/null +++ b/auth/auth-service/src/test/java/org/onap/aaf/auth/service/test/JU_ServiceImpl_createUserCred.java @@ -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 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 -- cgit 1.2.3-korg