aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordglFromAtt <dgl@research.att.com>2018-12-27 09:01:49 -0500
committerdglFromAtt <dgl@research.att.com>2018-12-27 09:02:04 -0500
commit297ea699d8f7f3be96abea6c28e4204f7c4687a4 (patch)
treeaeed9300a8fb584b72749d4d4399a3200680ac0d
parent956361f657eda468d5980249db6b155c472f5f85 (diff)
Introduce default pub/sub Roles for Topic
Change-Id: I79b553648a9a151c420ee66ef08ebe713d8d2515 Signed-off-by: dglFromAtt <dgl@research.att.com> Issue-ID: DMAAP-856
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java104
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java66
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java125
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/model/Topic.java14
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java2
-rw-r--r--src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java111
-rw-r--r--src/main/resources/schema_11.sql27
7 files changed, 370 insertions, 79 deletions
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
index 0000000..aa4fb89
--- /dev/null
+++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java
@@ -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
index 0000000..6acbefd
--- /dev/null
+++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java
@@ -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;
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java
index 112ab11..4778aff 100644
--- a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java
+++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java
@@ -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;
+ }
}
diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java
index c2f278d..bfd948b 100644
--- a/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java
+++ b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java
@@ -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\": \"");
diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java
index 5c2c8a3..9d9b922 100644
--- a/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java
+++ b/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java
@@ -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) ) {
diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java
index 49966d7..a26205c 100644
--- a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java
+++ b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java
@@ -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
index 0000000..de848b1
--- /dev/null
+++ b/src/main/resources/schema_11.sql
@@ -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;