aboutsummaryrefslogtreecommitdiffstats
path: root/odl-aaa-moon/aaa-authn-mdsal-store
diff options
context:
space:
mode:
Diffstat (limited to 'odl-aaa-moon/aaa-authn-mdsal-store')
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml99
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/src/main/yang/aaa-authn-model.yang154
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml40
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/src/main/resources/initial/08-authn-config.xml43
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml169
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/AuthNStore.java263
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypter.java101
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMMDSALStore.java483
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMObject2MDSAL.java224
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMStore.java182
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtil.java140
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModule.java90
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModuleFactory.java46
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/yang/aaa-authn-mdsal-store-cfg.yang77
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataBrokerReadMocker.java112
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypterTest.java38
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTest.java175
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTestUtil.java181
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/MDSALConvertTest.java78
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtilTest.java88
-rw-r--r--odl-aaa-moon/aaa-authn-mdsal-store/pom.xml22
21 files changed, 2805 insertions, 0 deletions
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml
new file mode 100644
index 00000000..fede7e5e
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>0.3.1-Beryllium-SR1</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>aaa-authn-mdsal-api</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-authn-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${bundle.plugin.version}</version>
+ <extensions>true</extensions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <stylesheet>maven</stylesheet>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>aggregate</goal>
+ </goals>
+ <phase>site</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+ </codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ <packaging>bundle</packaging>
+
+</project>
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/src/main/yang/aaa-authn-model.yang b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/src/main/yang/aaa-authn-model.yang
new file mode 100644
index 00000000..227cb313
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-api/src/main/yang/aaa-authn-model.yang
@@ -0,0 +1,154 @@
+module aaa-authn-model {
+ yang-version 1;
+ namespace "urn:aaa:yang:authn:claims";
+ prefix "authn";
+ organization "TBD";
+
+ contact "wdec@cisco.com";
+
+ revision 2014-10-29 {
+ description
+ "Initial revision.";
+ }
+
+//Main module begins
+
+// Following container provides the AuthN Claims data-structure
+
+ container tokencache {
+ config false;
+ list claims {
+ key "token";
+
+ leaf token {
+ type string;
+ description "Token";
+ }
+ leaf clientId {
+ type string;
+ description "id of the authorized client, or null if anonymous";
+ }
+ leaf userId {
+ type string;
+ description "Unique user-id. User IDs are system-created";
+ }
+ leaf user {
+ type string;
+ description "User name";
+ }
+ leaf domain {
+ type string;
+ description "Fully-qualified domain name";
+ }
+ leaf-list roles {
+ type string;
+ description "Assigned user roles";
+ }
+ }
+ }
+
+ container token_cache_times {
+
+ list token_list {
+ key userId;
+
+ leaf userId {
+ //TODO: Change to instance-ref
+ type string;
+ }
+
+ list user_tokens {
+ key tokenid;
+ leaf tokenid {
+ type leafref {path "/tokencache/claims/token";}
+ }
+ leaf timestamp {
+ type uint64;
+ }
+ leaf expiration {
+ type int64;
+ description "Expiration milliseconds since start of UTC epoch";
+ }
+ }
+ }
+ }
+
+ //authentication model is for generating objects to be stores in the
+ //data store for all the prev idm model objects.
+ container authentication{
+ list domain{
+ key domainid;
+ leaf domainid {
+ type string;
+ }
+ leaf name {
+ type string;
+ }
+ leaf description {
+ type string;
+ }
+ leaf enabled {
+ type boolean;
+ }
+ }
+
+ list user {
+ key userid;
+ leaf userid {
+ type string;
+ }
+ leaf name {
+ type string;
+ }
+ leaf description {
+ type string;
+ }
+ leaf enabled {
+ type boolean;
+ }
+ leaf email {
+ type string;
+ }
+ leaf password {
+ type string;
+ }
+ leaf salt {
+ type string;
+ }
+ leaf domainid {
+ type string;
+ }
+ }
+ list role {
+ key roleid;
+ leaf roleid {
+ type string;
+ }
+ leaf name {
+ type string;
+ }
+ leaf description {
+ type string;
+ }
+ leaf domainid {
+ type string;
+ }
+ }
+
+ list grant {
+ key grantid;
+ leaf grantid {
+ type string;
+ }
+ leaf domainid {
+ type string;
+ }
+ leaf userid {
+ type string;
+ }
+ leaf roleid {
+ type string;
+ }
+ }
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml
new file mode 100644
index 00000000..f01969a4
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml
@@ -0,0 +1,40 @@
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>0.3.1-Beryllium-SR1</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>aaa-authn-mdsal-config</artifactId>
+ <description>AuthN Token Store Service Configuration file </description>
+ <packaging>jar</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/${config.authn.store.configfile}</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/src/main/resources/initial/08-authn-config.xml b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/src/main/resources/initial/08-authn-config.xml
new file mode 100644
index 00000000..e4a78f4d
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-config/src/main/resources/initial/08-authn-config.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+ <!-- defines an implementation module -->
+ <module>
+ <type xmlns:authn="config:aaa:authn:mdsal:store">authn:aaa-authn-mdsal-store</type>
+ <name>aaa-authn-mdsal-store</name>
+ <dom-broker>
+ <type xmlns:dom="urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom">
+ dom:dom-broker-osgi-registry
+ </type>
+ <name>dom-broker</name>
+ </dom-broker>
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-async-data-broker
+ </type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ <timeToLive>3600000</timeToLive>
+ <timeToWait>15</timeToWait>
+ <password>CHANGE_ME</password>
+ </module>
+ </modules>
+ </data>
+
+ </configuration>
+ <required-capabilities>
+ <capability>config:aaa:authn:mdsal:store?module=aaa-authn-mdsal-store-cfg&amp;revision=2014-10-31</capability>
+ </required-capabilities>
+
+</snapshot>
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml
new file mode 100644
index 00000000..c36febee
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ ~
+ -->
+
+<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">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>0.3.1-Beryllium-SR1</version>
+ <relativePath>../../parent</relativePath>
+ </parent>
+
+ <artifactId>aaa-authn-mdsal-store-impl</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <powermock.version>1.5.2</powermock.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-authn-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-authn</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-authn-mdsal-api</artifactId>
+ </dependency>
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <!-- <Bundle-Activator>/Bundle-Activator> -->
+ <Export-Package>org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.*
+ </Export-Package>
+ </instructions>
+ </configuration>
+ <!-- <configuration> <Export-Package> </Export-Package> </configuration> -->
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>
+ org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ </codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>
+ urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
+ </namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>yang-jmx-generator-plugin</artifactId>
+ <version>${config.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/AuthNStore.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/AuthNStore.java
new file mode 100644
index 00000000..09170182
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/AuthNStore.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import java.math.BigInteger;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.opendaylight.aaa.api.Authentication;
+import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.authn.mdsal.store.util.AuthNStoreUtil;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.TokenCacheTimes;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.TokenList;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.TokenListKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.token_list.UserTokens;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.Claims;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AuthNStore implements AutoCloseable, TokenStore {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AuthNStore.class);
+ private DataBroker broker;
+ private static BigInteger timeToLive;
+ private static Integer timeToWait;
+ private final ExecutorService deleteExpiredTokenThread = Executors.newFixedThreadPool(1);
+ private final DataEncrypter dataEncrypter;
+
+ public AuthNStore(final DataBroker dataBroker, final String config_key) {
+ this.broker = dataBroker;
+ this.dataEncrypter = new DataEncrypter(config_key);
+ LOG.info("Created MD-SAL AAA Token Cache Service...");
+ }
+
+ @Override
+ public void close() throws Exception {
+ deleteExpiredTokenThread.shutdown();
+ LOG.info("MD-SAL AAA Token Cache closed...");
+
+ }
+
+ @Override
+ public void put(String token, Authentication auth) {
+ token = dataEncrypter.encrypt(token);
+ Claims claims = AuthNStoreUtil.createClaimsRecord(token, auth);
+
+ // create and insert parallel struct
+ UserTokens userTokens = AuthNStoreUtil.createUserTokens(token, timeToLive.longValue());
+ TokenList tokenlist = AuthNStoreUtil.createTokenList(userTokens, auth.userId());
+
+ writeClaimAndTokenToStore(claims, userTokens, tokenlist);
+ deleteExpiredTokenThread.execute(deleteOldTokens(claims));
+ }
+
+ @Override
+ public Authentication get(String token) {
+ token = dataEncrypter.encrypt(token);
+ Authentication authentication = null;
+ Claims claims = readClaims(token);
+ if (claims != null) {
+ UserTokens userToken = readUserTokensFromDS(claims.getToken(), claims.getUserId());
+ authentication = AuthNStoreUtil.convertClaimToAuthentication(claims,
+ userToken.getExpiration());
+ }
+ deleteExpiredTokenThread.execute(deleteOldTokens(claims));
+ return authentication;
+ }
+
+ @Override
+ public boolean delete(String token) {
+ token = dataEncrypter.encrypt(token);
+ boolean result = false;
+ Claims claims = readClaims(token);
+ result = deleteClaims(token);
+ if (result) {
+ deleteUserTokenFromDS(token, claims.getUserId());
+ }
+ deleteExpiredTokenThread.execute(deleteOldTokens(claims));
+ return result;
+ }
+
+ @Override
+ public long tokenExpiration() {
+ return timeToLive.longValue();
+ }
+
+ public void setTimeToLive(BigInteger timeToLive) {
+ this.timeToLive = timeToLive;
+ }
+
+ public void setTimeToWait(Integer timeToWait) {
+ this.timeToWait = timeToWait;
+ }
+
+ private void writeClaimAndTokenToStore(final Claims claims, UserTokens usertokens,
+ final TokenList tokenlist) {
+
+ final InstanceIdentifier<Claims> claims_iid = AuthNStoreUtil.createInstIdentifierForTokencache(claims.getToken());
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(LogicalDatastoreType.OPERATIONAL, claims_iid, claims, true);
+
+ final InstanceIdentifier<UserTokens> userTokens_iid = AuthNStoreUtil.createInstIdentifierUserTokens(
+ tokenlist.getUserId(), usertokens.getTokenid());
+ tx.put(LogicalDatastoreType.OPERATIONAL, userTokens_iid, usertokens, true);
+
+ CheckedFuture<Void, TransactionCommitFailedException> commitFuture = tx.submit();
+ Futures.addCallback(commitFuture, new FutureCallback<Void>() {
+
+ @Override
+ public void onSuccess(Void result) {
+ LOG.trace("Token {} was written to datastore.", claims.getToken());
+ LOG.trace("Tokenlist for userId {} was written to datastore.",
+ tokenlist.getUserId());
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.error("Inserting token {} to datastore failed.", claims.getToken());
+ LOG.trace("Inserting for userId {} tokenlist to datastore failed.",
+ tokenlist.getUserId());
+ }
+
+ });
+ }
+
+ private Claims readClaims(String token) {
+ final InstanceIdentifier<Claims> claims_iid = AuthNStoreUtil.createInstIdentifierForTokencache(token);
+ Claims claims = null;
+ ReadTransaction rt = broker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Claims>, ReadFailedException> claimsFuture = rt.read(
+ LogicalDatastoreType.OPERATIONAL, claims_iid);
+ try {
+ Optional<Claims> maybeClaims = claimsFuture.checkedGet();
+ if (maybeClaims.isPresent()) {
+ claims = maybeClaims.get();
+ }
+ } catch (ReadFailedException e) {
+ LOG.error(
+ "Something wrong happened in DataStore. Getting Claim for token {} failed.",
+ token, e);
+ }
+ return claims;
+ }
+
+ private TokenList readTokenListFromDS(String userId) {
+ InstanceIdentifier<TokenList> tokenList_iid = InstanceIdentifier.builder(
+ TokenCacheTimes.class).child(TokenList.class, new TokenListKey(userId)).build();
+ TokenList tokenList = null;
+ ReadTransaction rt = broker.newReadOnlyTransaction();
+ CheckedFuture<Optional<TokenList>, ReadFailedException> userTokenListFuture = rt.read(
+ LogicalDatastoreType.OPERATIONAL, tokenList_iid);
+ try {
+ Optional<TokenList> maybeTokenList = userTokenListFuture.checkedGet();
+ if (maybeTokenList.isPresent()) {
+ tokenList = maybeTokenList.get();
+ }
+ } catch (ReadFailedException e) {
+ LOG.error(
+ "Something wrong happened in DataStore. Getting TokenList for userId {} failed.",
+ userId, e);
+ }
+ return tokenList;
+ }
+
+ private UserTokens readUserTokensFromDS(String token, String userId) {
+ final InstanceIdentifier<UserTokens> userTokens_iid = AuthNStoreUtil.createInstIdentifierUserTokens(
+ userId, token);
+ UserTokens userTokens = null;
+
+ ReadTransaction rt = broker.newReadOnlyTransaction();
+ CheckedFuture<Optional<UserTokens>, ReadFailedException> userTokensFuture = rt.read(
+ LogicalDatastoreType.OPERATIONAL, userTokens_iid);
+
+ try {
+ Optional<UserTokens> maybeUserTokens = userTokensFuture.checkedGet();
+ if (maybeUserTokens.isPresent()) {
+ userTokens = maybeUserTokens.get();
+ }
+ } catch (ReadFailedException e) {
+ LOG.error(
+ "Something wrong happened in DataStore. Getting UserTokens for token {} failed.",
+ token, e);
+ }
+
+ return userTokens;
+ }
+
+ private boolean deleteClaims(String token) {
+ final InstanceIdentifier<Claims> claims_iid = AuthNStoreUtil.createInstIdentifierForTokencache(token);
+ boolean result = false;
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(LogicalDatastoreType.OPERATIONAL, claims_iid);
+ CheckedFuture<Void, TransactionCommitFailedException> commitFuture = tx.submit();
+
+ try {
+ commitFuture.checkedGet();
+ result = true;
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Something wrong happened in DataStore. Claim "
+ + "deletion for token {} from DataStore failed.", token, e);
+ }
+ return result;
+ }
+
+ private void deleteUserTokenFromDS(String token, String userId) {
+ final InstanceIdentifier<UserTokens> userTokens_iid = AuthNStoreUtil.createInstIdentifierUserTokens(
+ userId, token);
+
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(LogicalDatastoreType.OPERATIONAL, userTokens_iid);
+ CheckedFuture<Void, TransactionCommitFailedException> commitFuture = tx.submit();
+ try {
+ commitFuture.checkedGet();
+ } catch (TransactionCommitFailedException e) {
+ LOG.error("Something wrong happened in DataStore. UserToken "
+ + "deletion for token {} from DataStore failed.", token, e);
+ }
+ }
+
+ private Runnable deleteOldTokens(final Claims claims) {
+ return new Runnable() {
+
+ @Override
+ public void run() {
+ TokenList tokenList = null;
+ if (claims != null) {
+ tokenList = readTokenListFromDS(claims.getUserId());
+ }
+ if (tokenList != null) {
+ for (UserTokens currUserToken : tokenList.getUserTokens()) {
+ long diff = System.currentTimeMillis()
+ - currUserToken.getTimestamp().longValue();
+ if (diff > currUserToken.getExpiration()
+ && currUserToken.getExpiration() != 0) {
+ if (deleteClaims(currUserToken.getTokenid())) {
+ deleteUserTokenFromDS(currUserToken.getTokenid(),
+ claims.getUserId());
+ LOG.trace("Expired tokens for UserId {} deleted.",
+ claims.getUserId());
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypter.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypter.java
new file mode 100644
index 00000000..ca0a74be
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypter.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import java.security.spec.KeySpec;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author - Sharon Aicler (saichler@cisco.com)
+ **/
+public class DataEncrypter {
+
+ final protected SecretKey k;
+ private static final Logger LOG = LoggerFactory.getLogger(DataEncrypter.class);
+ private static final byte[] iv = { 0, 5, 0, 0, 7, 81, 0, 3, 0, 0, 0, 0, 0, 43, 0, 1 };
+ private static final IvParameterSpec ivspec = new IvParameterSpec(iv);
+ public static final String ENCRYPTED_TAG = "Encrypted:";
+
+ public DataEncrypter(final String ckey) {
+ SecretKey tmp = null;
+ if (ckey != null && !ckey.isEmpty()) {
+
+ try {
+ SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
+ KeySpec spec = new PBEKeySpec(ckey.toCharArray(), iv, 32768, 128);
+ tmp = keyFactory.generateSecret(spec);
+ } catch (Exception e) {
+ LOG.error("Couldn't initialize key factory", e);
+ }
+ if (tmp != null) {
+ k = new SecretKeySpec(tmp.getEncoded(), "AES");
+ } else {
+ throw new RuntimeException("Couldn't initalize encryption key");
+ }
+ } else {
+ k = null;
+ LOG.warn("Void crypto key passed! AuthN Store Encryption disabled");
+ }
+
+ }
+
+ protected String encrypt(String token) {
+
+ if (k == null) {
+ return token;
+ }
+
+ String cryptostring = null;
+ try {
+ Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ c.init(Cipher.ENCRYPT_MODE, k, ivspec);
+ byte[] cryptobytes = c.doFinal(token.getBytes());
+ cryptostring = DatatypeConverter.printBase64Binary(cryptobytes);
+ return ENCRYPTED_TAG + cryptostring;
+ } catch (Exception e) {
+ LOG.error("Couldn't encrypt token", e);
+ return null;
+ }
+ }
+
+ protected String decrypt(String eToken) {
+ if (k == null) {
+ return eToken;
+ }
+
+ if (eToken == null || eToken.length() == 0) {
+ return null;
+ }
+
+ if (!eToken.startsWith(ENCRYPTED_TAG)) {
+ return eToken;
+ }
+
+ try {
+ Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ c.init(Cipher.DECRYPT_MODE, k, ivspec);
+
+ byte[] cryptobytes = DatatypeConverter.parseBase64Binary(eToken.substring(ENCRYPTED_TAG.length()));
+ byte[] clearbytes = c.doFinal(cryptobytes);
+ return DatatypeConverter.printBase64Binary(clearbytes);
+
+ } catch (Exception e) {
+ LOG.error("Couldn't decrypt token", e);
+ return null;
+ }
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMMDSALStore.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMMDSALStore.java
new file mode 100644
index 00000000..88fba0ba
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMMDSALStore.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.aaa.api.IDMStoreException;
+import org.opendaylight.aaa.api.IDMStoreUtil;
+import org.opendaylight.aaa.api.SHA256Calculator;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.Authentication;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Sharon Aicler - saichler@cisco.com
+ *
+ */
+public class IDMMDSALStore {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IDMMDSALStore.class);
+ private final DataBroker dataBroker;
+
+ public IDMMDSALStore(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public static final String getString(String aValue, String bValue) {
+ if (aValue != null)
+ return aValue;
+ return bValue;
+ }
+
+ public static final Boolean getBoolean(Boolean aValue, Boolean bValue) {
+ if (aValue != null)
+ return aValue;
+ return bValue;
+ }
+
+ public static boolean waitForSubmit(CheckedFuture<Void, TransactionCommitFailedException> submit) {
+ // This can happen only when testing
+ if (submit == null)
+ return false;
+ while (!submit.isDone() && !submit.isCancelled()) {
+ try {
+ Thread.sleep(1000);
+ } catch (Exception err) {
+ LOG.error("Interrupted", err);
+ }
+ }
+ return submit.isCancelled();
+ }
+
+ // Domain methods
+ public Domain writeDomain(Domain domain) {
+ Preconditions.checkNotNull(domain);
+ Preconditions.checkNotNull(domain.getName());
+ Preconditions.checkNotNull(domain.isEnabled());
+ DomainBuilder b = new DomainBuilder();
+ b.setDescription(domain.getDescription());
+ b.setDomainid(domain.getName());
+ b.setEnabled(domain.isEnabled());
+ b.setName(domain.getName());
+ b.setKey(new DomainKey(b.getName()));
+ domain = b.build();
+ InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
+ Domain.class, new DomainKey(domain.getDomainid()));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.put(LogicalDatastoreType.CONFIGURATION, ID, domain, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
+ if (!waitForSubmit(submit)) {
+ return domain;
+ } else {
+ return null;
+ }
+ }
+
+ public Domain readDomain(String domainid) {
+ Preconditions.checkNotNull(domainid);
+ InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
+ Domain.class, new DomainKey(domainid));
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Domain>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, ID);
+ if (read == null) {
+ LOG.error("Failed to read domain from data store");
+ return null;
+ }
+ Optional<Domain> optional = null;
+ try {
+ optional = read.get();
+ } catch (InterruptedException | ExecutionException e1) {
+ LOG.error("Failed to read domain from data store", e1);
+ return null;
+ }
+
+ if (optional == null)
+ return null;
+
+ if (!optional.isPresent())
+ return null;
+
+ return optional.get();
+ }
+
+ public Domain deleteDomain(String domainid) {
+ Preconditions.checkNotNull(domainid);
+ Domain domain = readDomain(domainid);
+ if (domain == null) {
+ LOG.error("Failed to delete domain from data store, unknown domain");
+ return null;
+ }
+ InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
+ Domain.class, new DomainKey(domainid));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
+ wrt.submit();
+ return domain;
+ }
+
+ public Domain updateDomain(Domain domain) throws IDMStoreException {
+ Preconditions.checkNotNull(domain);
+ Preconditions.checkNotNull(domain.getDomainid());
+ Domain existing = readDomain(domain.getDomainid());
+ DomainBuilder b = new DomainBuilder();
+ b.setDescription(getString(domain.getDescription(), existing.getDescription()));
+ b.setName(existing.getName());
+ b.setEnabled(getBoolean(domain.isEnabled(), existing.isEnabled()));
+ return writeDomain(b.build());
+ }
+
+ public List<Domain> getAllDomains() {
+ InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, id);
+ if (read == null)
+ return null;
+
+ try {
+ if (read.get() == null)
+ return null;
+ if (read.get().isPresent()) {
+ Authentication auth = read.get().get();
+ return auth.getDomain();
+ }
+ } catch (Exception err) {
+ LOG.error("Failed to read domains", err);
+ }
+ return null;
+ }
+
+ public List<Role> getAllRoles() {
+ InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, id);
+ if (read == null)
+ return null;
+
+ try {
+ if (read.get() == null)
+ return null;
+ if (read.get().isPresent()) {
+ Authentication auth = read.get().get();
+ return auth.getRole();
+ }
+ } catch (Exception err) {
+ LOG.error("Failed to read domains", err);
+ }
+ return null;
+ }
+
+ public List<User> getAllUsers() {
+ InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, id);
+ if (read == null)
+ return null;
+
+ try {
+ if (read.get() == null)
+ return null;
+ if (read.get().isPresent()) {
+ Authentication auth = read.get().get();
+ return auth.getUser();
+ }
+ } catch (Exception err) {
+ LOG.error("Failed to read domains", err);
+ }
+ return null;
+ }
+
+ public List<Grant> getAllGrants() {
+ InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, id);
+ if (read == null)
+ return null;
+
+ try {
+ if (read.get() == null)
+ return null;
+ if (read.get().isPresent()) {
+ Authentication auth = read.get().get();
+ return auth.getGrant();
+ }
+ } catch (Exception err) {
+ LOG.error("Failed to read domains", err);
+ }
+ return null;
+ }
+
+ // Role methods
+ public Role writeRole(Role role) {
+ Preconditions.checkNotNull(role);
+ Preconditions.checkNotNull(role.getName());
+ Preconditions.checkNotNull(role.getDomainid());
+ Preconditions.checkNotNull(readDomain(role.getDomainid()));
+ RoleBuilder b = new RoleBuilder();
+ b.setDescription(role.getDescription());
+ b.setRoleid(IDMStoreUtil.createRoleid(role.getName(), role.getDomainid()));
+ b.setKey(new RoleKey(b.getRoleid()));
+ b.setName(role.getName());
+ b.setDomainid(role.getDomainid());
+ role = b.build();
+ InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
+ Role.class, new RoleKey(role.getRoleid()));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.put(LogicalDatastoreType.CONFIGURATION, ID, role, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
+ if (!waitForSubmit(submit)) {
+ return role;
+ } else {
+ return null;
+ }
+ }
+
+ public Role readRole(String roleid) {
+ Preconditions.checkNotNull(roleid);
+ InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
+ Role.class, new RoleKey(roleid));
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Role>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, ID);
+ if (read == null) {
+ LOG.error("Failed to read role from data store");
+ return null;
+ }
+ Optional<Role> optional = null;
+ try {
+ optional = read.get();
+ } catch (InterruptedException | ExecutionException e1) {
+ LOG.error("Failed to read role from data store", e1);
+ return null;
+ }
+
+ if (optional == null)
+ return null;
+
+ if (!optional.isPresent())
+ return null;
+
+ return optional.get();
+ }
+
+ public Role deleteRole(String roleid) {
+ Preconditions.checkNotNull(roleid);
+ Role role = readRole(roleid);
+ if (role == null) {
+ LOG.error("Failed to delete role from data store, unknown role");
+ return null;
+ }
+ InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
+ Role.class, new RoleKey(roleid));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
+ wrt.submit();
+ return role;
+ }
+
+ public Role updateRole(Role role) {
+ Preconditions.checkNotNull(role);
+ Preconditions.checkNotNull(role.getRoleid());
+ Role existing = readRole(role.getRoleid());
+ RoleBuilder b = new RoleBuilder();
+ b.setDescription(getString(role.getDescription(), existing.getDescription()));
+ b.setName(existing.getName());
+ b.setDomainid(existing.getDomainid());
+ return writeRole(b.build());
+ }
+
+ // User methods
+ public User writeUser(User user) throws IDMStoreException {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(user.getName());
+ Preconditions.checkNotNull(user.getDomainid());
+ Preconditions.checkNotNull(readDomain(user.getDomainid()));
+ UserBuilder b = new UserBuilder();
+ if (user.getSalt() == null) {
+ b.setSalt(SHA256Calculator.generateSALT());
+ } else {
+ b.setSalt(user.getSalt());
+ }
+ b.setUserid(IDMStoreUtil.createUserid(user.getName(), user.getDomainid()));
+ b.setDescription(user.getDescription());
+ b.setDomainid(user.getDomainid());
+ b.setEmail(user.getEmail());
+ b.setEnabled(user.isEnabled());
+ b.setKey(new UserKey(b.getUserid()));
+ b.setName(user.getName());
+ b.setPassword(SHA256Calculator.getSHA256(user.getPassword(), b.getSalt()));
+ user = b.build();
+ InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
+ User.class, new UserKey(user.getUserid()));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.put(LogicalDatastoreType.CONFIGURATION, ID, user, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
+ if (!waitForSubmit(submit)) {
+ return user;
+ } else {
+ return null;
+ }
+ }
+
+ public User readUser(String userid) {
+ Preconditions.checkNotNull(userid);
+ InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
+ User.class, new UserKey(userid));
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<User>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, ID);
+ if (read == null) {
+ LOG.error("Failed to read user from data store");
+ return null;
+ }
+ Optional<User> optional = null;
+ try {
+ optional = read.get();
+ } catch (InterruptedException | ExecutionException e1) {
+ LOG.error("Failed to read domain from data store", e1);
+ return null;
+ }
+
+ if (optional == null)
+ return null;
+
+ if (!optional.isPresent())
+ return null;
+
+ return optional.get();
+ }
+
+ public User deleteUser(String userid) {
+ Preconditions.checkNotNull(userid);
+ User user = readUser(userid);
+ if (user == null) {
+ LOG.error("Failed to delete user from data store, unknown user");
+ return null;
+ }
+ InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
+ User.class, new UserKey(userid));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
+ wrt.submit();
+ return user;
+ }
+
+ public User updateUser(User user) throws IDMStoreException {
+ Preconditions.checkNotNull(user);
+ Preconditions.checkNotNull(user.getUserid());
+ User existing = readUser(user.getUserid());
+ UserBuilder b = new UserBuilder();
+ b.setName(existing.getName());
+ b.setDomainid(existing.getDomainid());
+ b.setDescription(getString(user.getDescription(), existing.getDescription()));
+ b.setEmail(getString(user.getEmail(), existing.getEmail()));
+ b.setEnabled(getBoolean(user.isEnabled(), existing.isEnabled()));
+ b.setPassword(getString(user.getPassword(), existing.getPassword()));
+ b.setSalt(getString(user.getSalt(), existing.getSalt()));
+ return writeUser(b.build());
+ }
+
+ // Grant methods
+ public Grant writeGrant(Grant grant) throws IDMStoreException {
+ Preconditions.checkNotNull(grant);
+ Preconditions.checkNotNull(grant.getDomainid());
+ Preconditions.checkNotNull(grant.getUserid());
+ Preconditions.checkNotNull(grant.getRoleid());
+ Preconditions.checkNotNull(readDomain(grant.getDomainid()));
+ Preconditions.checkNotNull(readUser(grant.getUserid()));
+ Preconditions.checkNotNull(readRole(grant.getRoleid()));
+ GrantBuilder b = new GrantBuilder();
+ b.setDomainid(grant.getDomainid());
+ b.setRoleid(grant.getRoleid());
+ b.setUserid(grant.getUserid());
+ b.setGrantid(IDMStoreUtil.createGrantid(grant.getUserid(), grant.getDomainid(),
+ grant.getRoleid()));
+ b.setKey(new GrantKey(b.getGrantid()));
+ grant = b.build();
+ InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
+ Grant.class, new GrantKey(grant.getGrantid()));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.put(LogicalDatastoreType.CONFIGURATION, ID, grant, true);
+ CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
+ if (!waitForSubmit(submit)) {
+ return grant;
+ } else {
+ return null;
+ }
+ }
+
+ public Grant readGrant(String grantid) {
+ Preconditions.checkNotNull(grantid);
+ InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
+ Grant.class, new GrantKey(grantid));
+ ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
+ CheckedFuture<Optional<Grant>, ReadFailedException> read = rot.read(
+ LogicalDatastoreType.CONFIGURATION, ID);
+ if (read == null) {
+ LOG.error("Failed to read grant from data store");
+ return null;
+ }
+ Optional<Grant> optional = null;
+ try {
+ optional = read.get();
+ } catch (InterruptedException | ExecutionException e1) {
+ LOG.error("Failed to read domain from data store", e1);
+ return null;
+ }
+
+ if (optional == null)
+ return null;
+
+ if (!optional.isPresent())
+ return null;
+
+ return optional.get();
+ }
+
+ public Grant deleteGrant(String grantid) {
+ Preconditions.checkNotNull(grantid);
+ Grant grant = readGrant(grantid);
+ if (grant == null) {
+ LOG.error("Failed to delete grant from data store, unknown grant");
+ return null;
+ }
+ InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
+ Grant.class, new GrantKey(grantid));
+ WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
+ wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
+ wrt.submit();
+ return grant;
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMObject2MDSAL.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMObject2MDSAL.java
new file mode 100644
index 00000000..0b58ced7
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMObject2MDSAL.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.aaa.api.model.Domain;
+import org.opendaylight.aaa.api.model.Grant;
+import org.opendaylight.aaa.api.model.Role;
+import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+/**
+ *
+ * @author saichler@gmail.com
+ *
+ * This class is a codec to convert between MDSAL objects and IDM model objects. It is doing so via reflection when it assumes that the MDSAL
+ * Object and the IDM model object has the same method names.
+ */
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Sharon Aicler - saichler@cisco.com
+ *
+ */
+public abstract class IDMObject2MDSAL {
+ private static final Logger LOG = LoggerFactory.getLogger(IDMObject2MDSAL.class);
+ // this is a Map mapping between the class type of the IDM Model object to a
+ // structure containing the corresponding setters and getter methods
+ // in MDSAL object
+ private static Map<Class<?>, ConvertionMethods> typesMethods = new HashMap<Class<?>, ConvertionMethods>();
+
+ // This method generically via reflection receive a MDSAL object and the
+ // corresponding IDM model object class type and
+ // creates an IDM model element from the MDSAL element
+ private static Object fromMDSALObject(Object mdsalObject, Class<?> type) throws Exception {
+ if (mdsalObject == null)
+ return null;
+ Object result = type.newInstance();
+ ConvertionMethods cm = typesMethods.get(type);
+ if (cm == null) {
+ cm = new ConvertionMethods();
+ typesMethods.put(type, cm);
+ Method methods[] = type.getMethods();
+ for (Method m : methods) {
+ if (m.getName().startsWith("set")) {
+ cm.setMethods.add(m);
+ Method gm = null;
+ if (m.getParameterTypes()[0].equals(Boolean.class)
+ || m.getParameterTypes()[0].equals(boolean.class))
+ gm = ((DataObject) mdsalObject).getImplementedInterface().getMethod(
+ "is" + m.getName().substring(3), (Class[]) null);
+ else {
+ try {
+ gm = ((DataObject) mdsalObject).getImplementedInterface().getMethod(
+ "get" + m.getName().substring(3), (Class[]) null);
+ } catch (Exception err) {
+ LOG.error("Error associating get call", err);
+ }
+ }
+ cm.getMethods.put(m.getName(), gm);
+ }
+ }
+ }
+ for (Method m : cm.setMethods) {
+ try {
+ m.invoke(
+ result,
+ new Object[] { cm.getMethods.get(m.getName()).invoke(mdsalObject,
+ (Object[]) null) });
+ } catch (Exception err) {
+ LOG.error("Error invoking reflection method", err);
+ }
+ }
+ return result;
+ }
+
+ // This method generically use reflection to receive an IDM model object and
+ // the corresponsing MDSAL object and creates
+ // a MDSAL object out of the IDM model object
+ private static Object toMDSALObject(Object object, Class<?> mdSalBuilderType) throws Exception {
+ if (object == null)
+ return null;
+ Object result = mdSalBuilderType.newInstance();
+ ConvertionMethods cm = typesMethods.get(mdSalBuilderType);
+ if (cm == null) {
+ cm = new ConvertionMethods();
+ typesMethods.put(mdSalBuilderType, cm);
+ Method methods[] = mdSalBuilderType.getMethods();
+ for (Method m : methods) {
+ if (m.getName().startsWith("set")) {
+ try {
+ Method gm = null;
+ if (m.getParameterTypes()[0].equals(Boolean.class)
+ || m.getParameterTypes()[0].equals(boolean.class))
+ gm = object.getClass().getMethod("is" + m.getName().substring(3),
+ (Class[]) null);
+ else
+ gm = object.getClass().getMethod("get" + m.getName().substring(3),
+ (Class[]) null);
+ cm.getMethods.put(m.getName(), gm);
+ cm.setMethods.add(m);
+ } catch (NoSuchMethodException err) {
+ }
+ }
+ }
+ cm.builderMethod = mdSalBuilderType.getMethod("build", (Class[]) null);
+ }
+ for (Method m : cm.setMethods) {
+ m.invoke(result,
+ new Object[] { cm.getMethods.get(m.getName()).invoke(object, (Object[]) null) });
+ }
+
+ return cm.builderMethod.invoke(result, (Object[]) null);
+ }
+
+ // A struccture class to hold the getters & setters of each type to speed
+ // things up
+ private static class ConvertionMethods {
+ private List<Method> setMethods = new ArrayList<Method>();
+ private Map<String, Method> getMethods = new HashMap<String, Method>();
+ private Method builderMethod = null;
+ }
+
+ // Convert Domain
+ public static org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain toMDSALDomain(
+ Domain domain) {
+ try {
+ return (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain) toMDSALObject(
+ domain, DomainBuilder.class);
+ } catch (Exception err) {
+ LOG.error("Error converting domain to MDSAL object", err);
+ return null;
+ }
+ }
+
+ public static Domain toIDMDomain(
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain domain) {
+ try {
+ return (Domain) fromMDSALObject(domain, Domain.class);
+ } catch (Exception err) {
+ LOG.error("Error converting domain from MDSAL to IDM object", err);
+ return null;
+ }
+ }
+
+ // Convert Role
+ public static org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role toMDSALRole(
+ Role role) {
+ try {
+ return (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role) toMDSALObject(
+ role, RoleBuilder.class);
+ } catch (Exception err) {
+ LOG.error("Error converting role to MDSAL object", err);
+ return null;
+ }
+ }
+
+ public static Role toIDMRole(
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role role) {
+ try {
+ return (Role) fromMDSALObject(role, Role.class);
+ } catch (Exception err) {
+ LOG.error("Error converting role fom MDSAL to IDM object", err);
+ return null;
+ }
+ }
+
+ // Convert User
+ public static org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User toMDSALUser(
+ User user) {
+ try {
+ return (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User) toMDSALObject(
+ user, UserBuilder.class);
+ } catch (Exception err) {
+ LOG.error("Error converting user to MDSAL object", err);
+ return null;
+ }
+ }
+
+ public static User toIDMUser(
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User user) {
+ try {
+ return (User) fromMDSALObject(user, User.class);
+ } catch (Exception err) {
+ LOG.error("Error converting user from MDSAL to IDM object", err);
+ return null;
+ }
+ }
+
+ // Convert Grant
+ public static org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant toMDSALGrant(
+ Grant grant) {
+ try {
+ return (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant) toMDSALObject(
+ grant, GrantBuilder.class);
+ } catch (Exception err) {
+ LOG.error("Error converting grant to MDSAL object", err);
+ return null;
+ }
+ }
+
+ public static Grant toIDMGrant(
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant grant) {
+ try {
+ return (Grant) fromMDSALObject(grant, Grant.class);
+ } catch (Exception err) {
+ LOG.error("Error converting grant from MDSAL to IDM object", err);
+ return null;
+ }
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMStore.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMStore.java
new file mode 100644
index 00000000..69bc1d52
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/IDMStore.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import java.util.List;
+import org.opendaylight.aaa.api.IDMStoreException;
+import org.opendaylight.aaa.api.IDMStoreUtil;
+import org.opendaylight.aaa.api.IIDMStore;
+import org.opendaylight.aaa.api.model.Domain;
+import org.opendaylight.aaa.api.model.Domains;
+import org.opendaylight.aaa.api.model.Grant;
+import org.opendaylight.aaa.api.model.Grants;
+import org.opendaylight.aaa.api.model.Role;
+import org.opendaylight.aaa.api.model.Roles;
+import org.opendaylight.aaa.api.model.User;
+import org.opendaylight.aaa.api.model.Users;
+
+/**
+ * @author Sharon Aicler - saichler@cisco.com
+ *
+ */
+public class IDMStore implements IIDMStore {
+ private final IDMMDSALStore mdsalStore;
+
+ public IDMStore(IDMMDSALStore mdsalStore) {
+ this.mdsalStore = mdsalStore;
+ }
+
+ @Override
+ public Domain writeDomain(Domain domain) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMDomain(mdsalStore.writeDomain(IDMObject2MDSAL.toMDSALDomain(domain)));
+ }
+
+ @Override
+ public Domain readDomain(String domainid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMDomain(mdsalStore.readDomain(domainid));
+ }
+
+ @Override
+ public Domain deleteDomain(String domainid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMDomain(mdsalStore.deleteDomain(domainid));
+ }
+
+ @Override
+ public Domain updateDomain(Domain domain) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMDomain(mdsalStore.updateDomain(IDMObject2MDSAL.toMDSALDomain(domain)));
+ }
+
+ @Override
+ public Domains getDomains() throws IDMStoreException {
+ Domains domains = new Domains();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain> mdSalDomains = mdsalStore.getAllDomains();
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain d : mdSalDomains) {
+ domains.getDomains().add(IDMObject2MDSAL.toIDMDomain(d));
+ }
+ return domains;
+ }
+
+ @Override
+ public Role writeRole(Role role) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMRole(mdsalStore.writeRole(IDMObject2MDSAL.toMDSALRole(role)));
+ }
+
+ @Override
+ public Role readRole(String roleid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMRole(mdsalStore.readRole(roleid));
+ }
+
+ @Override
+ public Role deleteRole(String roleid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMRole(mdsalStore.deleteRole(roleid));
+ }
+
+ @Override
+ public Role updateRole(Role role) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMRole(mdsalStore.writeRole(IDMObject2MDSAL.toMDSALRole(role)));
+ }
+
+ @Override
+ public User writeUser(User user) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMUser(mdsalStore.writeUser(IDMObject2MDSAL.toMDSALUser(user)));
+ }
+
+ @Override
+ public User readUser(String userid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMUser(mdsalStore.readUser(userid));
+ }
+
+ @Override
+ public User deleteUser(String userid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMUser(mdsalStore.deleteUser(userid));
+ }
+
+ @Override
+ public User updateUser(User user) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMUser(mdsalStore.writeUser(IDMObject2MDSAL.toMDSALUser(user)));
+ }
+
+ @Override
+ public Grant writeGrant(Grant grant) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMGrant(mdsalStore.writeGrant(IDMObject2MDSAL.toMDSALGrant(grant)));
+ }
+
+ @Override
+ public Grant readGrant(String grantid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMGrant(mdsalStore.readGrant(grantid));
+ }
+
+ @Override
+ public Grant deleteGrant(String grantid) throws IDMStoreException {
+ return IDMObject2MDSAL.toIDMGrant(mdsalStore.readGrant(grantid));
+ }
+
+ @Override
+ public Roles getRoles() throws IDMStoreException {
+ Roles roles = new Roles();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role> mdSalRoles = mdsalStore.getAllRoles();
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role r : mdSalRoles) {
+ roles.getRoles().add(IDMObject2MDSAL.toIDMRole(r));
+ }
+ return roles;
+ }
+
+ @Override
+ public Users getUsers() throws IDMStoreException {
+ Users users = new Users();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User> mdSalUsers = mdsalStore.getAllUsers();
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User u : mdSalUsers) {
+ users.getUsers().add(IDMObject2MDSAL.toIDMUser(u));
+ }
+ return users;
+ }
+
+ @Override
+ public Users getUsers(String username, String domain) throws IDMStoreException {
+ Users users = new Users();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User> mdSalUsers = mdsalStore.getAllUsers();
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User u : mdSalUsers) {
+ if (u.getDomainid().equals(domain) && u.getName().equals(username)) {
+ users.getUsers().add(IDMObject2MDSAL.toIDMUser(u));
+ }
+ }
+ return users;
+ }
+
+ @Override
+ public Grants getGrants(String domainid, String userid) throws IDMStoreException {
+ Grants grants = new Grants();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant> mdSalGrants = mdsalStore.getAllGrants();
+ String currentGrantUserId, currentGrantDomainId;
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant g : mdSalGrants) {
+ currentGrantUserId = g.getUserid();
+ currentGrantDomainId = g.getDomainid();
+ if (currentGrantUserId.equals(userid) && currentGrantDomainId.equals(domainid)) {
+ grants.getGrants().add(IDMObject2MDSAL.toIDMGrant(g));
+ }
+ }
+ return grants;
+ }
+
+ @Override
+ public Grants getGrants(String userid) throws IDMStoreException {
+ Grants grants = new Grants();
+ List<org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant> mdSalGrants = mdsalStore.getAllGrants();
+ for (org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant g : mdSalGrants) {
+ if (g.getUserid().equals(userid)) {
+ grants.getGrants().add(IDMObject2MDSAL.toIDMGrant(g));
+ }
+ }
+ return grants;
+ }
+
+ @Override
+ public Grant readGrant(String domainid, String userid, String roleid) throws IDMStoreException {
+ return readGrant(IDMStoreUtil.createGrantid(userid, domainid, roleid));
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtil.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtil.java
new file mode 100644
index 00000000..6ef58109
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtil.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store.util;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.aaa.AuthenticationBuilder;
+import org.opendaylight.aaa.api.Authentication;
+import org.opendaylight.aaa.api.Claim;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.TokenCacheTimes;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.Tokencache;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.TokenList;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.TokenListBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.TokenListKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.token_list.UserTokens;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.token_list.UserTokensBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.token_list.UserTokensKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.Claims;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.ClaimsBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.ClaimsKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AuthNStoreUtil {
+
+ public static InstanceIdentifier<Claims> createInstIdentifierForTokencache(String token) {
+ if (token == null || token.length() == 0)
+ return null;
+
+ InstanceIdentifier<Claims> claims_iid = InstanceIdentifier.builder(Tokencache.class)
+ .child(Claims.class,
+ new ClaimsKey(token))
+ .build();
+ return claims_iid;
+ }
+
+ public static InstanceIdentifier<UserTokens> createInstIdentifierUserTokens(String userId,
+ String token) {
+ if (userId == null || userId.length() == 0 || token == null || token.length() == 0)
+ return null;
+
+ InstanceIdentifier<UserTokens> userTokens_iid = InstanceIdentifier.builder(
+ TokenCacheTimes.class)
+ .child(TokenList.class,
+ new TokenListKey(
+ userId))
+ .child(UserTokens.class,
+ new UserTokensKey(
+ token))
+ .build();
+ return userTokens_iid;
+ }
+
+ public static Claims createClaimsRecord(String token, Authentication auth) {
+ if (auth == null || token == null || token.length() == 0)
+ return null;
+
+ ClaimsKey claimsKey = new ClaimsKey(token);
+ ClaimsBuilder claimsBuilder = new ClaimsBuilder();
+ claimsBuilder.setClientId(auth.clientId());
+ claimsBuilder.setDomain(auth.domain());
+ claimsBuilder.setKey(claimsKey);
+ List<String> roles = new ArrayList<String>();
+ roles.addAll(auth.roles());
+ claimsBuilder.setRoles(roles);
+ claimsBuilder.setToken(token);
+ claimsBuilder.setUser(auth.user());
+ claimsBuilder.setUserId(auth.userId());
+ return claimsBuilder.build();
+ }
+
+ public static UserTokens createUserTokens(String token, Long expiration) {
+ if (expiration == null || token == null || token.length() == 0)
+ return null;
+
+ UserTokensBuilder userTokensBuilder = new UserTokensBuilder();
+ userTokensBuilder.setTokenid(token);
+ BigInteger timestamp = BigInteger.valueOf(System.currentTimeMillis());
+ userTokensBuilder.setTimestamp(timestamp);
+ userTokensBuilder.setExpiration(expiration);
+ userTokensBuilder.setKey(new UserTokensKey(token));
+ return userTokensBuilder.build();
+ }
+
+ public static TokenList createTokenList(UserTokens tokens, String userId) {
+ if (tokens == null || userId == null || userId.length() == 0)
+ return null;
+
+ TokenListBuilder tokenListBuilder = new TokenListBuilder();
+ tokenListBuilder.setUserId(userId);
+ tokenListBuilder.setKey(new TokenListKey(userId));
+ List<UserTokens> userTokens = new ArrayList<UserTokens>();
+ userTokens.add(tokens);
+ tokenListBuilder.setUserTokens(userTokens);
+ return tokenListBuilder.build();
+ }
+
+ public static Authentication convertClaimToAuthentication(final Claims claims, Long expiration) {
+ if (claims == null)
+ return null;
+
+ Claim claim = new Claim() {
+ @Override
+ public String clientId() {
+ return claims.getClientId();
+ }
+
+ @Override
+ public String userId() {
+ return claims.getUserId();
+ }
+
+ @Override
+ public String user() {
+ return claims.getUser();
+ }
+
+ @Override
+ public String domain() {
+ return claims.getDomain();
+ }
+
+ @Override
+ public Set<String> roles() {
+ return new HashSet<>(claims.getRoles());
+ }
+ };
+ AuthenticationBuilder authBuilder = new AuthenticationBuilder(claim);
+ authBuilder.setExpiration(expiration);
+ return authBuilder.build();
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModule.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModule.java
new file mode 100644
index 00000000..0631170e
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModule.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+package org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.rev141031;
+
+import org.opendaylight.aaa.api.IIDMStore;
+import org.opendaylight.aaa.api.TokenStore;
+import org.opendaylight.aaa.authn.mdsal.store.AuthNStore;
+import org.opendaylight.aaa.authn.mdsal.store.IDMMDSALStore;
+import org.opendaylight.aaa.authn.mdsal.store.IDMStore;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class AuthNStoreModule
+ extends
+ org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.rev141031.AbstractAuthNStoreModule {
+ private BundleContext bundleContext;
+
+ public AuthNStoreModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public AuthNStoreModule(
+ org.opendaylight.controller.config.api.ModuleIdentifier identifier,
+ org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.rev141031.AuthNStoreModule oldModule,
+ java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+
+ DataBroker dataBrokerService = getDataBrokerDependency();
+ final AuthNStore authNStore = new AuthNStore(dataBrokerService, getPassword());
+ final IDMMDSALStore mdsalStore = new IDMMDSALStore(dataBrokerService);
+ final IDMStore idmStore = new IDMStore(mdsalStore);
+
+ authNStore.setTimeToLive(getTimeToLive());
+
+ // Register the MD-SAL Token store with OSGI
+ final ServiceRegistration<?> serviceRegistration = bundleContext.registerService(
+ TokenStore.class.getName(), authNStore, null);
+ final ServiceRegistration<?> idmServiceRegistration = bundleContext.registerService(
+ IIDMStore.class.getName(), idmStore, null);
+ final class AutoCloseableStore implements AutoCloseable {
+
+ @Override
+ public void close() throws Exception {
+ serviceRegistration.unregister();
+ idmServiceRegistration.unregister();
+ authNStore.close();
+ }
+ }
+
+ return new AutoCloseableStore();
+
+ // return authNStore;
+
+ // throw new java.lang.UnsupportedOperationException();
+ }
+
+ /**
+ * @param bundleContext
+ */
+ public void setBundleContext(BundleContext bundleContext) {
+ this.bundleContext = bundleContext;
+ }
+
+ /**
+ * @return the bundleContext
+ */
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModuleFactory.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModuleFactory.java
new file mode 100644
index 00000000..b1e278fa
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/java/org/opendaylight/yang/gen/v1/config/aaa/authn/mdsal/store/rev141031/AuthNStoreModuleFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ */
+
+/*
+ * Generated file
+ *
+ * Generated from: yang module name: aaa-authn-mdsal-store-cfg yang module local name: aaa-authn-mdsal-store
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Thu Mar 19 18:06:18 CET 2015
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
+package org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.rev141031;
+
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+public class AuthNStoreModuleFactory
+ extends
+ org.opendaylight.yang.gen.v1.config.aaa.authn.mdsal.store.rev141031.AbstractAuthNStoreModuleFactory {
+
+ @Override
+ public AuthNStoreModule instantiateModule(String instanceName,
+ DependencyResolver dependencyResolver, BundleContext bundleContext) {
+ AuthNStoreModule module = super.instantiateModule(instanceName, dependencyResolver,
+ bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+
+ @Override
+ public AuthNStoreModule instantiateModule(String instanceName,
+ DependencyResolver dependencyResolver, AuthNStoreModule oldModule,
+ AutoCloseable oldInstance, BundleContext bundleContext) {
+ AuthNStoreModule module = super.instantiateModule(instanceName, dependencyResolver,
+ oldModule, oldInstance, bundleContext);
+ module.setBundleContext(bundleContext);
+ return module;
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/yang/aaa-authn-mdsal-store-cfg.yang b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/yang/aaa-authn-mdsal-store-cfg.yang
new file mode 100644
index 00000000..eac344b8
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/yang/aaa-authn-mdsal-store-cfg.yang
@@ -0,0 +1,77 @@
+module aaa-authn-mdsal-store-cfg {
+
+ yang-version 1;
+ namespace "config:aaa:authn:mdsal:store";
+ prefix "aaa-authn-store-cfg";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+ import opendaylight-md-sal-dom {prefix dom;}
+
+
+ description
+ "This module contains the base YANG definitions for
+ AuthN MD-SAL backed data cache implementation.";
+
+ revision "2014-10-31" {
+ description
+ "Initial revision.";
+ }
+
+ identity token-store-service{
+ base config:service-type;
+ config:java-class "org.opendaylight.aaa.api.TokenStore";
+ }
+
+
+ // This is the definition of the service implementation as a module identity.
+ identity aaa-authn-mdsal-store {
+ base config:module-type;
+ // Specifies the prefix for generated java classes.
+ config:java-name-prefix AuthNStore;
+ config:provided-service token-store-service;
+ }
+
+ // Augments the 'configuration' choice node under modules/module.
+
+ augment "/config:modules/config:module/config:configuration" {
+ case aaa-authn-mdsal-store {
+ when "/config:modules/config:module/config:type = 'aaa-authn-mdsal-store'";
+
+ //Defines reference to the Bundle context and MD-SAL data broker
+ container dom-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity dom:dom-broker-osgi-registry;
+ }
+ }
+ }
+ container data-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-async-data-broker;
+
+ }
+ }
+ }
+
+ leaf timeToLive {
+ description "Time to live for tokens. When set to 0 = never expire";
+ type uint64;
+ default 360000;
+ }
+ leaf timeToWait {
+ description "Time to wait for future from data store. 10 by default = never expire";
+ type uint16;
+ default 10;
+ }
+ leaf password {
+ description "Encryption password for the Store";
+ type string;
+ }
+ }
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataBrokerReadMocker.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataBrokerReadMocker.java
new file mode 100644
index 00000000..f821cf16
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataBrokerReadMocker.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DataBrokerReadMocker implements InvocationHandler {
+ private Map<Method, List<StubContainer>> stubs = new HashMap<Method, List<StubContainer>>();
+ private Class<?> mokingClass = null;
+
+ @Override
+ public Object invoke(Object arg0, Method arg1, Object[] arg2) throws Throwable {
+ List<StubContainer> stList = stubs.get(arg1);
+ if (stList != null) {
+ for (StubContainer sc : stList) {
+ if (sc.fitGeneric(arg2)) {
+ return sc.returnObject;
+ }
+ }
+ }
+ return null;
+ }
+
+ public DataBrokerReadMocker(Class<?> cls) {
+ this.mokingClass = cls;
+ }
+
+ public static Object addMock(Class<?> cls) {
+ return Proxy.newProxyInstance(cls.getClassLoader(), new Class[] { cls },
+ new DataBrokerReadMocker(cls));
+ }
+
+ public static DataBrokerReadMocker getMocker(Object o) {
+ return (DataBrokerReadMocker) Proxy.getInvocationHandler(o);
+ }
+
+ public static Method findMethod(Class<?> cls, String name, Object args[]) {
+ Method methods[] = cls.getMethods();
+ for (Method m : methods) {
+ if (m.getName().equals(name)) {
+ if ((m.getParameterTypes() == null || m.getParameterTypes().length == 0)
+ && args == null) {
+ return m;
+ }
+ boolean match = true;
+ for (int i = 0; i < m.getParameterTypes().length; i++) {
+ if (!m.getParameterTypes()[i].isAssignableFrom(args[i].getClass())) {
+ match = false;
+ }
+ }
+ if (match)
+ return m;
+ }
+ }
+ return null;
+ }
+
+ public void addWhen(String methodName, Object[] args, Object returnThis)
+ throws NoSuchMethodException, SecurityException {
+ Method m = findMethod(this.mokingClass, methodName, args);
+ if (m == null)
+ throw new IllegalArgumentException("Unable to find method");
+ StubContainer sc = new StubContainer(args, returnThis);
+ List<StubContainer> lst = stubs.get(m);
+ if (lst == null) {
+ lst = new ArrayList<>();
+ }
+ lst.add(sc);
+ stubs.put(m, lst);
+ }
+
+ private class StubContainer {
+ private Class<?>[] parameters = null;
+ private Class<?>[] generics = null;
+ private Object args[] = null;
+ private Object returnObject;
+
+ public StubContainer(Object[] _args, Object ret) {
+ this.args = _args;
+ this.returnObject = ret;
+ }
+
+ public boolean fitGeneric(Object _args[]) {
+ if (args == null && _args != null)
+ return false;
+ if (args != null && _args == null)
+ return false;
+ if (args == null && _args == null)
+ return true;
+ if (args.length != _args.length)
+ return false;
+ for (int i = 0; i < args.length; i++) {
+ if (!args[i].equals(_args[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypterTest.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypterTest.java
new file mode 100644
index 00000000..eec69bc0
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/DataEncrypterTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.xml.bind.DatatypeConverter;
+import org.junit.Test;
+
+public class DataEncrypterTest {
+
+ @Test
+ public void testEncrypt() {
+ DataEncrypter dataEncry = new DataEncrypter("foo_key_test");
+ String token = "foo_token_test";
+ String eToken = dataEncry.encrypt(token);
+ // check for decryption result
+ String returnToken = dataEncry.decrypt(eToken);
+ String tokenBase64 = DatatypeConverter.printBase64Binary(token.getBytes());
+ assertEquals(tokenBase64, returnToken);
+ }
+
+ @Test
+ public void testDecrypt() {
+ DataEncrypter dataEncry = new DataEncrypter("foo_key_test");
+ String eToken = "foo_etoken_test";
+ assertEquals(dataEncry.decrypt(""), null);
+ // check for encryption Tag
+ assertEquals(eToken, dataEncry.decrypt(eToken));
+ }
+
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTest.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTest.java
new file mode 100644
index 00000000..f376dd5f
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTest.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.aaa.api.IDMStoreUtil;
+import org.opendaylight.aaa.api.SHA256Calculator;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User;
+
+public class IDMStoreTest {
+
+ @Test
+ public void testWriteDomain() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoFordomain();
+ Domain domain = testedObject.writeDomain(util.domain);
+ Assert.assertNotNull(domain);
+ Assert.assertEquals(domain.getDomainid(), util.domain.getName());
+ }
+
+ @Test
+ public void testReadDomain() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoFordomain();
+ Domain domain = testedObject.readDomain(util.domain.getDomainid());
+ Assert.assertNotNull(domain);
+ Assert.assertEquals(domain, util.domain);
+ }
+
+ @Test
+ public void testDeleteDomain() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoFordomain();
+ Domain domain = testedObject.deleteDomain(util.domain.getDomainid());
+ Assert.assertEquals(domain, util.domain);
+ }
+
+ @Test
+ public void testUpdateDomain() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoFordomain();
+ Domain domain = testedObject.updateDomain(util.domain);
+ Assert.assertEquals(domain, util.domain);
+ }
+
+ @Test
+ public void testWriteRole() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForrole();
+ util.addMokitoFordomain();
+ Role role = testedObject.writeRole(util.role);
+ Assert.assertNotNull(role);
+ Assert.assertEquals(role.getRoleid(),
+ IDMStoreUtil.createRoleid(role.getName(), role.getDomainid()));
+ }
+
+ @Test
+ public void testReadRole() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForrole();
+ Role role = testedObject.readRole(util.role.getRoleid());
+ Assert.assertNotNull(role);
+ Assert.assertEquals(role, util.role);
+ }
+
+ @Test
+ public void testDeleteRole() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForrole();
+ Role role = testedObject.deleteRole(util.role.getRoleid());
+ Assert.assertNotNull(role);
+ Assert.assertEquals(role, util.role);
+ }
+
+ @Test
+ public void testUpdateRole() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForrole();
+ Role role = testedObject.updateRole(util.role);
+ Assert.assertNotNull(role);
+ Assert.assertEquals(role, util.role);
+ }
+
+ @Test
+ public void testWriteUser() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForuser();
+ User user = testedObject.writeUser(util.user);
+ Assert.assertNotNull(user);
+ Assert.assertEquals(user.getUserid(),
+ IDMStoreUtil.createUserid(user.getName(), util.user.getDomainid()));
+ }
+
+ @Test
+ public void testReadUser() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForuser();
+ User user = testedObject.readUser(util.user.getUserid());
+ Assert.assertNotNull(user);
+ Assert.assertEquals(user, util.user);
+ }
+
+ @Test
+ public void testDeleteUser() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForuser();
+ User user = testedObject.deleteUser(util.user.getUserid());
+ Assert.assertNotNull(user);
+ Assert.assertEquals(user, util.user);
+ }
+
+ @Test
+ public void testUpdateUser() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForuser();
+ User user = testedObject.updateUser(util.user);
+ Assert.assertNotNull(user);
+ Assert.assertEquals(user.getPassword(),
+ SHA256Calculator.getSHA256(util.user.getPassword(), util.user.getSalt()));
+ }
+
+ @Test
+ public void testWriteGrant() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoFordomain();
+ util.addMokitoForrole();
+ util.addMokitoForuser();
+ util.addMokitoForgrant();
+ Grant grant = testedObject.writeGrant(util.grant);
+ Assert.assertNotNull(grant);
+ }
+
+ @Test
+ public void testReadGrant() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForgrant();
+ Grant grant = testedObject.readGrant(util.grant.getGrantid());
+ Assert.assertNotNull(grant);
+ Assert.assertEquals(grant, util.grant);
+ }
+
+ @Test
+ public void testDeleteGrant() throws Exception {
+ IDMStoreTestUtil util = new IDMStoreTestUtil();
+ IDMMDSALStore testedObject = new IDMMDSALStore(util.dataBroker);
+ util.addMokitoForgrant();
+ Grant grant = testedObject.deleteGrant(util.grant.getGrantid());
+ Assert.assertNotNull(grant);
+ Assert.assertEquals(grant, util.grant);
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTestUtil.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTestUtil.java
new file mode 100644
index 00000000..39eeadb4
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/IDMStoreTestUtil.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.aaa.api.IDMStoreUtil;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.Authentication;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleKey;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IDMStoreTestUtil {
+ /* DataBroker mocked with Mokito */
+ protected static DataBroker dataBroker = mock(DataBroker.class);
+ protected static WriteTransaction wrt = mock(WriteTransaction.class);
+ protected static ReadOnlyTransaction rot = null;
+
+ static {
+ rot = (ReadOnlyTransaction) DataBrokerReadMocker.addMock(ReadOnlyTransaction.class);
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(rot);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(wrt);
+ }
+
+ /* Domain Data Object Instance */
+ public Domain domain = createdomain();
+
+ /* Domain create Method */
+ public Domain createdomain() {
+ /* Start of Domain builder */
+ DomainBuilder domainbuilder = new DomainBuilder();
+ domainbuilder.setName("SETNAME");
+ domainbuilder.setDomainid("SETNAME");
+ domainbuilder.setKey(new DomainKey("SETNAME"));
+ domainbuilder.setDescription("SETDESCRIPTION");
+ domainbuilder.setEnabled(true);
+ /* End of Domain builder */
+ return domainbuilder.build();
+ }
+
+ /* Role Data Object Instance */
+ public Role role = createrole();
+
+ /* Role create Method */
+ public Role createrole() {
+ /* Start of Role builder */
+ RoleBuilder rolebuilder = new RoleBuilder();
+ rolebuilder.setRoleid("SETNAME@SETNAME");
+ rolebuilder.setName("SETNAME");
+ rolebuilder.setKey(new RoleKey(rolebuilder.getRoleid()));
+ rolebuilder.setDomainid(createdomain().getDomainid());
+ rolebuilder.setDescription("SETDESCRIPTION");
+ /* End of Role builder */
+ return rolebuilder.build();
+ }
+
+ /* User Data Object Instance */
+ public User user = createuser();
+
+ /* User create Method */
+ public User createuser() {
+ /* Start of User builder */
+ UserBuilder userbuilder = new UserBuilder();
+ userbuilder.setUserid("SETNAME@SETNAME");
+ userbuilder.setName("SETNAME");
+ userbuilder.setKey(new UserKey(userbuilder.getUserid()));
+ userbuilder.setDomainid(createdomain().getDomainid());
+ userbuilder.setEmail("SETEMAIL");
+ userbuilder.setPassword("SETPASSWORD");
+ userbuilder.setSalt("SETSALT");
+ userbuilder.setEnabled(true);
+ userbuilder.setDescription("SETDESCRIPTION");
+ /* End of User builder */
+ return userbuilder.build();
+ }
+
+ /* Grant Data Object Instance */
+ public Grant grant = creategrant();
+
+ /* Grant create Method */
+ public Grant creategrant() {
+ /* Start of Grant builder */
+ GrantBuilder grantbuilder = new GrantBuilder();
+ grantbuilder.setDomainid(createdomain().getDomainid());
+ grantbuilder.setRoleid(createrole().getRoleid());
+ grantbuilder.setUserid(createuser().getUserid());
+ grantbuilder.setGrantid(IDMStoreUtil.createGrantid(grantbuilder.getUserid(),
+ grantbuilder.getDomainid(), grantbuilder.getRoleid()));
+ grantbuilder.setKey(new GrantKey(grantbuilder.getGrantid()));
+ /* End of Grant builder */
+ return grantbuilder.build();
+ }
+
+ /* InstanceIdentifier for Grant instance grant */
+ public InstanceIdentifier<Grant> grantID = InstanceIdentifier.create(Authentication.class)
+ .child(Grant.class,
+ creategrant().getKey());
+
+ /* Mokito DataBroker method for grant Data Object */
+ public void addMokitoForgrant() throws NoSuchMethodException, SecurityException, InterruptedException, ExecutionException {
+ CheckedFuture<Optional<Grant>, ReadFailedException> read = mock(CheckedFuture.class);
+ DataBrokerReadMocker.getMocker(rot).addWhen("read",
+ new Object[] { LogicalDatastoreType.CONFIGURATION, grantID }, read);
+ Optional<Grant> optional = mock(Optional.class);
+ when(read.get()).thenReturn(optional);
+ when(optional.get()).thenReturn(grant);
+ when(optional.isPresent()).thenReturn(true);
+ }
+
+ /* InstanceIdentifier for Domain instance domain */
+ public InstanceIdentifier<Domain> domainID = InstanceIdentifier.create(Authentication.class)
+ .child(Domain.class,
+ new DomainKey(
+ new String(
+ "SETNAME")));
+
+ /* Mokito DataBroker method for domain Data Object */
+ public void addMokitoFordomain() throws NoSuchMethodException, SecurityException, InterruptedException, ExecutionException {
+ CheckedFuture<Optional<Domain>, ReadFailedException> read = mock(CheckedFuture.class);
+ DataBrokerReadMocker.getMocker(rot).addWhen("read",
+ new Object[] { LogicalDatastoreType.CONFIGURATION, domainID }, read);
+ Optional<Domain> optional = mock(Optional.class);
+ when(read.get()).thenReturn(optional);
+ when(optional.get()).thenReturn(domain);
+ when(optional.isPresent()).thenReturn(true);
+ }
+
+ /* InstanceIdentifier for Role instance role */
+ public InstanceIdentifier<Role> roleID = InstanceIdentifier.create(Authentication.class).child(
+ Role.class, createrole().getKey());
+
+ /* Mokito DataBroker method for role Data Object */
+ public void addMokitoForrole() throws NoSuchMethodException, SecurityException, InterruptedException, ExecutionException {
+ CheckedFuture<Optional<Role>, ReadFailedException> read = mock(CheckedFuture.class);
+ DataBrokerReadMocker.getMocker(rot).addWhen("read",
+ new Object[] { LogicalDatastoreType.CONFIGURATION, roleID }, read);
+ Optional<Role> optional = mock(Optional.class);
+ when(read.get()).thenReturn(optional);
+ when(optional.get()).thenReturn(role);
+ when(optional.isPresent()).thenReturn(true);
+ }
+
+ /* InstanceIdentifier for User instance user */
+ public InstanceIdentifier<User> userID = InstanceIdentifier.create(Authentication.class).child(
+ User.class, createuser().getKey());
+
+ /* Mokito DataBroker method for user Data Object */
+ public void addMokitoForuser() throws NoSuchMethodException, SecurityException, InterruptedException, ExecutionException {
+ CheckedFuture<Optional<User>, ReadFailedException> read = mock(CheckedFuture.class);
+ DataBrokerReadMocker.getMocker(rot).addWhen("read",
+ new Object[] { LogicalDatastoreType.CONFIGURATION, userID }, read);
+ Optional<User> optional = mock(Optional.class);
+ when(read.get()).thenReturn(optional);
+ when(optional.get()).thenReturn(user);
+ when(optional.isPresent()).thenReturn(true);
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/MDSALConvertTest.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/MDSALConvertTest.java
new file mode 100644
index 00000000..9b7c9712
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/MDSALConvertTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.aaa.api.model.Domain;
+import org.opendaylight.aaa.api.model.Grant;
+import org.opendaylight.aaa.api.model.Role;
+import org.opendaylight.aaa.api.model.User;
+
+public class MDSALConvertTest {
+ @Test
+ public void testConvertDomain() {
+ Domain d = new Domain();
+ d.setDescription("hello");
+ d.setDomainid("hello");
+ d.setEnabled(true);
+ d.setName("Hello");
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain mdsalDomain = IDMObject2MDSAL.toMDSALDomain(d);
+ Assert.assertNotNull(mdsalDomain);
+ Domain d2 = IDMObject2MDSAL.toIDMDomain(mdsalDomain);
+ Assert.assertNotNull(d2);
+ Assert.assertEquals(d, d2);
+ }
+
+ @Test
+ public void testConvertRole() {
+ Role r = new Role();
+ r.setDescription("hello");
+ r.setRoleid("Hello@hello");
+ r.setName("Hello");
+ r.setDomainid("hello");
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role mdsalRole = IDMObject2MDSAL.toMDSALRole(r);
+ Assert.assertNotNull(mdsalRole);
+ Role r2 = IDMObject2MDSAL.toIDMRole(mdsalRole);
+ Assert.assertNotNull(r2);
+ Assert.assertEquals(r, r2);
+ }
+
+ @Test
+ public void testConvertUser() {
+ User u = new User();
+ u.setDescription("hello");
+ u.setDomainid("hello");
+ u.setUserid("hello@hello");
+ u.setName("Hello");
+ u.setEmail("email");
+ u.setEnabled(true);
+ u.setPassword("pass");
+ u.setSalt("salt");
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User mdsalUser = IDMObject2MDSAL.toMDSALUser(u);
+ Assert.assertNotNull(mdsalUser);
+ User u2 = IDMObject2MDSAL.toIDMUser(mdsalUser);
+ Assert.assertNotNull(u2);
+ Assert.assertEquals(u, u2);
+ }
+
+ @Test
+ public void testConvertGrant() {
+ Grant g = new Grant();
+ g.setDomainid("hello");
+ g.setUserid("hello@hello");
+ g.setRoleid("hello@hello");
+ g.setGrantid("hello@hello@Hello");
+ org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant mdsalGrant = IDMObject2MDSAL.toMDSALGrant(g);
+ Assert.assertNotNull(mdsalGrant);
+ Grant g2 = IDMObject2MDSAL.toIDMGrant(mdsalGrant);
+ Assert.assertNotNull(g2);
+ Assert.assertEquals(g, g2);
+ }
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtilTest.java b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtilTest.java
new file mode 100644
index 00000000..10c18790
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/test/java/org/opendaylight/aaa/authn/mdsal/store/util/AuthNStoreUtilTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.aaa.authn.mdsal.store.util;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.aaa.api.Authentication;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.token_cache_times.token_list.UserTokens;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.Claims;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.ClaimsBuilder;
+import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.tokencache.ClaimsKey;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+public class AuthNStoreUtilTest {
+
+ private String token = "foo_token_test";
+ private String userId = "123";
+ private Long expire = new Long(365);
+ @Mock
+ private Authentication auth;
+ @Mock
+ private UserTokens tokens;
+ @Mock
+ private Claims claims;
+
+ @Test
+ public void testCreateInstIdentifierForTokencache() {
+ assertTrue(AuthNStoreUtil.createInstIdentifierForTokencache("") == null);
+ assertNotNull(AuthNStoreUtil.createInstIdentifierForTokencache(token));
+ }
+
+ @Test
+ public void testCreateInstIdentifierUserTokens() {
+ assertTrue(AuthNStoreUtil.createInstIdentifierUserTokens("", "") == null);
+ assertNotNull(AuthNStoreUtil.createInstIdentifierUserTokens(userId, token));
+ }
+
+ @Test
+ public void testCreateClaimsRecord() {
+ assertTrue(AuthNStoreUtil.createClaimsRecord("", null) == null);
+ assertNotNull(AuthNStoreUtil.createClaimsRecord(token, auth));
+ }
+
+ @Test
+ public void testCreateUserTokens() {
+ assertTrue(AuthNStoreUtil.createUserTokens("", null) == null);
+ assertNotNull(AuthNStoreUtil.createUserTokens(token, expire));
+ }
+
+ @Test
+ public void testCreateTokenList() {
+ assertTrue(AuthNStoreUtil.createTokenList(null, "") == null);
+ assertNotNull(AuthNStoreUtil.createTokenList(tokens, userId));
+ }
+
+ @Test
+ public void testConvertClaimToAuthentication() {
+ ClaimsKey claimsKey = new ClaimsKey(token);
+ ClaimsBuilder claimsBuilder = new ClaimsBuilder();
+ claimsBuilder.setClientId("123");
+ claimsBuilder.setDomain("foo_domain");
+ claimsBuilder.setKey(claimsKey);
+ List<String> roles = new ArrayList<String>();
+ roles.add("foo_role");
+ claimsBuilder.setRoles(roles);
+ claimsBuilder.setToken(token);
+ claimsBuilder.setUser("foo_usr");
+ claimsBuilder.setUserId(userId);
+ Claims fooClaims = claimsBuilder.build();
+
+ assertTrue(AuthNStoreUtil.convertClaimToAuthentication(null, expire) == null);
+ assertNotNull(AuthNStoreUtil.convertClaimToAuthentication(fooClaims, expire));
+ }
+
+}
diff --git a/odl-aaa-moon/aaa-authn-mdsal-store/pom.xml b/odl-aaa-moon/aaa-authn-mdsal-store/pom.xml
new file mode 100644
index 00000000..38d29147
--- /dev/null
+++ b/odl-aaa-moon/aaa-authn-mdsal-store/pom.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>0.3.1-Beryllium-SR1</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>aaa-authn-mdsal-store</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>aaa-authn-mdsal-api</module>
+ <module>aaa-authn-mdsal-config</module>
+ <module>aaa-authn-mdsal-store-impl</module>
+ </modules>
+</project>