Update DNSLocator code and use 51/89051/1
authorInstrumental <jonathan.gathman@att.com>
Fri, 31 May 2019 15:02:47 +0000 (10:02 -0500)
committerInstrumental <jonathan.gathman@att.com>
Fri, 31 May 2019 15:09:32 +0000 (10:09 -0500)
Issue-ID: AAF-838
Change-Id: Ieaf112365e40237b6f252371d2d2f95e9bc47f89
Signed-off-by: Instrumental <jonathan.gathman@att.com>
17 files changed:
auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/CredDAO.java
auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java
auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/List.java
auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ID.java [new file with mode: 0644]
auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/User.java
auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java
auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java
auth/auth-service/src/main/java/org/onap/aaf/auth/service/mapper/Mapper_2_0.java
auth/auth-service/src/main/java/org/onap/aaf/auth/service/validation/ServiceValidator.java
auth/helm/aaf/values.yaml
cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFSingleLocator.java
cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AbsAAFLocator.java
cadi/client/src/main/java/org/onap/aaf/cadi/http/HMangr.java
cadi/client/src/main/java/org/onap/aaf/cadi/locator/DNSLocator.java
cadi/client/src/test/java/org/onap/aaf/cadi/http/test/JU_HMangr.java
cadi/client/src/test/java/org/onap/aaf/cadi/locator/test/JU_DNSLocator.java
cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java

index 9c57d20..868f9ac 100644 (file)
@@ -53,6 +53,7 @@ public class CredDAO extends CassDAOImpl<AuthzTrans,CredDAO.Data> {
     public static final String TABLE = "cred";
     public static final int CACHE_SEG = 0x40; // yields segment 0x0-0x3F
     public static final int RAW = -1;
+    public static final int FQI = 0;
     public static final int BASIC_AUTH = 1;
     public static final int BASIC_AUTH_SHA256 = 2;
     public static final int CERT_SHA256_RSA =200;
@@ -225,8 +226,12 @@ public class CredDAO extends CassDAOImpl<AuthzTrans,CredDAO.Data> {
        @Override
        public Result<Data> create(AuthzTrans trans, Data data) {
                if(data.tag == null) {
-                       long l = srand.nextLong();
-                       data.tag = Long.toHexString(l);
+                       if(data.type==0) {
+                               data.tag="PlaceHolder";
+                       } else {
+                               long l = srand.nextLong();
+                               data.tag = Long.toHexString(l);
+                       }
                }
                return super.create(trans, data);
        }
index bd0c835..2c98a9b 100644 (file)
@@ -920,6 +920,9 @@ public class Question {
                 tt.done();
             }
             
+        } else if (cred.type==CredDAO.FQI) {
+               cred.cred = null;
+               return Result.ok(cred);
         }
         return Result.err(Status.ERR_Security,"invalid/unreadable credential");
     }
index 3dae0fa..42306c8 100644 (file)
@@ -163,8 +163,9 @@ public class List extends BaseCmd<NS> {
             type = 9999;
         } 
         switch(type) {
+               case 0:   return "NoCrd";
             case 1:   return "U/P";
-            case 2:      return "U/P2";
+            case 2:   return "U/P2";
             case 10:  return "Cert";
             case 200: return "x509";
             default:
diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ID.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ID.java
new file mode 100644 (file)
index 0000000..12035a1
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * ============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.cmd.user;
+
+import org.onap.aaf.auth.cmd.AAFcli;
+import org.onap.aaf.auth.cmd.Cmd;
+import org.onap.aaf.auth.cmd.Param;
+import org.onap.aaf.auth.rserv.HttpMethods;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.misc.env.APIException;
+
+import aaf.v2_0.CredRequest;
+
+public class ID extends Cmd {
+    public static final String ATTEMPT_FAILED_SPECIFICS_WITHELD = "Attempt Failed.  Specifics witheld.";
+    private static final String CRED_PATH = "/authn/cred";
+    private static final String[] options = {"add","del"};
+    public ID(User parent) {
+        super(parent,"fqi",
+                new Param(optionsToString(options),true),
+                new Param("id",true)
+        );
+    }
+
+    @Override
+    public int _exec(int _idx, final String ... args) throws CadiException, APIException, LocatorException { 
+        int idx = _idx;
+        String key = args[idx++];
+        final int option = whichOption(options,key);
+
+        final CredRequest cr = new CredRequest();
+        cr.setId(args[idx++]);
+        cr.setType(0);
+        if (args.length>idx)
+            cr.setEntry(args[idx]);
+        
+        // Set Start/End commands
+        setStartEnd(cr);
+        Integer ret = same(new Retryable<Integer>() {
+            @Override
+            public Integer code(Rcli<?> client) throws CadiException, APIException {
+                Future<CredRequest> fp=null;
+                String verb =null;
+                switch(option) {
+                    case 0:
+                        fp = client.create(
+                            CRED_PATH, 
+                            getDF(CredRequest.class), 
+                            cr
+                            );
+                        verb = "Added ID [";
+                        break;
+                    case 1:
+                        setQueryParamsOn(client);
+                        fp = client.delete(CRED_PATH,
+                            getDF(CredRequest.class),
+                            cr
+                            );
+                        verb = "Deleted ID [";
+                        break;
+                    default:
+                        break;
+                }
+                if (fp==null) {
+                    return null; // get by Sonar check.
+                }
+                if (fp.get(AAFcli.timeout())) {
+                    pw().print(verb);
+                    pw().print(cr.getId());
+                    pw().println(']');
+                } else if (fp.code()==202) {
+                        pw().println("ID Action Accepted, but requires Approvals before actualizing");
+                } else if (fp.code()==406 && option==1) {
+                        pw().println("You cannot delete this ID");
+                } else {
+                    pw().println(ATTEMPT_FAILED_SPECIFICS_WITHELD);
+                }
+                return fp.code();
+            }
+        });
+        if (ret==null)ret = -1;
+        return ret;
+    }
+    
+    @Override
+    public void detailedHelp(int _indent, StringBuilder sb) {
+            int indent = _indent;
+        detailLine(sb,indent,"Add or Delete Fully Qualified Identity: An ID attached to the Namespace");
+        indent+=2;
+        detailLine(sb,indent,"fqi      - the ID to create/delete within AAF");
+        sb.append('\n');
+        detailLine(sb,indent,"This usage has NO Credential, and serves only to allow IDs to be attached");
+        detailLine(sb,indent,"to Roles before credentials such as Certificates are established.");
+        detailLine(sb,indent,"The Domain can be related to any Namespace you have access to *");
+        detailLine(sb,indent,"The Domain is in reverse order of Namespace, i.e. ");
+        detailLine(sb,indent+2,"NS of com.att.myapp can create user of XY1234@myapp.att.com");
+        indent-=2;
+        api(sb,indent,HttpMethods.POST,"authn/cred",CredRequest.class,true);
+        api(sb,indent,HttpMethods.DELETE,"authn/cred",CredRequest.class,false);
+        api(sb,indent,HttpMethods.PUT,"authn/cred",CredRequest.class,false);
+    }
+}
index 26e35be..746f9c2 100644 (file)
@@ -29,6 +29,7 @@ public class User extends BaseCmd<User> {
     public User(AAFcli aafcli) throws APIException {
         super(aafcli,"user");
         cmds.add(new Role(this));
+        cmds.add(new ID(this));
         cmds.add(new Cred(this));
         cmds.add(new Delg(this));
         cmds.add(new List(this));
index 359cb28..f8aeb11 100644 (file)
@@ -131,7 +131,8 @@ public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<E
         deployedVersion = access.getProperty(Config.AAF_RELEASE, "N/A:2.x");
 
         // Certificate Manager
-        cmCon =  new AAFConHttp(env.access(),Config.AAF_URL_CM);
+        String aaf_url_cm = env.getProperty(Config.AAF_URL_CM,Config.AAF_URL_CM_DEF);
+        cmCon =  new AAFConHttp(env.access(),aaf_url_cm);
         artifactsDF = env.newDataFactory(Artifacts.class);
         certInfoDF  = env.newDataFactory(CertInfo.class);
         
index 751825c..e311513 100644 (file)
@@ -2290,7 +2290,6 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
         try {
             Result<CredDAO.Data> rcred = mapper.cred(trans, from, true);
             if (rcred.isOKhasData()) {
-                byte[] rawCred = rcred.value.cred.array();
                 rcred = ques.userCredSetup(trans, rcred.value);
                 
                 final ServiceValidator v = new ServiceValidator();
@@ -2333,7 +2332,9 @@ public class AuthzCassServiceImpl    <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE
                         // Note: ASPR specifies character differences, but we don't actually store the
                         // password to validate char differences.
                         
-                        rb = ques.userCredCheck(trans, curr, rawCred);
+//                      byte[] rawCred = rcred.value.type==CredDAO.RAW?null:;
+
+                        rb = ques.userCredCheck(trans, curr, rcred.value.cred.array());
                         if (rb.notOK()) {
                             return Result.err(rb);
                         } else if (rb.value){
index 72a24d2..187f4e3 100644 (file)
@@ -509,22 +509,27 @@ public class Mapper_2_0 implements Mapper<Nss, Perms, Pkey, Roles, Users, UserRo
         CredDAO.Data to = new CredDAO.Data();
         to.id=from.getId();
         to.ns = Question.domain2ns(to.id);
-        String passwd = from.getPassword();
-        if (requiresPass) {
-            String ok = trans.org().isValidPassword(trans, to.id,passwd);
-            if (ok.length()>0) {
-                return Result.err(Status.ERR_BadData,ok);
-            }
-        } else {
-            to.type=0;
-        }
-        if (passwd != null) {
-            to.cred = ByteBuffer.wrap(passwd.getBytes());
-            to.type = CredDAO.RAW; 
+        to.type = from.getType();
+        if(to.type!=null && to.type==CredDAO.FQI) {
+               to.cred = null;
         } else {
-            to.type = 0;
-        }
-        
+               String passwd = from.getPassword();
+               if (requiresPass) {
+                   String ok = trans.org().isValidPassword(trans, to.id,passwd);
+                   if (ok.length()>0) {
+                       return Result.err(Status.ERR_BadData,ok);
+                   }
+               } else {
+                   to.type=0;
+               }
+               if (passwd != null) {
+                   to.cred = ByteBuffer.wrap(passwd.getBytes());
+                   to.type = CredDAO.RAW; 
+               } else {
+                   to.type = CredDAO.FQI;
+               }
+        }
+               
         // Note: Ensure requested EndDate created will match Organization Password Rules
         //  P.S. Do not apply TempPassword rule here. Do that when you know you are doing a Create/Reset (see Service)
         to.expires = getExpires(trans.org(),Expiration.Password,base,from.getId());
index 128fdcd..adff461 100644 (file)
@@ -162,6 +162,7 @@ public class ServiceValidator extends Validator {
             } else {
                 switch(cd.type) {
                     case CredDAO.BASIC_AUTH_SHA256:
+                    case CredDAO.FQI:
                         // ok
                         break;
                     default:
index 4ae0777..fae2629 100644 (file)
@@ -114,7 +114,7 @@ image:
   # When using Docker Repo, add, and include trailing "/"
   # repository: nexus3.onap.org:10003/
   # repository: localhost:5000/
-  version: 2.1.14
+  version: 2.1.14-SNAPSHOT
 
 resources: {}
   # We usually recommend not to specify default resources and to leave this as a conscious
index 93ab4ab..80e9f19 100644 (file)
@@ -23,6 +23,7 @@ package org.onap.aaf.cadi.aaf.v2_0;
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.Locator;
 import org.onap.aaf.cadi.LocatorException;
 
@@ -89,4 +90,8 @@ public class AAFSingleLocator implements Locator<URI> {
        
        private class SingleItem implements Item {
        }
+       
+       public static AAFSingleLocator create(Access access, String url) throws URISyntaxException {
+               return new AAFSingleLocator(url);
+       }
 }
index 2405962..ac8168b 100644 (file)
@@ -74,7 +74,12 @@ public abstract class AbsAAFLocator<TRANS extends Trans> implements Locator<URI>
                }
         try {
                aaf_locator_host = rph.replacements(getClass().getSimpleName(),"https://"+Config.AAF_LOCATE_URL_TAG,null,null);
-            aaf_locator_uri = new URI(aaf_locator_host);
+               if(aaf_locator_host.endsWith("/locate")) {
+                aaf_locator_uri = new URI(aaf_locator_host);
+               } else {
+                       aaf_locator_uri = new URI(aaf_locator_host+"/locate");
+               }
+               
             access.printf(Level.INFO, "AbsAAFLocator AAF URI is %s",aaf_locator_uri);
         } catch (URISyntaxException e) {
             throw new LocatorException(e);
index 1e5c521..ae562cb 100644 (file)
@@ -162,14 +162,21 @@ public class HMangr {
         return same(ss,retryable);
     }
     public<RET> RET all(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable) throws LocatorException, CadiException, APIException {
-        return oneOf(ss,retryable,true,null);
+        return call(ss,retryable,true,null);
     }
 
     public<RET> RET all(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify) throws LocatorException, CadiException, APIException {
-        return oneOf(ss,retryable,notify,null);
+        return call(ss,retryable,notify,null);
     }
     
+    public <RET> RET allExcept(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify, String selfHost) throws LocatorException, CadiException, APIException {
+       return call(ss,retryable,notify,selfHost);
+    }
+
     public<RET> RET oneOf(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify,String host) throws LocatorException, CadiException, APIException {
+       return call(ss,retryable,notify,host);
+    }
+    private<RET> RET call(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify,String host) throws LocatorException, CadiException, APIException {
         RET ret = null;
         // make sure we have all current references:
         loc.refresh();
index 8357129..b7c0b02 100644 (file)
@@ -60,23 +60,27 @@ public class DNSLocator implements Locator<URI> {
         if (aaf_locate==null) {
             throw new LocatorException("Null passed into DNSLocator constructor");
         }
-        int start, port;
+        int start, defPort;
         if (aaf_locate.startsWith("https:")) {
-            protocol = "https:";
-            start = 9; // https://
-            port = 443;
+            protocol = "https";
+            start = 8; // https://
+            defPort = 443;
         } else if (aaf_locate.startsWith("http:")) {
-            protocol = "http:";
-            start = 8; // http://
-            port = 80;
+            protocol = "http";
+            start = 7; // http://
+            defPort = 80;
         } else {
             throw new LocatorException("DNSLocator accepts only https or http protocols.  (requested URL " + aaf_locate + ')');
         }
-        
-        parsePorts(aaf_locate.substring(start), port);
+        host = parseHostAndPorts(aaf_locate, start, defPort);
+        refresh();
     }
 
-    @Override
+    public static DNSLocator create(Access access, String url) throws LocatorException {
+               return new DNSLocator(access, url);
+       }
+
+       @Override
     public URI get(Item item) throws LocatorException {
         return hosts[((DLItem)item).cnt].uri;
     }
@@ -159,10 +163,11 @@ public class DNSLocator implements Locator<URI> {
         return false;
     }
     
-    private void parsePorts(String aaf_locate, int defaultPort) throws LocatorException {
+    private String parseHostAndPorts(String aaf_locate, int _start, int defaultPort) throws LocatorException {
         int slash, start;
-        int colon = aaf_locate.indexOf(':');
+        int colon = aaf_locate.indexOf(':',_start);
         if (colon > 0) {
+               host = aaf_locate.substring(_start,colon);
             start = colon + 1;
             int left = aaf_locate.indexOf('[', start);
             if (left > 0) {
@@ -195,8 +200,12 @@ public class DNSLocator implements Locator<URI> {
                 }
             }
         } else {
+               slash = aaf_locate.indexOf('/', _start);
+               host = slash<_start?aaf_locate.substring(_start):aaf_locate.substring(_start,slash);
             startPort = endPort = defaultPort;
-        }        
+        }
+        
+        return host;
     }
 
     private class Host {
@@ -206,9 +215,13 @@ public class DNSLocator implements Locator<URI> {
         
         public Host(InetAddress inetAddress, int port, String suffix) throws URISyntaxException {
             ia = inetAddress;
-            uri = new URI(protocol,null,inetAddress.getHostAddress(),port,suffix,null,null);
+            uri = new URI(protocol,null,inetAddress.getCanonicalHostName(),port,suffix,null,null);
             status = Status.UNTRIED;
         }
+        
+        public String toString() {
+               return uri.toString() + " - " + status.name();
+        }
     }
     
     private class DLItem implements Item {
index 9d87d69..d174425 100644 (file)
 
 package org.onap.aaf.cadi.http.test;
 
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
@@ -34,10 +40,10 @@ import java.net.URISyntaxException;
 
 import javax.net.ssl.SSLHandshakeException;
 
-import static org.hamcrest.CoreMatchers.*;
-
-import org.junit.*;
-import org.mockito.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.onap.aaf.cadi.Access;
 import org.onap.aaf.cadi.CadiException;
 import org.onap.aaf.cadi.Locator;
@@ -49,6 +55,8 @@ import org.onap.aaf.cadi.client.Retryable;
 import org.onap.aaf.cadi.http.HMangr;
 import org.onap.aaf.misc.env.APIException;
 
+import junit.framework.Assert;
+
 public class JU_HMangr {
     
     @Mock Locator<URI> locMock;
@@ -173,9 +181,14 @@ public class JU_HMangr {
     @Test
     public void allTest() throws LocatorException, CadiException, APIException {
         HManagerStub hman = new HManagerStub(access, locMock);
+
         assertThat(hman.best(ssMock, retryableMock), is(nullValue()));
-        assertThat(hman.all(ssMock, retryableMock), is(nullValue()));
-        assertThat(hman.all(ssMock, retryableMock, true), is(nullValue()));
+        try {
+               hman.all(ssMock, retryableMock, true);
+               Assert.fail("Should have thrown LocatorException");
+        } catch (LocatorException e) {
+               assertEquals(e.getLocalizedMessage(),"No available clients to call");
+        }
     }
 
     @Test
index 9b5bbaf..dfc7142 100644 (file)
@@ -53,9 +53,9 @@ public class JU_DNSLocator {
         
         item = dl.best();
         uri = dl.get(item);
-        assertThat(uri.toString(), is("https://127.0.0.1:8100"));
+        assertThat(uri.toString(), is("https://localhost:8100"));
         item = dl.best();
-        assertThat(uri.toString(), is("https://127.0.0.1:8100"));
+        assertThat(uri.toString(), is("https://localhost:8100"));
 
         assertThat(dl.hasItems(), is(true));
         for (item = dl.first(); item != null; item = dl.next(item)) {
index 8cb1045..52bb53e 100644 (file)
@@ -221,6 +221,7 @@ public class Config {
     public static final String AAF_URL_GUI="aaf_url_gui";
     public static final String AAF_URL_FS="aaf_url_fs";
     public static final String AAF_URL_CM = "aaf_url_cm";
+    public static final String AAF_URL_CM_DEF = "https://AAF_LOCATE_URL/AAF_NS.cm:"+AAF_DEFAULT_API_VERSION;
     public static final String AAF_URL_HELLO = "aaf_url_hello";
     public static final String CM_TRUSTED_CAS = "cm_trusted_cas";
 
@@ -856,18 +857,24 @@ public class Config {
                } catch (UnknownHostException | CadiException e1) {
                        throw new LocatorException(e1);
                }
-            
+
+            String aaf_locator_class;
+            if(_url.equals(url) && !url.contains("/locate/")) {
+               aaf_locator_class = "org.onap.aaf.cadi.locator.DNSLocator";
+            } else {
+               aaf_locator_class = AAF_LOCATOR_CLASS_DEF;
+            }
             try {
-                Class<?> lcls = loadClass(access,AAF_LOCATOR_CLASS_DEF);
+                Class<?> lcls = loadClass(access,aaf_locator_class);
                 if (lcls==null) {
                     throw new CadiException("Need to include aaf-cadi-aaf jar for AAFLocator");
                 }
                 // First check for preloaded
                 try {
-                    Method meth = lcls.getMethod("create",String.class);
-                    locator = (Locator<URI>)meth.invoke(null,url);
+                    Method meth = lcls.getMethod("create",Access.class,String.class);
+                    locator = (Locator<URI>)meth.invoke(null,access,url);
                 } catch (Exception e) {
-                    access.log(Level.DEBUG, "(Not fatal) Cannot load by create(String)", e);
+                    access.log(Level.TRACE, "(Not fatal) Cannot load by create(String)", e);
                 }
                 if (locator==null) {
                     URI locatorURI = new URI(url);