diff options
author | DUVAL Thomas <thomas.duval@orange.com> | 2016-06-16 14:50:31 +0200 |
---|---|---|
committer | DUVAL Thomas <thomas.duval@orange.com> | 2016-06-16 14:50:31 +0200 |
commit | adf7e6616c2a8d6f60207059288423f693509928 (patch) | |
tree | b79848d3b61f28e975f4730de541532c5089c6ed /odl-aaa-moon/aaa/aaa-authn-mdsal-store | |
parent | 506a1fc1252268fa31ba89882ea55b7665579965 (diff) |
Add new version of aaa
Change-Id: I94d72011e6019e66c98f46d11436a5cb33ff295d
Diffstat (limited to 'odl-aaa-moon/aaa/aaa-authn-mdsal-store')
21 files changed, 2805 insertions, 0 deletions
diff --git a/odl-aaa-moon/aaa/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml b/odl-aaa-moon/aaa/aaa-authn-mdsal-store/aaa-authn-mdsal-api/pom.xml new file mode 100644 index 00000000..da6f27f1 --- /dev/null +++ b/odl-aaa-moon/aaa/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.2-Beryllium-SR2</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/aaa-authn-mdsal-store/aaa-authn-mdsal-api/src/main/yang/aaa-authn-model.yang b/odl-aaa-moon/aaa/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/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/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml b/odl-aaa-moon/aaa/aaa-authn-mdsal-store/aaa-authn-mdsal-config/pom.xml new file mode 100644 index 00000000..3ac6e57f --- /dev/null +++ b/odl-aaa-moon/aaa/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.2-Beryllium-SR2</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/aaa-authn-mdsal-store/aaa-authn-mdsal-config/src/main/resources/initial/08-authn-config.xml b/odl-aaa-moon/aaa/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/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&revision=2014-10-31</capability> + </required-capabilities> + +</snapshot> diff --git a/odl-aaa-moon/aaa/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml b/odl-aaa-moon/aaa/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/pom.xml new file mode 100644 index 00000000..069ec60c --- /dev/null +++ b/odl-aaa-moon/aaa/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.2-Beryllium-SR2</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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/aaa-authn-mdsal-store/aaa-authn-mdsal-store-impl/src/main/yang/aaa-authn-mdsal-store-cfg.yang b/odl-aaa-moon/aaa/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/aaa-authn-mdsal-store/pom.xml b/odl-aaa-moon/aaa/aaa-authn-mdsal-store/pom.xml new file mode 100644 index 00000000..e5e4f92f --- /dev/null +++ b/odl-aaa-moon/aaa/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.2-Beryllium-SR2</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> |