summaryrefslogtreecommitdiffstats
path: root/cass
diff options
context:
space:
mode:
authorsg481n <sg481n@att.com>2017-08-03 17:39:12 -0400
committersg481n <sg481n@att.com>2017-08-03 17:39:12 -0400
commit4a51a8f96715ffb2a42189b93b9fa91b453b8530 (patch)
treeb028ce9e44920addba4194643db5b1c115a00e1a /cass
parent81ad32335f59a3169c032139fb77148b247ed7f0 (diff)
 [AAF-21] Initial code import
Change-Id: Ia1dd196befd061f6ba0c2be6bf4456a30ea50f97 Signed-off-by: sg481n <sg481n@att.com>
Diffstat (limited to 'cass')
-rw-r--r--cass/.gitignore5
-rw-r--r--cass/etc/cadi.properties69
-rw-r--r--cass/pom.xml115
-rw-r--r--cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticatedUser.java112
-rw-r--r--cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticator.java176
-rw-r--r--cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthorizer.java228
-rw-r--r--cass/src/main/java/com/att/cadi/aaf/cass/AAFBase.java193
-rw-r--r--cass/src/test/java/com/att/aaf/cass/JU_CASS.java108
-rw-r--r--cass/src/test/java/com/att/cadi/aaf/cass/test/JU_CASS.java108
9 files changed, 1114 insertions, 0 deletions
diff --git a/cass/.gitignore b/cass/.gitignore
new file mode 100644
index 0000000..cf85207
--- /dev/null
+++ b/cass/.gitignore
@@ -0,0 +1,5 @@
+/bin/
+/target/
+/.classpath
+/.project
+.settings
diff --git a/cass/etc/cadi.properties b/cass/etc/cadi.properties
new file mode 100644
index 0000000..f9676b0
--- /dev/null
+++ b/cass/etc/cadi.properties
@@ -0,0 +1,69 @@
+#-------------------------------------------------------------------------------
+# ============LICENSE_START====================================================
+# * org.onap.aai
+# * ===========================================================================
+# * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# * Copyright © 2017 Amdocs
+# * ===========================================================================
+# * 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====================================================
+# *
+# * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# *
+#-------------------------------------------------------------------------------
+###############################################################################
+# Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+###############################################################################
+##
+## AUTHZ API (authz-service) Properties
+##
+
+## DISCOVERY (DME2) Parameters on the Command Line
+AFT_LATITUDE=38.627345
+AFT_LONGITUDE=-90.193774
+AFT_ENVIRONMENT=AFTUAT
+
+# CADI
+cadi_keyfile=/opt/app/aaf/common/com.att.aaf.keyfile
+cadi_loglevel=WARN
+
+# CASSANDRA Required for APP
+cass_group_name=com.att.aaf
+
+# CASSANDRA Optional
+cass_cluster_name=mithril
+
+# AAF Required for APP
+aaf_url=https://DME2RESOLVE/service=com.att.authz.AuthorizationService/version=2.0/envContext=DEV/routeOffer=BAU_SE
+DME2_EP_REGISTRY_CLASS=DME2FS
+AFT_DME2_EP_REGISTRY_FS_DIR=/Volumes/Data/src/authz/dme2reg
+
+aaf_default_realm=aaf.localized
+aaf_id=XX@NS
+aaf_password=enc:
+cadi_loglevel=DEBUG
+
+# AAF Optional
+# Connection Time Out (milliseconds)
+aaf_conn_timeout=10000
+# User Cache Expiration (milliseconds)
+aaf_user_expires=600000
+# High count... Rough top number of objects held in Cache per cycle. If high is reached, more are
+# recycled next time.
+aaf_high_count=1000
+
+##
+## Localized Passwords
+##
+basic_realm=aaf.localized
+local_users=root@aaf.localized%<PASS>:/dbname
diff --git a/cass/pom.xml b/cass/pom.xml
new file mode 100644
index 0000000..89582d6
--- /dev/null
+++ b/cass/pom.xml
@@ -0,0 +1,115 @@
+<!--
+ ============LICENSE_START====================================================
+ * org.onap.aai
+ * ===========================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===========================================================================
+ * 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====================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ *
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>com.att.cadi</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.3.2</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <name>CADI Cassandra Plugin</name>
+ <packaging>jar</packaging>
+ <url>https://github.com/att/AAF</url>
+ <description>CADI</description>
+ <artifactId>cadi-cass</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.att.cadi</groupId>
+ <artifactId>cadi-aaf</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.cassandra</groupId>
+ <artifactId>cassandra-all</artifactId>
+ <version>2.1.14</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jarsigner-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <failOnError>false</failOnError>
+ </configuration>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>2.2.1</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar-no-fork</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.sonatype.plugins</groupId>
+ <artifactId>nexus-staging-maven-plugin</artifactId>
+ <version>1.6.7</version>
+ <extensions>true</extensions>
+ <configuration>
+ <serverId>ossrhdme</serverId>
+ <nexusUrl>https://oss.sonatype.org/</nexusUrl>
+ <autoReleaseAfterClose>true</autoReleaseAfterClose>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticatedUser.java b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticatedUser.java
new file mode 100644
index 0000000..d720e28
--- /dev/null
+++ b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticatedUser.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.cadi.aaf.cass;
+
+import java.security.Principal;
+
+import org.apache.cassandra.auth.AuthenticatedUser;
+
+import com.att.cadi.Access;
+
+public class AAFAuthenticatedUser extends AuthenticatedUser implements Principal {
+ private boolean anonymous = false, supr=false, local=false;
+ private String fullName;
+// private Access access;
+
+ public AAFAuthenticatedUser(Access access, String name) {
+ super(name);
+// this.access = access;
+ int endIndex = name.indexOf("@");
+ if(endIndex >= 0) {
+ fullName = name;
+ } else {
+ fullName = name + '@' + AAFBase.default_realm;
+ }
+ }
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public String getName() {
+ return fullName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.cassandra.auth.AuthenticatedUser#isAnonymous()
+ */
+ @Override
+ public boolean isAnonymous() {
+ return anonymous;
+ }
+
+ public void setAnonymous(boolean anon) {
+ anonymous = anon;
+ }
+
+ public boolean getAnonymous() {
+ return anonymous;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.cassandra.auth.AuthenticatedUser#isSuper()
+ */
+ @Override
+ public boolean isSuper() {
+ return supr;
+ }
+
+ public void setSuper(boolean supr) {
+ this.supr = supr;
+ }
+
+ public boolean getSuper() {
+ return supr;
+ }
+
+ /**
+ * We check Local so we can compare with the right Lur. This is AAF Plugin only.
+ * @return
+ */
+ public boolean isLocal() {
+ return local;
+ }
+
+ public void setLocal(boolean val) {
+ local = val;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AAFAuthenticatedUser)) return false;
+ return ((AuthenticatedUser)o).getName().equals(this.getName());
+ }
+
+ @Override
+ public int hashCode() {
+ //access.log(Level.DEBUG, "AAFAuthentication hashcode ",getName().hashCode());
+ return getName().hashCode();
+ }
+}
diff --git a/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticator.java b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticator.java
new file mode 100644
index 0000000..8228899
--- /dev/null
+++ b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthenticator.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.cadi.aaf.cass;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cassandra.auth.AuthenticatedUser;
+import org.apache.cassandra.auth.IAuthenticator;
+import org.apache.cassandra.auth.ISaslAwareAuthenticator;
+import org.apache.cassandra.exceptions.AuthenticationException;
+import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.exceptions.RequestExecutionException;
+
+import com.att.cadi.Access.Level;
+import com.att.cadi.CredVal.Type;
+import com.att.cadi.Symm;
+import com.att.cadi.config.Config;
+
+public class AAFAuthenticator extends AAFBase implements ISaslAwareAuthenticator {
+
+ public boolean requireAuthentication() {
+ return true;
+ }
+
+ /**
+ * Invoked to authenticate an user
+ */
+ public AuthenticatedUser authenticate(Map<String, String> credentials) throws AuthenticationException {
+ String username = (String)credentials.get("username");
+ if (username == null) {
+ throw new AuthenticationException("'username' is missing");
+ }
+
+ AAFAuthenticatedUser aau = new AAFAuthenticatedUser(access,username);
+ String fullName=aau.getFullName();
+ access.log(Level.DEBUG, "Authenticating", aau.getName(),"(", fullName,")");
+
+ String password = (String)credentials.get("password");
+ if (password == null) {
+ throw new AuthenticationException("'password' is missing");
+ } else if(password.startsWith("bsf:")) {
+ try {
+ password = Symm.base64noSplit.depass(password);
+ } catch (IOException e) {
+ throw new AuthenticationException("AAF bnf: Password cannot be decoded");
+ }
+ } else if(password.startsWith("enc:???")) {
+ try {
+ password = access.decrypt(password, true);
+ } catch (IOException e) {
+ throw new AuthenticationException("AAF Encrypted Password cannot be decrypted");
+ }
+ }
+
+ if(localLur!=null) {
+ access.log(Level.DEBUG, "Validating",fullName, "with LocalTaf", password);
+ if(localLur.validate(fullName, Type.PASSWORD, password.getBytes())) {
+ aau.setAnonymous(true);
+ aau.setLocal(true);
+ access.log(Level.DEBUG, fullName, "is authenticated locally");
+ return aau;
+ }
+ }
+
+ String aafResponse;
+ try {
+ access.log(Level.DEBUG, "Validating",fullName, "with AAF");//, password);
+ aafResponse = aafAuthn.validate(fullName, password);
+ if(aafResponse != null) { // Reason for failing.
+ access.log(Level.AUDIT, "AAF reports ",fullName,":",aafResponse);
+ throw new AuthenticationException(aafResponse);
+ }
+ access.log(Level.AUDIT, fullName, "is authenticated"); //,password);
+ // This tells Cassandra to skip checking it's own tables for User Entries.
+ aau.setAnonymous(true);
+ } catch (AuthenticationException ex) {
+ throw ex;
+ } catch(Exception ex) {
+ access.log(ex,"Exception validating user");
+ throw new AuthenticationException("Exception validating user");
+ }
+
+ return aau;
+ }
+
+ public void create(String username, Map<IAuthenticator.Option, Object> options) throws InvalidRequestException, RequestExecutionException {
+ access.log(Level.INFO,"Use AAF CLI to create user");
+ }
+
+ public void alter(String username, Map<IAuthenticator.Option, Object> options) throws RequestExecutionException {
+ access.log(Level.INFO,"Use AAF CLI to alter user");
+ }
+
+ public void drop(String username) throws RequestExecutionException {
+ access.log(Level.INFO,"Use AAF CLI to delete user");
+ }
+
+ public SaslAuthenticator newAuthenticator() {
+ return new ISaslAwareAuthenticator.SaslAuthenticator() {
+ private boolean complete = false;
+ private Map<String, String> credentials;
+
+ public byte[] evaluateResponse(byte[] clientResponse) throws AuthenticationException {
+ this.credentials = decodeCredentials(clientResponse);
+ this.complete = true;
+ return null;
+ }
+
+ public boolean isComplete() {
+ return this.complete;
+ }
+
+ public AuthenticatedUser getAuthenticatedUser() throws AuthenticationException {
+ return AAFAuthenticator.this.authenticate(this.credentials);
+ }
+
+ private Map<String, String> decodeCredentials(byte[] bytes) throws AuthenticationException {
+ access.log(Level.DEBUG,"Decoding credentials from client token");
+ byte[] user = null;
+ byte[] pass = null;
+ int end = bytes.length;
+ for (int i = bytes.length - 1; i >= 0; i--)
+ {
+ if (bytes[i] != 0)
+ continue;
+ if (pass == null)
+ pass = Arrays.copyOfRange(bytes, i + 1, end);
+ else if (user == null)
+ user = Arrays.copyOfRange(bytes, i + 1, end);
+ end = i;
+ }
+
+ if (user == null)
+ throw new AuthenticationException("Authentication ID must not be null");
+ if (pass == null) {
+ throw new AuthenticationException("Password must not be null");
+ }
+ Map<String,String> credentials = new HashMap<String,String>();
+ try {
+ credentials.put(IAuthenticator.USERNAME_KEY, new String(user, Config.UTF_8));
+ credentials.put(IAuthenticator.PASSWORD_KEY, new String(pass, Config.UTF_8));
+ } catch (UnsupportedEncodingException e) {
+ throw new AuthenticationException(e.getMessage());
+ }
+ return credentials;
+ }
+ };
+ }
+
+}
+
diff --git a/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthorizer.java b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthorizer.java
new file mode 100644
index 0000000..a923e9b
--- /dev/null
+++ b/cass/src/main/java/com/att/cadi/aaf/cass/AAFAuthorizer.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.cadi.aaf.cass;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.cassandra.auth.AuthenticatedUser;
+import org.apache.cassandra.auth.IAuthorizer;
+import org.apache.cassandra.auth.IResource;
+import org.apache.cassandra.auth.Permission;
+import org.apache.cassandra.auth.PermissionDetails;
+import org.apache.cassandra.exceptions.RequestExecutionException;
+import org.apache.cassandra.exceptions.RequestValidationException;
+
+import com.att.cadi.Access.Level;
+import com.att.cadi.aaf.v2_0.AbsAAFLur;
+import com.att.cadi.lur.LocalPermission;
+
+public class AAFAuthorizer extends AAFBase implements IAuthorizer {
+ // Returns every permission on the resource granted to the user.
+ public Set<Permission> authorize(AuthenticatedUser user, IResource resource) {
+ String uname, rname;
+ access.log(Level.DEBUG,"Authorizing",uname=user.getName(),"for",rname=resource.getName());
+
+ Set<Permission> permissions;
+
+ if(user instanceof AAFAuthenticatedUser) {
+ AAFAuthenticatedUser aafUser = (AAFAuthenticatedUser) user;
+ aafUser.setAnonymous(false);
+
+ if(aafUser.isLocal()) {
+ permissions = checkPermissions(aafUser, new LocalPermission(
+ rname.replaceFirst("data", cluster_name)
+ ));
+ } else {
+ permissions = checkPermissions(
+ aafUser,
+ perm_type,
+ ':'+rname.replaceFirst("data", cluster_name).replace('/', ':'));
+ }
+ } else {
+ permissions = Permission.NONE;
+ }
+
+ access.log(Level.INFO,"Permissions on",rname,"for",uname,':', permissions);
+
+ return permissions;
+ }
+
+ /**
+ * Check only for Localized IDs (see cadi.properties)
+ * @param aau
+ * @param perm
+ * @return
+ */
+ private Set<Permission> checkPermissions(AAFAuthenticatedUser aau, LocalPermission perm) {
+ if(localLur.fish(aau.getFullName(), perm)) {
+// aau.setSuper(true);
+ return Permission.ALL;
+ } else {
+ return Permission.NONE;
+ }
+ }
+
+ /**
+ * Check remoted AAF Permissions
+ * @param aau
+ * @param type
+ * @param instance
+ * @return
+ */
+ private Set<Permission> checkPermissions(AAFAuthenticatedUser aau, String type, String instance) {
+ // Can perform ALL actions
+ String fullName = aau.getFullName();
+ PermHolder ph = new PermHolder(aau);
+ aafLur.fishOneOf(fullName, ph,type,instance,actions);
+ return ph.permissions;
+ }
+
+ private class PermHolder {
+ private AAFAuthenticatedUser aau;
+ public PermHolder(AAFAuthenticatedUser aau) {
+ this.aau = aau;
+ }
+ public Set<Permission> permissions = Permission.NONE;
+ public void mutable() {
+ if(permissions==Permission.NONE) {
+ permissions = new HashSet<Permission>();
+ }
+ }
+ };
+
+ /**
+ * This specialty List avoid extra Object Creation, and allows the Lur to do a Vistor on all appropriate Perms
+ */
+ private static final ArrayList<AbsAAFLur.Action<PermHolder>> actions = new ArrayList<AbsAAFLur.Action<PermHolder>>();
+ static {
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "*";
+ }
+
+ public boolean exec(PermHolder a) {
+ a.aau.setSuper(true);
+ a.permissions = Permission.ALL;
+ return true;
+ }
+ });
+
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "SELECT";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.SELECT);
+ return false;
+ }
+ });
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "MODIFY";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.MODIFY);
+ return false;
+ }
+ });
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "CREATE";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.CREATE);
+ return false;
+ }
+ });
+
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "ALTER";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.ALTER);
+ return false;
+ }
+ });
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "DROP";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.DROP);
+ return false;
+ }
+ });
+ actions.add(new AbsAAFLur.Action<PermHolder>() {
+ public String getName() {
+ return "AUTHORIZE";
+ }
+
+ public boolean exec(PermHolder ph) {
+ ph.mutable();
+ ph.permissions.add(Permission.AUTHORIZE);
+ return false;
+ }
+ });
+
+
+ };
+
+
+ public void grant(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String to) throws RequestExecutionException {
+ access.log(Level.INFO, "Use AAF CLI to grant permission(s) to user/role");
+ }
+
+ public void revoke(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String from) throws RequestExecutionException {
+ access.log(Level.INFO,"Use AAF CLI to revoke permission(s) for user/role");
+ }
+
+ public Set<PermissionDetails> list(AuthenticatedUser performer, Set<Permission> permissions, IResource resource, String of) throws RequestValidationException, RequestExecutionException {
+ access.log(Level.INFO,"Use AAF CLI to find the list of permissions");
+ return null;
+ }
+
+ // Called prior to deleting the user with DROP USER query. Internal hook, so no permission checks are needed here.
+ public void revokeAll(String droppedUser) {
+ access.log(Level.INFO,"Use AAF CLI to revoke permission(s) for user/role");
+ }
+
+ // Called after a resource is removed (DROP KEYSPACE, DROP TABLE, etc.).
+ public void revokeAll(IResource droppedResource) {
+ access.log(Level.INFO,"Use AAF CLI to delete the unused permission", droppedResource.getName());
+ }
+
+}
diff --git a/cass/src/main/java/com/att/cadi/aaf/cass/AAFBase.java b/cass/src/main/java/com/att/cadi/aaf/cass/AAFBase.java
new file mode 100644
index 0000000..32690f4
--- /dev/null
+++ b/cass/src/main/java/com/att/cadi/aaf/cass/AAFBase.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.cadi.aaf.cass;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.cassandra.auth.DataResource;
+import org.apache.cassandra.auth.IAuthenticator;
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.exceptions.ConfigurationException;
+
+import com.att.cadi.Access;
+import com.att.cadi.Access.Level;
+import com.att.cadi.Lur;
+import com.att.cadi.SLF4JAccess;
+import com.att.cadi.aaf.v2_0.AAFAuthn;
+import com.att.cadi.aaf.v2_0.AAFCon;
+import com.att.cadi.aaf.v2_0.AbsAAFLur;
+import com.att.cadi.config.Config;
+import com.att.cadi.lur.EpiLur;
+import com.att.cadi.lur.LocalLur;
+import com.att.cadi.aaf.AAFPermission;
+
+public abstract class AAFBase {
+ protected static final Set<IAuthenticator.Option> options;
+ protected static final Set<DataResource> dataResource;
+
+ static {
+ options = new HashSet<IAuthenticator.Option>();
+ options.add(IAuthenticator.Option.PASSWORD);
+
+ dataResource = new HashSet<DataResource>();
+ dataResource.add(DataResource.columnFamily("system_auth", "credentials"));
+ }
+
+ protected static Access access;
+ protected static LocalLur localLur;
+ protected static AAFCon<?> aafcon;
+ protected static AAFAuthn<?> aafAuthn;
+ protected static AbsAAFLur<AAFPermission> aafLur;
+ protected static String default_realm;
+ protected static String cluster_name;
+ protected static String perm_type;
+ private static boolean props_ok = false;
+
+ /**
+ * If you use your own Access Class, this must be called before
+ * "setup()" is invoked by Cassandra.
+ *
+ * Otherwise, it will default to reading Properties CADI style.
+ *
+ * @param access
+ */
+ public static void setAccess(Access access) {
+ AAFBase.access = access;
+ }
+
+
+ public void validateConfiguration() throws ConfigurationException {
+ setup();
+ if(!props_ok) {
+ throw new ConfigurationException("AAF not initialized");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void setup() {
+ if(aafAuthn == null) {
+ try {
+ if(access==null) {
+ String value = System.getProperty(Config.CADI_PROP_FILES, "cadi.properties");
+ Properties initial = new Properties();
+ URL cadi_props = ClassLoader.getSystemResource(value);
+ if(cadi_props == null) {
+ File cp = new File(value);
+ if(cp.exists()) {
+ InputStream is = new FileInputStream(cp);
+ try {
+ initial.load(is);
+ } finally {
+ is.close();
+ }
+ } else {
+ System.out.printf("%s does not exist as File or in Classpath\n",value);
+ initial.setProperty(Config.CADI_PROP_FILES, value);
+ }
+ } else {
+ InputStream is = cadi_props.openStream();
+ try {
+ initial.load(is);
+ } finally {
+ is.close();
+ }
+ }
+ access = new SLF4JAccess(initial);
+ }
+ props_ok = true;
+ if((perm_type = Config.logProp(access, "cass_group_name",null))==null) {
+ props_ok=false;
+ } else {
+ perm_type = perm_type + ".cass";
+ }
+
+ if((cluster_name = Config.logProp(access,"cass_cluster_name",null))==null) {
+ if((cluster_name = DatabaseDescriptor.getClusterName())==null) {
+ props_ok=false;
+ }
+ }
+
+ if((default_realm = Config.logProp(access, Config.AAF_DEFAULT_REALM, null))==null) {
+ props_ok=false;
+ }
+
+ if(props_ok==false) {
+ return;
+ }
+
+ // AAFLur has pool of DME clients as needed, and Caches Client lookups
+ Lur lur = Config.configLur(access);
+ // Loop through to find AAFLur out of possible Lurs, to reuse AAFCon
+ if(lur instanceof EpiLur) {
+ EpiLur elur = (EpiLur)lur;
+ for(int i=0; (lur = elur.get(i))!=null;++i) {
+ if(lur instanceof AbsAAFLur) {
+ aafLur=(AbsAAFLur<AAFPermission>)lur;
+ aafcon = aafLur.aaf;
+ aafAuthn = aafLur.aaf.newAuthn(aafLur);
+ break;
+ } else if(lur instanceof LocalLur) {
+ localLur = (LocalLur)lur;
+ }
+ }
+ } else if(lur instanceof AbsAAFLur) {
+ aafLur=(AbsAAFLur<AAFPermission>)lur;
+ aafcon = aafLur.aaf;
+ aafAuthn = aafLur.aaf.newAuthn(aafLur);
+ }
+ if(aafAuthn==null) {
+ access.log(Level.INIT,"Failed to instantiate full AAF access");
+ props_ok = false;
+ }
+ } catch (Exception e) {
+ aafAuthn=null;
+ if(access!=null)access.log(e, "Failed to initialize AAF");
+ props_ok = false;
+ }
+ }
+ }
+
+ public Set<DataResource> protectedResources() {
+ access.log(Level.DEBUG, "Data Resource asked for: it's",dataResource.isEmpty()?"":"not","empty");
+ return dataResource;
+ }
+
+ public Set<IAuthenticator.Option> supportedOptions() {
+ access.log(Level.DEBUG, "supportedOptions() called");
+ return options;
+ }
+
+ public Set<IAuthenticator.Option> alterableOptions() {
+ access.log(Level.DEBUG, "alterableOptions() called");
+ return options;
+ }
+
+
+}
diff --git a/cass/src/test/java/com/att/aaf/cass/JU_CASS.java b/cass/src/test/java/com/att/aaf/cass/JU_CASS.java
new file mode 100644
index 0000000..f25a6b5
--- /dev/null
+++ b/cass/src/test/java/com/att/aaf/cass/JU_CASS.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.aaf.cass;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cassandra.auth.AuthenticatedUser;
+import org.apache.cassandra.auth.IResource;
+import org.apache.cassandra.auth.Permission;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.att.cadi.aaf.cass.AAFAuthenticator;
+import com.att.cadi.aaf.cass.AAFAuthorizer;
+
+public class JU_CASS {
+
+ private static AAFAuthenticator aa;
+ private static AAFAuthorizer an;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ System.setProperty("cadi_prop_files", "etc/cadi.properties");
+
+ aa = new AAFAuthenticator();
+ an = new AAFAuthorizer();
+
+ aa.setup();
+ an.setup(); // does nothing after aa.
+
+ aa.validateConfiguration();
+
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Test
+ public void test() throws Exception {
+ Map<String,String> creds = new HashMap<String,String>();
+ creds.put("username", "XXX@NS");
+ creds.put("password", "enc:???");
+ AuthenticatedUser aaf = aa.authenticate(creds);
+
+ // Test out "aaf_default_domain
+ creds.put("username", "XX");
+ aaf = aa.authenticate(creds);
+
+ IResource resource = new IResource() {
+ public String getName() {
+ return "data/authz";
+ }
+
+ public IResource getParent() {
+ return null;
+ }
+
+ public boolean hasParent() {
+ return false;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ };
+
+ Set<Permission> perms = an.authorize(aaf, resource);
+
+ // Test out "AAF" access
+ creds.put("username", "XXX@NS");
+ creds.put("password", "enc:???");
+ aaf = aa.authenticate(creds);
+ perms = an.authorize(aaf, resource);
+ Assert.assertFalse(perms.isEmpty());
+
+ perms = an.authorize(aaf, resource);
+ Assert.assertFalse(perms.isEmpty());
+
+ }
+
+}
diff --git a/cass/src/test/java/com/att/cadi/aaf/cass/test/JU_CASS.java b/cass/src/test/java/com/att/cadi/aaf/cass/test/JU_CASS.java
new file mode 100644
index 0000000..9bfc17e
--- /dev/null
+++ b/cass/src/test/java/com/att/cadi/aaf/cass/test/JU_CASS.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.cadi.aaf.cass.test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cassandra.auth.AuthenticatedUser;
+import org.apache.cassandra.auth.IResource;
+import org.apache.cassandra.auth.Permission;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.att.cadi.aaf.cass.AAFAuthenticator;
+import com.att.cadi.aaf.cass.AAFAuthorizer;
+
+public class JU_CASS {
+
+ private static AAFAuthenticator aa;
+ private static AAFAuthorizer an;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ System.setProperty("cadi_prop_files", "etc/cadi.properties");
+
+ aa = new AAFAuthenticator();
+ an = new AAFAuthorizer();
+
+ aa.setup();
+ an.setup(); // does nothing after aa.
+
+ aa.validateConfiguration();
+
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ }
+
+ @Test
+ public void test() throws Exception {
+ Map<String,String> creds = new HashMap<String,String>();
+ creds.put("username", "XXX@NS");
+ creds.put("password", "enc:???");
+ AuthenticatedUser aaf = aa.authenticate(creds);
+
+ // Test out "aaf_default_domain
+ creds.put("username", "XX");
+ aaf = aa.authenticate(creds);
+
+ IResource resource = new IResource() {
+ public String getName() {
+ return "data/authz";
+ }
+
+ public IResource getParent() {
+ return null;
+ }
+
+ public boolean hasParent() {
+ return false;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ };
+
+ Set<Permission> perms = an.authorize(aaf, resource);
+
+ // Test out "AAF" access
+ creds.put("username", "XXX@NS");
+ creds.put("password", "enc:???");
+ aaf = aa.authenticate(creds);
+ perms = an.authorize(aaf, resource);
+ Assert.assertFalse(perms.isEmpty());
+
+ perms = an.authorize(aaf, resource);
+ Assert.assertFalse(perms.isEmpty());
+
+ }
+
+}