Introduce default pub/sub Roles for Topic 44/75144/1
authordglFromAtt <dgl@research.att.com>
Thu, 27 Dec 2018 14:01:49 +0000 (09:01 -0500)
committerdglFromAtt <dgl@research.att.com>
Thu, 27 Dec 2018 14:02:04 +0000 (09:02 -0500)
Change-Id: I79b553648a9a151c420ee66ef08ebe713d8d2515
Signed-off-by: dglFromAtt <dgl@research.att.com>
Issue-ID: DMAAP-856

src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java [new file with mode: 0644]
src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java [new file with mode: 0644]
src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java
src/main/java/org/onap/dmaap/dbcapi/model/Topic.java
src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java
src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java
src/main/resources/schema_11.sql [new file with mode: 0644]

diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java
new file mode 100644 (file)
index 0000000..aa4fb89
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2017 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.dmaap.dbcapi.aaf;
+
+import java.util.ArrayList;
+
+import org.apache.log4j.Logger;
+import org.onap.dmaap.dbcapi.util.DmaapConfig;
+
+
+public class AafNamespace extends AafObject  {
+       static final Logger logger = Logger.getLogger(AafNamespace.class);
+       
+       private String  name;
+       private ArrayList<String>       admin;
+       private ArrayList<String>       responsible;
+       
+       // in some environments, an AAF Namespace must be owned by a human.
+       // So, when needed, this var can be set via a property
+       static private String NsOwnerIdentity;
+       
+       public AafNamespace(String ns, String identity ) {
+               super();
+               DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
+               NsOwnerIdentity = p.getProperty( "aaf.NsOwnerIdentity", "");
+               this.admin = new ArrayList<String>();
+               this.responsible = new ArrayList<String>();
+               
+               this.name = ns;
+               this.admin.add( identity );
+               this.responsible.add( NsOwnerIdentity );
+       }
+       public void setName( String ns ) {
+               this.name = ns;
+       }
+       public String getName() {
+               return name;
+       }
+       public ArrayList<String> getAdmin() {
+               return admin;
+       }
+       public void setAdmin(ArrayList<String> admin) {
+               this.admin = admin;
+       }
+       public ArrayList<String> getResponsible() {
+               return responsible;
+       }
+       public void setResponsible(ArrayList<String> responsible) {
+               this.responsible = responsible;
+       }
+
+
+       // given an Array of Strings, return a String that is a separated list of quoted strings.
+       // e.g. input [ a, b, c ]
+       //       output  "a", "b", "c"
+       private String separatedList( ArrayList<String> list, String sep ) {
+               if (list.isEmpty()) return null;
+               String aList = new String();
+               String delim = "";
+               for( String item: list) {
+                       if( ! item.isEmpty()) {
+                               aList += String.format( "%s\"%s\"", delim, item );
+                               delim = sep;
+                       }
+               }
+               return aList;
+       }
+
+       public String toJSON() {
+
+               String postJSON = String.format(" { \"name\": \"%s\", \"admin\": [", 
+                               this.getName()
+                                );
+               postJSON += separatedList( this.getAdmin(), "," );
+               postJSON += "], \"responsible\":[";
+               postJSON += separatedList( this.getResponsible(), ",");
+               postJSON += "]}";
+               logger.info( "returning JSON: " + postJSON);
+                       
+               return postJSON;
+       }
+       
+       
+       
+       
+}
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java
new file mode 100644 (file)
index 0000000..6acbefd
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2017 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.dmaap.dbcapi.aaf;
+
+import org.apache.log4j.Logger;
+
+
+public class AafRole extends AafObject  {
+       static final Logger logger = Logger.getLogger(AafRole.class);
+       
+       private String  namespace;
+       private String  role;
+       
+       public AafRole(String ns,  String role) {
+               super();
+               this.namespace = ns;
+               this.role = role;
+       }
+       public void setNamespace( String ns ) {
+               this.namespace = ns;
+       }
+       public String getNamespace() {
+               return namespace;
+       }
+       public void setRole(String role) {
+               this.role = role;
+       }
+       public String getRole() {
+               return role;
+       }
+       public String getFullyQualifiedRole() {
+               return namespace + "." + role;
+       }
+
+       public String toJSON() {
+
+               String postJSON = String.format(" { \"name\": \"%s.%s\"}", 
+                               this.getNamespace(), 
+                               this.getRole() );
+               logger.info( "returning JSON: " + postJSON);
+                       
+               return postJSON;
+       }
+       
+       
+       
+       
+}
index 112ab11..4778aff 100644 (file)
@@ -36,9 +36,21 @@ public class AafService extends BaseLoggingClass {
        private AafConnection aaf;
        private ServiceType ctype;
        private String aafURL ;
+       private String identity;
        private boolean useAAF = false;
        
        
+       
+       public String getIdentity() {
+               return identity;
+       }
+
+
+       public void setIdentity(String identity) {
+               this.identity = identity;
+       }
+
+
        private String getCred( boolean wPwd ) {
                String mechIdProperty = null;
                String pwdProperty = null;
@@ -55,7 +67,7 @@ public class AafService extends BaseLoggingClass {
                        logger.error( "Unexpected case for AAF credential type: " + ctype );
                        return null;
                }
-               String user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" );
+               identity = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" );
 
                String pwd = "";
                String encPwd = p.getProperty( pwdProperty, "notSet" );
@@ -64,14 +76,15 @@ public class AafService extends BaseLoggingClass {
                pwd = decryptor.decrypt(encPwd);
                
                if ( wPwd ) {
-                       return user + ":" + pwd;
+                       return identity + ":" + pwd;
                } else {
-                       return user;
+                       return identity;
                }
                
                
        }
        
+       
        public AafService(ServiceType t ) {
                DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
                aafURL = p.getProperty( "aaf.URL", "https://authentication.domain.netset.com:8095/proxy/");
@@ -92,70 +105,12 @@ public class AafService extends BaseLoggingClass {
        }
        
        public int addPerm(DmaapPerm perm) {
-
-               int rc = -1;
                logger.info( "entry: addPerm() "  );
-               String pURL = aafURL + "authz/perm";
-               logger.info( "addPerm=" + useAAF );
-               if ( useAAF ) {
-                       logger.info( "addPerm: " + perm.toJSON());
-                       rc = aaf.postAaf( perm, pURL );
-               } else {
-                       rc = 201;
-               }
-        switch( rc ) {
-       case 401:
-       case 403:
-                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
-               System.exit(1);
-       case 409:
-               logger.warn( "Perm already exists. Possible conflict.");
-               break;
-               
-       case 201:
-               logger.info( "expected response: " + rc);
-               break;
-               default :
-               logger.error( "Unexpected response: " + rc );
-               break;
-        }
-               
-               return rc;
+               return doPost( perm, "authz/perm", 201);
        }
        public int addGrant(DmaapGrant grant ) {
-
-               int rc = -1;
                logger.info( "entry: addGrant() "  );
-
-               String pURL = aafURL + "authz/role/perm";
-               logger.info( "addGrant: useAAF=" + useAAF );
-               if ( useAAF ) {
-                       logger.info( "addGrant: " + grant.toJSON() );
-                       rc = aaf.postAaf( grant, pURL );
-               } else {
-                       rc = 201;
-               }
-               
-        switch( rc ) {
-       case 401:
-       case 403:
-                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
-               System.exit(1);
-               break;
-
-       case 409:
-               logger.warn( "Perm already exists. Possible conflict.");
-               break;
-               
-       case 201:
-               logger.info( "expected response" );
-               break;
-               default :
-               logger.error( "Unexpected response: " + rc );
-               break;
-        }
-               
-               return rc;
+               return doPost( grant, "authz/role/perm", 201 );
        }
 
        public int delGrant( DmaapGrant grant ) {
@@ -191,5 +146,49 @@ public class AafService extends BaseLoggingClass {
                return rc;
        }
 
+       public int addRole(AafRole role) {
+               logger.info( "entry: addRole() "  );
+               return doPost( role, "authz/role", 201 );
+       }
+
+       
+       
+       public int addNamespace(AafNamespace ns) {
+               logger.info( "entry: addNamespace() "  );
+               return doPost( ns, "authz/ns", 201 );
+       }
+
+       
+       private int doPost( AafObject obj, String uri, int expect ) {
+               int rc = -1;
+               logger.info( "entry: doPost() "  );
+               String pURL = aafURL + uri;
+               logger.info( "doPost: useAAF=" + useAAF );
+               if ( useAAF ) {
+                       logger.info( "doPost: " + obj.toJSON());
+                       rc = aaf.postAaf( obj, pURL );
+               } else {
+                       rc = expect;
+               }
+        switch( rc ) {
+       case 401:
+       case 403:
+                       errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR,  getCred( false ) );
+               System.exit(1);
+       case 409:
+               logger.warn( "Object for " + uri + " already exists. Possible conflict.");
+               break;
+               
 
+               default :
+                       if ( rc == expect ) {
+                               logger.info( "expected response: " + rc);
+                       } else {
+                               logger.error( "Unexpected response: " + rc );
+                       }
+               break;
+        }
+        
+        return rc;
+       }
 }
index c2f278d..bfd948b 100644 (file)
@@ -49,6 +49,8 @@ public class Topic extends DmaapObject  {
        private String  version;        
        private String  partitionCount;
        private String  replicationCount;
+       private String  publisherRole;
+       private String  subscriberRole;
 
 
        private ArrayList<MR_Client> clients;
@@ -282,6 +284,18 @@ public class Topic extends DmaapObject  {
 
 
 
+       public String getPublisherRole() {
+               return publisherRole;
+       }
+       public void setPublisherRole(String publisherRole) {
+               this.publisherRole = publisherRole;
+       }
+       public String getSubscriberRole() {
+               return subscriberRole;
+       }
+       public void setSubscriberRole(String subscriberRole) {
+               this.subscriberRole = subscriberRole;
+       }
        public String toProvJSON() {
                StringBuilder str = new StringBuilder();
                str.append("{ \"topicName\": \"");
index 5c2c8a3..9d9b922 100644 (file)
@@ -168,6 +168,8 @@ public class DmaapService  extends BaseLoggingClass  {
        public String getTopicPerm( String val ) {
                Dmaap dmaap = dmaapholder.get();
                String nsRoot = dmaap.getTopicNsRoot();
+               if ( nsRoot == null ) { return null; }
+               
                String t;
                // in ONAP Casablanca, we assume no distinction of environments reflected in topic namespace
                if ( nsRoot.startsWith(noEnvironmentPrefix) ) {
index 49966d7..a26205c 100644 (file)
@@ -29,7 +29,10 @@ import java.util.Set;
 
 import javax.ws.rs.core.Response.Status;
 
+import org.onap.dmaap.dbcapi.aaf.AafNamespace;
+import org.onap.dmaap.dbcapi.aaf.AafRole;
 import org.onap.dmaap.dbcapi.aaf.AafService;
+import org.onap.dmaap.dbcapi.aaf.DmaapGrant;
 import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType;
 import org.onap.dmaap.dbcapi.aaf.DmaapPerm;
 import org.onap.dmaap.dbcapi.database.DatabaseClass;
@@ -112,6 +115,94 @@ public class TopicService extends BaseLoggingClass {
                apiError.setCode(Status.OK.getStatusCode());
                return t;
        }
+       
+       private void aafTopicSetup(Topic topic, ApiError err ) {
+
+               String t = dmaapSvc.getTopicPerm();
+               if ( t == null ) {
+                       err.setCode(500);
+                       err.setMessage("Unable to establish AAF namespace root: (check /dmaap object)"  );
+                       err.setFields("topicNsRoot");
+                       return;
+               }
+
+               // establish AAF Connection using TopicMgr identity
+               AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
+               
+
+               
+               // create AAF namespace for this topic
+               AafNamespace ns = new AafNamespace( topic.getFqtn(), aaf.getIdentity());
+               {
+                       int rc = aaf.addNamespace( ns );
+                       if ( rc != 201 && rc != 409 ) {
+                               err.setCode(500);
+                               err.setMessage("Unexpected response from AAF:" + rc );
+                               err.setFields("namespace:" + topic.getFqtn() + " identity="+ aaf.getIdentity());
+                               return;
+                       }
+               }
+               
+               // create AAF Roles for MR clients of this topic
+               String rn = "publisher";
+               AafRole pubRole = new AafRole( topic.getFqtn(), rn );
+               int rc = aaf.addRole( pubRole );
+               if ( rc != 201 && rc != 409 ) {
+                       err.setCode(500);
+                       err.setMessage("Unexpected response from AAF:" + rc );
+                       err.setFields("topic:" + topic.getFqtn() + " role="+ rn);
+                       return;
+               }
+               topic.setPublisherRole( pubRole.getFullyQualifiedRole() );
+               
+               rn = "subscriber";
+               AafRole subRole = new AafRole( topic.getFqtn(), rn );
+               rc = aaf.addRole( subRole );
+               if ( rc != 201 && rc != 409 ) {
+                       err.setCode(500);
+                       err.setMessage("Unexpected response from AAF:" + rc );
+                       err.setFields("topic:" + topic.getFqtn() + " role="+ rn);
+                       return;
+               }
+               topic.setSubscriberRole( subRole.getFullyQualifiedRole() );
+       
+               
+               // create AAF perms checked by MR
+               String instance = ":topic." + topic.getFqtn();
+               String[] actions = { "pub", "sub", "view" };
+               for ( String action : actions ){
+                       DmaapPerm perm = new DmaapPerm( t, instance, action );
+                       rc = aaf.addPerm( perm );
+                       if ( rc != 201 && rc != 409 ) {
+                               err.setCode(500);
+                               err.setMessage("Unexpected response from AAF:" + rc );
+                               err.setFields("t="+t + " instance="+ instance + " action="+ action);
+                               return;
+                       }
+                       // Grant perms to our default Roles
+                       if ( action.equals( "pub") || action.equals( "view") ) {
+                               DmaapGrant g = new DmaapGrant( perm, pubRole.getFullyQualifiedRole() );
+                               rc = aaf.addGrant( g );
+                               if ( rc != 201 && rc != 409 ) {
+                                       err.setCode(rc);
+                                       err.setMessage( "Grant of " + perm.toString() + " failed for " + pubRole.getFullyQualifiedRole() );
+                                       logger.warn( err.getMessage());
+                                       return;
+                               } 
+                       }
+                       if ( action.equals( "sub") || action.equals( "view") ) {
+                               DmaapGrant g = new DmaapGrant( perm, subRole.getFullyQualifiedRole() );
+                               rc = aaf.addGrant( g );
+                               if ( rc != 201 && rc != 409 ) {
+                                       err.setCode(rc);
+                                       err.setMessage( "Grant of " + perm.toString() + " failed for " + subRole.getFullyQualifiedRole() );
+                                       logger.warn( err.getMessage());
+                                       return;
+                               } 
+                       }
+
+               }
+       }
 
        public Topic addTopic( Topic topic, ApiError err, Boolean useExisting ) {
                logger.info( "Entry: addTopic");
@@ -135,23 +226,11 @@ public class TopicService extends BaseLoggingClass {
 
                topic.setFqtn( nFqtn );
                
-               AafService aaf = new AafService(ServiceType.AAF_TopicMgr);
-
-               String t = dmaapSvc.getTopicPerm();
-
-               String instance = ":topic." + topic.getFqtn();
+               aafTopicSetup( topic, err );
+               if ( err.getCode() >= 400 ) {
+                       return null;
+               }       
 
-               String[] actions = { "pub", "sub", "view" };
-               for ( String action : actions ){
-                       DmaapPerm perm = new DmaapPerm( t, instance, action );
-                       int rc = aaf.addPerm( perm );
-                       if ( rc != 201 && rc != 409 ) {
-                               err.setCode(500);
-                               err.setMessage("Unexpected response from AAF:" + rc );
-                               err.setFields("t="+t + " instance="+ instance + " action="+ action);
-                               return null;
-                       }
-               }
                if ( topic.getReplicationCase().involvesGlobal() ) {
                        if ( topic.getGlobalMrURL() == null ) {
                                topic.setGlobalMrURL(defaultGlobalMrHost);
diff --git a/src/main/resources/schema_11.sql b/src/main/resources/schema_11.sql
new file mode 100644 (file)
index 0000000..de848b1
--- /dev/null
@@ -0,0 +1,27 @@
+---
+-- ============LICENSE_START=======================================================
+-- OpenECOMP - org.onap.dbcapi
+-- ================================================================================
+-- Copyright (C) 2017 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=========================================================
+---
+
+
+@alter table topic
+       add column      publisher_role  varchar(100),
+       add column      subscriber_role varchar(100)
+;
+
+update dmaapbc_sch_ver set version = 11 where version = 10;