--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology. 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 INTERNAL
+-->
+<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.4.0-SNAPSHOT</version>
+ <relativePath>../parent/</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>aaa-cert</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
+ <openflow.protocol.spi.version>0.8.0-SNAPSHOT</openflow.protocol.spi.version>
+ <powermock.version>1.5.2</powermock.version>
+ </properties>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+
+ <!-- Bouncy Castle dependency -->
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+
+ <!-- openflow dependency -->
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin</artifactId>
+ <classifier>features</classifier>
+ <version>${openflowplugin.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowjava</groupId>
+ <artifactId>openflow-protocol-spi</artifactId>
+ <version>${openflow.protocol.spi.version}</version>
+ </dependency>
+
+ <!-- Testing 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.powermock</groupId>
+ <artifactId>powermock-core</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>
+ <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-api-support</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>
+ </plugin>
+ <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/08-aaa-cert-config.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </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>${mdsal.model.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies. 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.cert.api;
+
+import java.security.KeyStore;
+
+/**
+ *
+ * @author mserngawy
+ *
+ * IAaaCertProvider define the basic operation for certificates management
+ */
+public interface IAaaCertProvider extends java.lang.AutoCloseable {
+
+ boolean addCertificateODLKeyStore(String storePasswd, String alias, String certificate);
+
+ boolean addCertificateTrustStore(String storePasswd, String alias, String certificate);
+
+ String createODLKeyStore(String keyStore, String storePasswd, String alias, String dName, int validity);
+
+ String createTrustKeyStore(String keyStore, String storePasswd, String alias);
+
+ String genODLKeyStorCertificateReq(String storePasswd, String alias);
+
+ String getCertificateTrustStore(String storePasswd, String aliase);
+
+ String getODLKeyStorCertificate(String storePasswd, String alias);
+
+ KeyStore getODLKeyStore();
+
+ KeyStore getTrustKeyStore();
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies. 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.cert.impl;
+
+import com.google.common.util.concurrent.SettableFuture;
+import java.security.KeyStore;
+import java.util.concurrent.Future;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.CtlKeystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.TrustKeystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.AaaCertRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetNodeCertifcateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetNodeCertifcateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetNodeCertifcateOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateReqOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateReqOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.SetNodeCertifcateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.SetODLCertifcateInput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author mserngawy
+ * AaaCertProvider use to manage the certificates manipulation operations add, revoke and update
+ */
+public class AaaCertProvider implements AutoCloseable, IAaaCertProvider, BindingAwareProvider, AaaCertRpcService {
+
+ private final static Logger LOG = LoggerFactory.getLogger(AaaCertProvider.class);
+ private ServiceRegistration<AaaCertRpcService> aaaCertRpcServiceRegisteration;
+ private ServiceRegistration<IAaaCertProvider> aaaCertServiceRegisteration;
+ private final CtlKeystore ctlKeyStore;
+ private final ODLKeyTool odlKeyTool;
+ private final TrustKeystore trustKeyStore;
+
+ public AaaCertProvider(final CtlKeystore ctlKeyStore, final TrustKeystore trustKeyStore) {
+ LOG.info("aaa Certificate Service Initalized");
+ odlKeyTool = new ODLKeyTool();
+ this.ctlKeyStore = ctlKeyStore;
+ this.trustKeyStore = trustKeyStore;
+ }
+
+ @Override
+ public boolean addCertificateODLKeyStore(final String storePasswd, final String alias, final String certificate) {
+ return odlKeyTool.addCertificate(ctlKeyStore.getName(), storePasswd, certificate, alias);
+ }
+
+ @Override
+ public boolean addCertificateTrustStore(final String storePasswd, final String alias, final String certificate) {
+ return odlKeyTool.addCertificate(trustKeyStore.getName(), storePasswd, certificate, alias);
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("aaa Certificate Service Closed");
+ aaaCertServiceRegisteration.unregister();
+ aaaCertRpcServiceRegisteration.unregister();
+ }
+
+ public void createODLKeyStore() {
+ createODLKeyStore(ctlKeyStore.getName(),ctlKeyStore.getStorePassword(), ctlKeyStore.getAlias(),
+ ctlKeyStore.getDname(), ctlKeyStore.getValidity());
+ }
+
+ @Override
+ public String createODLKeyStore(final String keyStore, final String storePasswd, final String alias,
+ final String dName, final int validity) {
+ ctlKeyStore.setAlias(alias);
+ ctlKeyStore.setDname(dName);
+ ctlKeyStore.setName(keyStore);
+ ctlKeyStore.setStorePassword(storePasswd);
+ ctlKeyStore.setValidity(validity);
+ if(odlKeyTool.createKeyStoreWithSelfSignCert(keyStore, storePasswd, dName, alias, validity)) {
+ return keyStore + " Keystore created.";
+ } else {
+ return "Failed to create keystore " + keyStore;
+ }
+ }
+
+ public void createTrustKeyStore() {
+ odlKeyTool.createKeyStoreImportCert(trustKeyStore.getName(), trustKeyStore.getStorePassword(),
+ trustKeyStore.getCertFile(), trustKeyStore.getAlias());
+ }
+
+ @Override
+ public String createTrustKeyStore(final String keyStore, final String storePasswd, final String alias) {
+ trustKeyStore.setAlias(alias);
+ trustKeyStore.setName(keyStore);
+ trustKeyStore.setStorePassword(storePasswd);
+ if(odlKeyTool.createKeyStoreImportCert(keyStore, storePasswd, trustKeyStore.getCertFile(), alias)) {
+ return keyStore + " Keystore created.";
+ } else {
+ return "Failed to create keystore " + keyStore;
+ }
+ }
+
+ @Override
+ public String genODLKeyStorCertificateReq(final String storePasswd, final String alias) {
+ return odlKeyTool.generateCertificateReq(ctlKeyStore.getName(), storePasswd,
+ alias,KeyStoreUtilis.defaultSignAlg, true);
+ }
+
+ @Override
+ public String getCertificateTrustStore(final String storePasswd, final String aliase) {
+ return odlKeyTool.getCertificate(trustKeyStore.getName(), storePasswd, aliase, true);
+ }
+
+ @Override
+ public Future<RpcResult<GetNodeCertifcateOutput>> getNodeCertifcate(final GetNodeCertifcateInput input) {
+ final SettableFuture<RpcResult<GetNodeCertifcateOutput>> futureResult = SettableFuture.create();
+ final String cert = odlKeyTool.getCertificate(trustKeyStore.getName(), trustKeyStore.getStorePassword(),
+ input.getNodeAlias(), true);
+ if (cert != null) {
+ final GetNodeCertifcateOutput nodeCertOutput = new GetNodeCertifcateOutputBuilder()
+ .setNodeCert(cert)
+ .build();
+ futureResult.set(RpcResultBuilder.<GetNodeCertifcateOutput> success(nodeCertOutput).build());
+ } else {
+ futureResult.set(RpcResultBuilder.<GetNodeCertifcateOutput> failed().build());
+ }
+ return futureResult;
+ }
+
+ @Override
+ public Future<RpcResult<GetODLCertificateOutput>> getODLCertificate() {
+ final SettableFuture<RpcResult<GetODLCertificateOutput>> futureResult = SettableFuture.create();
+ final String cert = odlKeyTool.getCertificate(ctlKeyStore.getName(), ctlKeyStore.getStorePassword(),
+ ctlKeyStore.getAlias(), true);
+ if (cert != null) {
+ final GetODLCertificateOutput odlCertOutput = new GetODLCertificateOutputBuilder()
+ .setOdlCert(cert)
+ .build();
+ futureResult.set(RpcResultBuilder.<GetODLCertificateOutput> success(odlCertOutput).build());
+ } else {
+ futureResult.set(RpcResultBuilder.<GetODLCertificateOutput> failed().build());
+ }
+ return futureResult;
+ }
+
+ @Override
+ public Future<RpcResult<GetODLCertificateReqOutput>> getODLCertificateReq() {
+ final SettableFuture<RpcResult<GetODLCertificateReqOutput>> futureResult = SettableFuture.create();
+ final String certReq = odlKeyTool.generateCertificateReq(ctlKeyStore.getName(), ctlKeyStore.getStorePassword(),
+ ctlKeyStore.getAlias(), KeyStoreUtilis.defaultSignAlg, true);
+ if (certReq != null) {
+ final GetODLCertificateReqOutput odlCertReqOutput = new GetODLCertificateReqOutputBuilder()
+ .setOdlCertReq(certReq)
+ .build();
+ futureResult.set(RpcResultBuilder.<GetODLCertificateReqOutput> success(odlCertReqOutput).build());
+ } else {
+ futureResult.set(RpcResultBuilder.<GetODLCertificateReqOutput> failed().build());
+ }
+ return futureResult;
+ }
+
+ @Override
+ public String getODLKeyStorCertificate(final String storePasswd, final String alias) {
+ return odlKeyTool.getCertificate(ctlKeyStore.getName(), storePasswd, alias, true);
+ }
+
+ @Override
+ public KeyStore getODLKeyStore() {
+ return odlKeyTool.getKeyStore(ctlKeyStore.getName(), ctlKeyStore.getStorePassword());
+ }
+
+ @Override
+ public KeyStore getTrustKeyStore() {
+ return odlKeyTool.getKeyStore(trustKeyStore.getName(), trustKeyStore.getStorePassword());
+ }
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session) {
+ LOG.info("aaa Certificate Service Session Initiated");
+ final BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ aaaCertServiceRegisteration = context.registerService(IAaaCertProvider.class, this, null);
+ aaaCertRpcServiceRegisteration = context.registerService(AaaCertRpcService.class, this, null);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> setNodeCertifcate(final SetNodeCertifcateInput input) {
+ LOG.info("{} Certificate will be added to the trust keystore.", input.getNodeAlias());
+ final SettableFuture<RpcResult<Void>> futureResult = SettableFuture.create();
+ if (odlKeyTool.addCertificate(trustKeyStore.getName(), trustKeyStore.getStorePassword(),
+ input.getNodeCert(), input.getNodeAlias())) {
+ futureResult.set(RpcResultBuilder.<Void> success().build());
+ } else {
+ futureResult.set(RpcResultBuilder.<Void> failed().build());
+ }
+ return futureResult;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> setODLCertifcate(final SetODLCertifcateInput input) {
+ LOG.info("Certificate will be add to ODL keystore.");
+ final SettableFuture<RpcResult<Void>> futureResult = SettableFuture.create();
+ //adding ca to the alias of signed certificate by Certificate Authority.
+ //can not have 2 certifciate under the same alias.
+ ctlKeyStore.setAlias("ca" + ctlKeyStore.getAlias());
+ if (odlKeyTool.addCertificate(ctlKeyStore.getName(), ctlKeyStore.getStorePassword(),
+ input.getOdlCert(), ctlKeyStore.getAlias())) {
+ futureResult.set(RpcResultBuilder.<Void> success().build());
+ } else {
+ futureResult.set(RpcResultBuilder.<Void> failed().build());
+ }
+ return futureResult;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cert.impl;
+
+import java.net.InetAddress;
+
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
+import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration;
+import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.TransportProtocol;
+
+public class ConnectionConfigurationImpl implements ConnectionConfiguration {
+
+ private final ConnectionConfiguration connConfig;
+ private final TlsConfiguration tlsConfig;
+
+ public ConnectionConfigurationImpl(final ConnectionConfiguration baseConnConfig, final TlsConfiguration tlsConfig) {
+ connConfig = baseConnConfig;
+ this.tlsConfig = tlsConfig;
+ }
+
+ @Override
+ public InetAddress getAddress() {
+ return connConfig.getAddress();
+ }
+
+ @Override
+ public int getPort() {
+ return connConfig.getPort();
+ }
+
+ @Override
+ public Object getSslContext() {
+ return connConfig.getSslContext();
+ }
+
+ @Override
+ public long getSwitchIdleTimeout() {
+ return connConfig.getSwitchIdleTimeout();
+ }
+
+ @Override
+ public ThreadConfiguration getThreadConfiguration() {
+ return connConfig.getThreadConfiguration();
+ }
+
+ @Override
+ public TlsConfiguration getTlsConfiguration() {
+ return tlsConfig;
+ }
+
+ @Override
+ public Object getTransferProtocol() {
+ return TransportProtocol.TLS;
+ }
+
+ @Override
+ public boolean useBarrier() {
+ return connConfig.useBarrier();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies. 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.cert.impl;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ *
+ * @author mserngawy
+ * Utility class for aaa-cert bundle
+ */
+public class KeyStoreUtilis {
+
+ public static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----";
+
+ public static final String BEGIN_CERTIFICATE_REQUEST = "-----BEGIN CERTIFICATE REQUEST-----";
+ public static String defaultKeyAlg = "RSA"; //DES
+ public static int defaultKeySize = 2048; //1024
+ public static String defaultSignAlg = "SHA1WithRSAEncryption"; //MD5WithRSAEncryption
+
+ public static int defaultValidity = 365;
+ public static final String END_CERTIFICATE = "-----END CERTIFICATE-----";
+ public static final String END_CERTIFICATE_REQUEST = "-----END CERTIFICATE REQUEST-----";
+ public static String keyStorePath = "configuration" + File.separator + "ssl" + File.separator;
+
+ public static boolean checkKeyStoreFile(final String fileName) {
+ final File file = new File(keyStorePath + fileName);
+ return file.exists();
+ }
+
+ public static String createDir(final String dir) {
+ final File file = new File(dir);
+ if(!file.exists()) {
+ file.mkdirs();
+ }
+ return file.getAbsolutePath();
+ }
+
+ public static String readFile(final String certFile) {
+ if (certFile == null || certFile.isEmpty()) {
+ return null;
+ }
+
+ try {
+ final FileInputStream fInputStream = new FileInputStream(keyStorePath + certFile);
+ final byte[] certBytes = new byte[fInputStream.available()];
+ fInputStream.read(certBytes);
+ fInputStream.close();
+ final String cert = new String(certBytes, StandardCharsets.UTF_8);
+ return cert;
+ } catch (final IOException e) {
+ return null;
+ }
+ }
+
+ public static boolean saveCert(final String fileName, final String cert) {
+ if (fileName == null || fileName.isEmpty()) {
+ return false;
+ }
+
+ BufferedWriter out;
+ try {
+ out = new BufferedWriter(new FileWriter(keyStorePath + fileName));
+ out.write(cert);
+ out.close();
+ return true;
+ } catch (final IOException e) {
+ return false;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies. 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.cert.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.commons.codec.binary.Base64;
+import org.bouncycastle.asn1.x509.X509Name;
+import org.bouncycastle.jce.PKCS10CertificationRequest;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author mserngawy
+ *
+ * ODLKeyTool has the basic operation to manage the Java keyStores such as generate, add and delete certificates
+ */
+public class ODLKeyTool {
+
+ private final static Logger LOG = LoggerFactory.getLogger(ODLKeyTool.class);
+ // Day time in millisecond
+ private final long dayTime = 1000L * 60 * 60 * 24;
+ private String workingDir = KeyStoreUtilis.keyStorePath;
+
+ protected ODLKeyTool() {
+ KeyStoreUtilis.createDir(workingDir);
+ }
+
+ public ODLKeyTool(final String workingDirectory) {
+ workingDir = workingDirectory;
+ KeyStoreUtilis.createDir(workingDir);
+ }
+
+ public boolean addCertificate(final String keyStoreName, final String keyStorePwd, final String certificate, final String alias) {
+ try {
+ final X509Certificate newCert = getCertificate(certificate);
+ final KeyStore keyStore = KeyStore.getInstance("JKS");
+ final FileInputStream fInputStream = new FileInputStream(workingDir + keyStoreName);
+ keyStore.load(fInputStream, keyStorePwd.toCharArray());
+ if(keyStore.isCertificateEntry(alias)) {
+ keyStore.deleteEntry(alias);
+ }
+ keyStore.setCertificateEntry(alias, newCert);
+ keyStore.store( new FileOutputStream(workingDir + keyStoreName), keyStorePwd.toCharArray());
+ LOG.info("Certificate {} Added to keyStore {}", alias, keyStoreName);
+ return true;
+ } catch (CertificateException | KeyStoreException | NoSuchAlgorithmException | IOException e) {
+ LOG.error("failed to add certificate {}", e.getMessage());
+ return false;
+ }
+ }
+
+ public boolean createKeyStoreImportCert(final String keyStoreName, final String keyStorePwd, final String certFile, final String alias) {
+ KeyStore trustKeyStore;
+ try {
+ trustKeyStore = KeyStore.getInstance("JKS");
+ trustKeyStore.load(null, keyStorePwd.toCharArray());
+ if(KeyStoreUtilis.checkKeyStoreFile(certFile)) {
+ final String certificate = KeyStoreUtilis.readFile(certFile);
+ final X509Certificate newCert = getCertificate(certificate);
+ trustKeyStore.setCertificateEntry(alias, newCert);
+ }
+ trustKeyStore.store( new FileOutputStream(workingDir + keyStoreName), keyStorePwd.toCharArray());
+ LOG.info("{} is created", keyStoreName);
+ return true;
+ } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
+ LOG.error("Failed to create keystore {}", keyStoreName);
+ return false;
+ }
+ }
+
+ public boolean createKeyStoreWithSelfSignCert(final String keyStoreName, final String keyStorePwd, final String dName, final String keyAlias, final int validity) {
+ try {
+ final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyStoreUtilis.defaultKeyAlg);
+ keyPairGenerator.initialize(KeyStoreUtilis.defaultKeySize);
+ final KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ final X509V3CertificateGenerator x509V3CertGen = new X509V3CertificateGenerator();
+ x509V3CertGen.setSerialNumber(getSecureRandomeInt());
+ x509V3CertGen.setIssuerDN(new X509Principal(dName));
+ x509V3CertGen.setNotBefore(new Date(System.currentTimeMillis()));
+ x509V3CertGen.setNotAfter(new Date(System.currentTimeMillis() + (dayTime * validity)));
+ x509V3CertGen.setSubjectDN(new X509Principal(dName));
+ x509V3CertGen.setPublicKey(keyPair.getPublic());
+ x509V3CertGen.setSignatureAlgorithm(KeyStoreUtilis.defaultSignAlg);
+ final X509Certificate x509Cert = x509V3CertGen.generateX509Certificate(keyPair.getPrivate());
+ final KeyStore ctlKeyStore = KeyStore.getInstance("JKS");
+ ctlKeyStore.load(null, keyStorePwd.toCharArray());
+ ctlKeyStore.setKeyEntry(keyAlias, keyPair.getPrivate(), keyStorePwd.toCharArray(),
+ new java.security.cert.Certificate[]{x509Cert});
+ final FileOutputStream fOutputStream = new FileOutputStream(workingDir + keyStoreName);
+ ctlKeyStore.store( fOutputStream, keyStorePwd.toCharArray());
+ LOG.info("{} is created", keyStoreName);
+ return true;
+ }
+ catch (NoSuchAlgorithmException | InvalidKeyException | SecurityException | SignatureException | KeyStoreException | CertificateException | IOException e) {
+ LOG.error("Fatal error creating key cert: {}", e.getMessage());
+ return false;
+ }
+ }
+
+ public String generateCertificateReq(final String keyStoreName, final String keyStorePwd, final String keyAlias, final String signAlg,
+ final boolean withTag) {
+ try {
+ final KeyStore ctlKeyStore = KeyStore.getInstance("JKS");
+ final FileInputStream fInputStream = new FileInputStream(workingDir + keyStoreName);
+ ctlKeyStore.load(fInputStream, keyStorePwd.toCharArray());
+ if (ctlKeyStore.containsAlias(keyAlias)) {
+ final X509Certificate odlCert = (X509Certificate)ctlKeyStore.getCertificate(keyAlias);
+ final PublicKey pubKey = odlCert.getPublicKey();
+ final PrivateKey privKey = (PrivateKey)ctlKeyStore.getKey(keyAlias, keyStorePwd.toCharArray());
+ final String subject = odlCert.getSubjectDN().getName();
+ final X509Name xname = new X509Name(subject);
+ final String signatureAlgorithm = signAlg;
+ final PKCS10CertificationRequest csr =
+ new PKCS10CertificationRequest(signatureAlgorithm, xname, pubKey, null, privKey);
+ final String certReq = DatatypeConverter.printBase64Binary(csr.getEncoded());
+ if (withTag) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(KeyStoreUtilis.BEGIN_CERTIFICATE_REQUEST);
+ sb.append("\n");
+ sb.append(certReq);
+ sb.append("\n");
+ sb.append(KeyStoreUtilis.END_CERTIFICATE_REQUEST);
+ return sb.toString();
+ }
+ return certReq;
+ }
+ LOG.info("{} KeyStore does not contain alias {}", keyStoreName, keyAlias);
+ return null;
+ } catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException |
+ UnrecoverableKeyException | InvalidKeyException | NoSuchProviderException | SignatureException e) {
+ LOG.error("Failed to generate certificate request {}", e.getMessage());
+ return null;
+ }
+ }
+
+ private X509Certificate getCertificate(String certificate) {
+ if (certificate.isEmpty()) {
+ return null;
+ }
+
+ if (certificate.contains(KeyStoreUtilis.BEGIN_CERTIFICATE)) {
+ final int fIdx = certificate.indexOf(KeyStoreUtilis.BEGIN_CERTIFICATE) + KeyStoreUtilis.BEGIN_CERTIFICATE.length();
+ final int sIdx = certificate.indexOf(KeyStoreUtilis.END_CERTIFICATE);
+ certificate = certificate.substring(fIdx, sIdx);
+ }
+ final byte[] byteCert = Base64.decodeBase64(certificate);
+ final InputStream inputStreamCert = new ByteArrayInputStream(byteCert);
+ CertificateFactory certFactory;
+ try {
+ certFactory = CertificateFactory.getInstance("X.509");
+ final X509Certificate newCert = (X509Certificate) certFactory.generateCertificate(inputStreamCert);
+ newCert.checkValidity();
+ return newCert;
+ } catch (final CertificateException e) {
+ LOG.error("Failed to get certificate {}", e.getMessage());
+ return null;
+ }
+ }
+
+ public String getCertificate(final String keyStoreName, final String keyStorePwd, final String certAlias, final boolean withTag) {
+ try {
+ final KeyStore ctlKeyStore = KeyStore.getInstance("JKS");
+ final FileInputStream fInputStream = new FileInputStream(workingDir + keyStoreName);
+ ctlKeyStore.load(fInputStream, keyStorePwd.toCharArray());
+ if (ctlKeyStore.containsAlias(certAlias)) {
+ final X509Certificate odlCert = (X509Certificate)ctlKeyStore.getCertificate(certAlias);
+ final String cert = DatatypeConverter.printBase64Binary(odlCert.getEncoded());
+ if (withTag) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(KeyStoreUtilis.BEGIN_CERTIFICATE);
+ sb.append("\n");
+ sb.append(cert);
+ sb.append("\n");
+ sb.append(KeyStoreUtilis.END_CERTIFICATE);
+ return sb.toString();
+ }
+ return cert;
+ }
+ LOG.info("{} KeyStore does not contain alias {}", keyStoreName, certAlias);
+ return null;
+ } catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException e) {
+ LOG.error("Failed to get Certificate {}", e.getMessage());
+ return null;
+ }
+ }
+
+ public KeyStore getKeyStore(final String keyStoreName, final String keyStorePwd) {
+ try {
+ final KeyStore keyStore = KeyStore.getInstance("JKS");
+ final FileInputStream fInputStream = new FileInputStream(workingDir + keyStoreName);
+ keyStore.load(fInputStream, keyStorePwd.toCharArray());
+ return keyStore;
+ } catch (NoSuchAlgorithmException | CertificateException | IOException | KeyStoreException e) {
+ LOG.error("failed to get keystore {}", e.getMessage());
+ return null;
+ }
+ }
+
+ private BigInteger getSecureRandomeInt() {
+ final SecureRandom secureRandom = new SecureRandom();
+ final BigInteger bigInt = BigInteger.valueOf(secureRandom.nextInt());
+ return new BigInteger(1, bigInt.toByteArray());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cert.impl;
+
+import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType;
+
+/**
+ *
+ * @author mserngawy
+ * TlsConfigurationImp has configurations of the TLS connection
+ */
+public class TlsConfigurationImp implements TlsConfiguration{
+
+ private final String certPwd;
+ private final String tlsKeyStore;
+ private final PathType tlsKeystorePathType;
+ private final String tlsKeyStorePwd;
+ private final KeystoreType tlsKeyStoreType;
+ private final String trustKeyStore;
+ private final PathType trustKeystorePathType;
+ private final String trustKeyStorePwd;
+ private final KeystoreType trustKeyStoreType;
+
+ public TlsConfigurationImp(final String tlsKeyStore, final String trustKeyStore, final String tlsKeyStorePwd,
+ final String trustKeyStorePwd, final String certPwd, final KeystoreType tlsKeyStoreType,final KeystoreType trustKeyStoreTy,
+ final PathType tlsKeystorePathType, final PathType trustKeystorePathType) {
+ this.tlsKeyStore = tlsKeyStore;
+ this.trustKeyStore = trustKeyStore;
+ this.tlsKeyStorePwd = tlsKeyStorePwd;
+ this.trustKeyStorePwd = trustKeyStorePwd;
+ this.certPwd = certPwd;
+ this.tlsKeyStoreType = tlsKeyStoreType;
+ this.trustKeyStoreType = trustKeyStoreTy;
+ this.tlsKeystorePathType = tlsKeystorePathType;
+ this.trustKeystorePathType = trustKeystorePathType;
+ }
+
+ @Override
+ public String getCertificatePassword() {
+ return certPwd;
+ }
+
+ @Override
+ public String getKeystorePassword() {
+ return tlsKeyStorePwd;
+ }
+
+ @Override
+ public String getTlsKeystore() {
+ return tlsKeyStore;
+ }
+
+ @Override
+ public PathType getTlsKeystorePathType() {
+ return tlsKeystorePathType;
+ }
+
+ @Override
+ public KeystoreType getTlsKeystoreType() {
+ return tlsKeyStoreType;
+ }
+
+ @Override
+ public String getTlsTruststore() {
+ return trustKeyStore;
+ }
+
+ @Override
+ public PathType getTlsTruststorePathType() {
+ return trustKeystorePathType;
+ }
+
+ @Override
+ public KeystoreType getTlsTruststoreType() {
+ return trustKeyStoreType;
+ }
+
+ @Override
+ public String getTruststorePassword() {
+ return trustKeyStorePwd;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Inocybe Technologies. 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.urn.opendaylight.yang.aaa.cert.rev151126;
+
+import java.util.List;
+
+import org.opendaylight.aaa.cert.impl.AaaCertProvider;
+import org.opendaylight.aaa.cert.impl.ConnectionConfigurationImpl;
+import org.opendaylight.aaa.cert.impl.KeyStoreUtilis;
+import org.opendaylight.aaa.cert.impl.TlsConfigurationImp;
+import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
+import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
+import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author mserngawy
+ * AaaCertProviderModule create and intialize the AaaCertProvider services
+ */
+public class AaaCertProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.AbstractAaaCertProviderModule {
+
+ private final static Logger LOG = LoggerFactory.getLogger(AaaCertProviderModule.class);
+
+ public AaaCertProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public AaaCertProviderModule(final org.opendaylight.controller.config.api.ModuleIdentifier identifier, final org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, final org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.AaaCertProviderModule oldModule, final java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public AutoCloseable createInstance() {
+ final CtlKeystore ctlKeyStore = this.getCtlKeystore();
+ final TrustKeystore trust = this.getTrustKeystore();
+ final AaaCertProvider aaaCertProvider = new AaaCertProvider(ctlKeyStore, trust);
+ if (this.getUseConfig() && !KeyStoreUtilis.checkKeyStoreFile(ctlKeyStore.getName())) {
+ LOG.info("Creating keystore based on given configuration");
+ aaaCertProvider.createODLKeyStore();
+ aaaCertProvider.createTrustKeyStore();
+ }
+
+ final List<SwitchConnectionProvider> listSwitchConnectionProvider = this.getOpenflowSwitchConnectionDependency();
+ for (final SwitchConnectionProvider switchConnProvider : listSwitchConnectionProvider) {
+ if (switchConnProvider.getConfiguration() != null) {
+ LOG.info("Set TLS config then restart the connections ");
+ final ConnectionConfiguration connConfig = switchConnProvider.getConfiguration();
+ final TlsConfiguration tlsConfig = new TlsConfigurationImp(KeyStoreUtilis.keyStorePath + ctlKeyStore.getName(),
+ KeyStoreUtilis.keyStorePath + trust.getName(), ctlKeyStore.getStorePassword(), trust.getStorePassword(),
+ trust.getStorePassword(), KeystoreType.JKS, KeystoreType.JKS,
+ PathType.PATH, PathType.PATH);
+ final ConnectionConfigurationImpl connConfigImpl = new ConnectionConfigurationImpl(connConfig, tlsConfig);
+ switchConnProvider.shutdown();
+ switchConnProvider.setConfiguration(connConfigImpl);
+ switchConnProvider.startup();
+ }
+ }
+
+ getBrokerDependency().registerProvider(aaaCertProvider);
+ return aaaCertProvider;
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: aaa-cert yang module local name: aaa-cert
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Sun Nov 29 23:46:12 EST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126;
+public class AaaCertProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.AbstractAaaCertProviderModuleFactory {
+
+}
--- /dev/null
+<blueprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+</blueprint>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology. 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 INTERNAL
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:yang:aaa:cert?module=aaa-cert&revision=2015-11-26</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ </required-capabilities>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:yang:aaa:cert">prefix:aaa-cert</type>
+ <name>aaa-cert</name>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ <openflow-switch-connection>
+ <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
+ <name>openflow-switch-connection-provider-legacy</name>
+ </openflow-switch-connection>
+ <openflow-switch-connection>
+ <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
+ <name>openflow-switch-connection-provider-default</name>
+ </openflow-switch-connection>
+ <useConfig>true</useConfig>
+ <ctlKeystore>
+ <name>ctl.jks</name>
+ <alias>controller</alias>
+ <storePassword>storePassword</storePassword>
+ <dname>CN=ODL, OU=Dev, O=LinuxFoundation, L=QC Montreal, C=CA</dname>
+ <validity>365</validity>
+ </ctlKeystore>
+ <trustKeystore>
+ <name>truststore.jks</name>
+ <alias>controller</alias>
+ <storePassword>storePassword</storePassword>
+ <certFile>cacert.pem</certFile>
+ </trustKeystore>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cert.test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.security.Security;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.opendaylight.aaa.cert.impl.AaaCertProvider;
+import org.opendaylight.aaa.cert.impl.KeyStoreUtilis;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.CtlKeystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rev151126.TrustKeystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetNodeCertifcateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetNodeCertifcateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.GetODLCertificateReqOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.SetNodeCertifcateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.yang.aaa.cert.rpc.rev151215.SetODLCertifcateInput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+public class AaaCertProviderTest {
+
+ private static AaaCertProvider aaaCertProv;
+ private static CtlKeystore ctlKeyStore;
+ private static TrustKeystore trustKeyStore;
+
+ private String dummyAlias = "fooAlias";
+ private String dummyCert = KeyStoreUtilis.BEGIN_CERTIFICATE +
+ "MIIDLjCCAhagAwIBAgIELsFzhjANBgkqhkiG9w0BAQUFADBZMQwwCgYDV"+
+ "QQDDANPREwxDDAKBgNVBAsMA0RldjEYMBYGA1UECgwPTGludXhGb3VuZG"+
+ "F0aW9uMRQwEgYDVQQHDAtRQyBNb250cmVhbDELMAkGA1UEBhMCQ0EwHhc"+
+ "NMTYwMTA0MTcxNDM3WhcNMTcwMTAzMTcxNDM3WjBZMQwwCgYDVQQDDANP"+
+ "REwxDDAKBgNVBAsMA0RldjEYMBYGA1UECgwPTGludXhGb3VuZGF0aW9uM"+
+ "RQwEgYDVQQHDAtRQyBNb250cmVhbDELMAkGA1UEBhMCQ0EwggEiMA0GCS"+
+ "qGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsmMPHlF5pfAO3HzvM1pVIPwg"+
+ "at1gq8cHi5wF8d+qt4+jK2uihp9LhAZ3aAZEbRqvZjDYnXaavCFRXZKUN"+
+ "3AjxvYV0VHtVILK7+xOJGUWgJ5BxZ4utTvQ/3LavTQGZHNH3jGeqWMf3f"+
+ "t1T1jiM72nNxN3KZykDVKoUPLpmci0OCMo+IFkcelVojRJGC9q7MSHcbY"+
+ "XBU/HI+frmp4UkfBTcUWJidTj3jJvT8azCEoysy0HSt85x/IZukN2goco"+
+ "kDm6uyavImdqac/c2ApzEAkBVM/+NkvMBIrRjX4AsmejYSP6nMIPbYRV0"+
+ "V6oWL1sMmrvCb5Kt8/jNDa493jO/dDiRAgMBAAEwDQYJKoZIhvcNAQEFB"+
+ "QADggEBAHKFTBRPqXFp4VYECTSdUsn7nad1LawrYE4DB16j5pbmnNwNIH"+
+ "D4W+Wh0EJEfd6iEdu7DJfHS6OqjYKj9ruqyO6LOGBy8eYzyvtq9dkYEOy"+
+ "i86CIb6NRfVR/ycJgeC7sc+y91wPbZlRXtY+UA7RohebC8Cyg6Kr/zEwv"+
+ "OT0fAjQi6Mypje08OstA2sklTSPfYtrDFJUpJW7+5fGic/wf5ITPmMVJl"+
+ "rt6aSStfyOLhCSAWXmU/1Pn1pixltJvaLnd0HYQdhcFOS9XG5LfA3Mlqm"+
+ "ZEwGEjhpmk810dJyRjoCEsokljWyhmJGW6hTK1j+2V+PCHqyawghiTB0jQFRTt2zo="+
+ KeyStoreUtilis.END_CERTIFICATE;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ KeyStoreUtilis.keyStorePath = "target" + File.separator + "test" + File.separator;
+ String dName = "CN=ODL, OU=Dev, O=LinuxFoundation, L=QC Montreal, C=CA";
+ Security.addProvider(new BouncyCastleProvider());
+ ctlKeyStore = new CtlKeystore();
+ ctlKeyStore.setAlias("fooTest");
+ ctlKeyStore.setDname(dName);
+ ctlKeyStore.setName("fooTest.jks");
+ ctlKeyStore.setStorePassword("passWord");
+ ctlKeyStore.setValidity(KeyStoreUtilis.defaultValidity);
+ trustKeyStore = new TrustKeystore();
+ trustKeyStore.setAlias("trustTest");
+ trustKeyStore.setCertFile("cacert.pem");
+ trustKeyStore.setName("trustTest.jks");
+ trustKeyStore.setStorePassword("passWord");
+ aaaCertProv = new AaaCertProvider(ctlKeyStore, trustKeyStore);
+ }
+
+ @Test
+ public void testCreateTrustKeyStore() {
+ String result = aaaCertProv.createTrustKeyStore(trustKeyStore.getName(), trustKeyStore.getStorePassword(),
+ trustKeyStore.getAlias());
+ assertEquals(result, trustKeyStore.getName() + " Keystore created.");
+ }
+
+ @Test
+ public void testCreateODLKeyStoreString() {
+ String result = aaaCertProv.createODLKeyStore(ctlKeyStore.getName(), ctlKeyStore.getStorePassword(),
+ ctlKeyStore.getAlias(), ctlKeyStore.getDname(), ctlKeyStore.getValidity());
+ assertEquals(result, ctlKeyStore.getName() + " Keystore created.");
+ }
+
+ @Test
+ public void testGetODLCertificateReq() throws InterruptedException, ExecutionException {
+ Future<RpcResult<GetODLCertificateReqOutput>> future = aaaCertProv.getODLCertificateReq();
+ assertTrue(future != null);
+ RpcResult<GetODLCertificateReqOutput> rpc = future.get();
+ assertTrue(rpc.isSuccessful());
+ String certReq = rpc.getResult().getOdlCertReq();
+ assertTrue(certReq != null);
+ assertTrue(certReq.contains(KeyStoreUtilis.BEGIN_CERTIFICATE_REQUEST));
+ }
+
+ @Test
+ public void testSetODLCertifcate() throws InterruptedException, ExecutionException {
+ SetODLCertifcateInput input = mock(SetODLCertifcateInput.class, Mockito.RETURNS_MOCKS);
+ when(input.getOdlCert()).thenReturn(dummyCert);
+ Future<RpcResult<Void>> future = aaaCertProv.setODLCertifcate(input);
+ assertTrue(future != null);
+ assertTrue(future.get().isSuccessful());
+ }
+
+ @Test
+ public void testGetODLCertificate() throws InterruptedException, ExecutionException {
+ Future<RpcResult<GetODLCertificateOutput>> future = aaaCertProv.getODLCertificate();
+ assertTrue(future != null);
+ RpcResult<GetODLCertificateOutput> rpc = future.get();
+ assertTrue(rpc.isSuccessful());
+ String cert = aaaCertProv.getODLKeyStorCertificate(ctlKeyStore.getStorePassword(), ctlKeyStore.getAlias());
+ assertEquals(rpc.getResult().getOdlCert(), cert);
+ }
+
+ @Test
+ public void testSetNodeCertifcate() throws InterruptedException, ExecutionException {
+ SetNodeCertifcateInput input = mock(SetNodeCertifcateInput.class, Mockito.RETURNS_MOCKS);
+ when(input.getNodeCert()).thenReturn(dummyCert);
+ when(input.getNodeAlias()).thenReturn(dummyAlias);
+ Future<RpcResult<Void>> future = aaaCertProv.setNodeCertifcate(input);
+ assertTrue(future != null);
+ assertTrue(future.get().isSuccessful());
+ }
+
+ @Test
+ public void testGetNodeCertifcate() throws InterruptedException, ExecutionException {
+ GetNodeCertifcateInput input = mock(GetNodeCertifcateInput.class, Mockito.RETURNS_MOCKS);
+ when(input.getNodeAlias()).thenReturn(dummyAlias);
+ Future<RpcResult<GetNodeCertifcateOutput>> future = aaaCertProv.getNodeCertifcate(input);
+ assertTrue(future != null);
+ RpcResult<GetNodeCertifcateOutput> rpc = future.get();
+ assertTrue(rpc.isSuccessful());
+ String cert = aaaCertProv.getCertificateTrustStore(trustKeyStore.getStorePassword(), dummyAlias);
+ assertEquals(cert, rpc.getResult().getNodeCert());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cert.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.aaa.cert.impl.KeyStoreUtilis;
+
+public class KeyStoreUtilisTest {
+
+ private final String fileName = "foo.pem";
+ private final String txt = "test save text";
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ KeyStoreUtilis.keyStorePath = "target" + File.separator + "test" + File.separator;
+ }
+
+ @Test
+ public void testCreateDir() {
+ final String path = KeyStoreUtilis.createDir(KeyStoreUtilis.keyStorePath);
+ assertTrue(!path.isEmpty());
+ final File dir = new File(path);
+ assertTrue(dir.exists());
+ }
+
+ @Test
+ public void testSaveCert() {
+ assertTrue(KeyStoreUtilis.saveCert(fileName, txt));
+ }
+
+ @Test
+ public void testCheckKeyStoreFile() {
+ assertTrue(KeyStoreUtilis.checkKeyStoreFile(fileName));
+ assertTrue(!KeyStoreUtilis.checkKeyStoreFile("notExist.txt"));
+ }
+
+ @Test
+ public void testReadFile() {
+ final String readTxt = KeyStoreUtilis.readFile(fileName);
+ assertEquals(txt, readTxt);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cert.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.security.Security;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.aaa.cert.impl.KeyStoreUtilis;
+import org.opendaylight.aaa.cert.impl.ODLKeyTool;
+
+public class ODLKeyToolTest {
+
+ private static ODLKeyTool odlKeyTool;
+ private static String testPath = "target" + File.separator + "test" + File.separator;
+ private final String keyStore = "fooTest.jks";
+ private final String trustKeyStore = "footrust.jks";
+ private final String passwd = "Password";
+ private final String alias = "FooTest";
+ private final String certFile = "cert.pem";
+
+ static {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ KeyStoreUtilis.keyStorePath = testPath;
+ odlKeyTool = new ODLKeyTool(testPath);
+ }
+
+ @Test
+ public void testCreateKeyStoreWithSelfSignCert() {
+ final String dName = "CN=ODL, OU=Dev, O=LinuxFoundation, L=QC Montreal, C=CA";
+ assertTrue(odlKeyTool.createKeyStoreWithSelfSignCert(keyStore, passwd, dName, alias,
+ KeyStoreUtilis.defaultValidity));
+ }
+
+ @Test
+ public void testGetCertificate() {
+ String cert = odlKeyTool.getCertificate(keyStore, passwd, alias, false);
+ assertTrue(cert != null && cert.length() > 0);
+ cert = odlKeyTool.getCertificate(keyStore, passwd, alias, true);
+ assertTrue(cert.contains(KeyStoreUtilis.BEGIN_CERTIFICATE));
+ }
+
+ @Test
+ public void testGenerateCertificateReq() {
+ String certReq = odlKeyTool.generateCertificateReq(keyStore, passwd, alias,
+ KeyStoreUtilis.defaultSignAlg, false);
+ assertTrue(certReq != null && certReq.length() > 0);
+ certReq = odlKeyTool.generateCertificateReq(keyStore, passwd, alias,
+ KeyStoreUtilis.defaultSignAlg, true);
+ assertTrue(certReq.contains(KeyStoreUtilis.BEGIN_CERTIFICATE_REQUEST));
+ }
+
+ @Test
+ public void testCreateKeyStoreImportCert() {
+ assertTrue(odlKeyTool.createKeyStoreImportCert(trustKeyStore, passwd, null, alias));
+ final String cert = odlKeyTool.getCertificate(keyStore, passwd, alias, false);
+ KeyStoreUtilis.saveCert(certFile, cert);
+ assertTrue(odlKeyTool.createKeyStoreImportCert(trustKeyStore, passwd, certFile, alias));
+ }
+
+ @Test
+ public void testAddCertificate() {
+ final String cert = KeyStoreUtilis.readFile(certFile);
+ assertTrue(odlKeyTool.addCertificate(trustKeyStore, passwd, cert, alias));
+ }
+
+ @Test
+ public void testGetKeyStore() {
+ assertNotNull(odlKeyTool.getKeyStore(keyStore, passwd));
+ assertNotNull(odlKeyTool.getKeyStore(trustKeyStore, passwd));
+ }
+
+}
--- /dev/null
+/*
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+*/
+
+module aaa-cert-rpc {
+ yang-version 1;
+ namespace "urn:opendaylight:yang:aaa:cert:rpc";
+ prefix "aaa-cert-rpc";
+
+ description
+ "defination of node certificate grouping and Rpc calls of certificate manipulation";
+
+ contact
+ "melserngawy@inocybe.com";
+
+ revision "2015-12-15" {
+ description
+ "Initial revision.";
+ }
+
+ grouping node-certificate {
+ leaf alias {
+ description "ovs node certificate alias";
+ type string;
+ }
+ leaf certificate {
+ description "ovs node certificate";
+ type string;
+ }
+ }
+
+ rpc getODLCertificate {
+ description
+ "Get the ctl.jks keystore certificate";
+ output {
+ leaf odl-cert {
+ type string;
+ }
+ }
+ }
+
+ rpc getODLCertificateReq {
+ description
+ "Generate a certificate request from the ctl.jks keystore to be signed by a CA";
+ output {
+ leaf odl-cert-req {
+ type string;
+ }
+ }
+ }
+
+ rpc setODLCertifcate {
+ description
+ "The certifcate should be generated based on
+ a certifcate request generated from the ctl.jks
+ keystore otherwise the certifcated will not be added to ctl keystore";
+ input {
+ leaf odl-cert {
+ type string;
+ }
+ }
+ }
+
+ rpc setNodeCertifcate {
+ description
+ "Certifcate of the ovs node that will communicate with opendaylight through TLS connection";
+ input {
+ leaf node-alias {
+ type string;
+ }
+ leaf node-cert {
+ type string;
+ }
+ }
+ }
+
+ rpc getNodeCertifcate {
+ description
+ "Get the ovs node certificate based on node alias";
+ input {
+ leaf node-alias {
+ type string;
+ }
+ }
+ output {
+ leaf node-cert {
+ type string;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+*/
+
+module aaa-cert {
+ yang-version 1;
+ namespace "urn:opendaylight:yang:aaa:cert";
+ prefix aaa-cert;
+
+ import config {
+ prefix config;
+ revision-date 2013-04-05;
+ }
+
+ import opendaylight-md-sal-binding {
+ prefix md-sal-binding;
+ revision-date 2013-10-28;
+ }
+
+ import openflow-switch-connection-provider {
+ prefix openflow-switch-connection-provider;
+ revision-date 2014-03-28;
+ }
+
+ description
+ "Service definition for aaa certificate";
+
+ contact
+ "melserngawy@inocybe.com";
+
+ revision "2015-11-26" {
+ description
+ "Initial revision.";
+ }
+
+ identity aaa-cert {
+ base config:module-type;
+ config:java-name-prefix AaaCertProvider;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case aaa-cert {
+ when "/config:modules/config:module/config:type = 'aaa-cert'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ list openflow-switch-connection {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
+ }
+ }
+ }
+ leaf useConfig {
+ description "Use the configuration data to create the keystores";
+ type boolean;
+ default false;
+ }
+ container ctlKeystore {
+ leaf name {
+ description "keystore name default is ctl";
+ type string;
+ }
+ leaf alias {
+ description "key alias";
+ type string;
+ }
+ leaf storePassword {
+ description "keystore password";
+ type string;
+ }
+ leaf dname {
+ description "X.500 Distinguished Names should be in the following formate
+ CN=commonName
+ OU=organizationUnit
+ O=organizationName
+ L=localityName
+ S=stateName
+ C=country";
+ type string;
+ }
+ leaf validity {
+ description "validity";
+ type int32;
+ }
+ }
+ container trustKeystore {
+ leaf name {
+ description "keystore name default is truststore";
+ type string;
+ }
+ leaf alias {
+ description "key alias";
+ type string;
+ }
+ leaf storePassword {
+ description "keystore password";
+ type string;
+ }
+ leaf certFile {
+ description "path to CA certificate pem file";
+ type string;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+-->
+<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.4.0-SNAPSHOT</version>
+ <relativePath>../parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>aaa-cli</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.version}</version>
+ </dependency>
+
+ <!-- Testing 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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import java.io.FileInputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+
+@Command(name = "add-odl-cert", scope = "aaa", description = "Add ODL signed certificaet to ODL key store.")
+
+/**
+ *
+ * @author mserngawy
+ * AddCertODLKeyStore adding certificate to the ODL keyStore
+ */
+public class AddCertODLKeyStore extends OsgiCommandSupport {
+
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-cert",
+ aliases = { "--CertFile" },
+ description = "The ODL certificate file.\n-file / --should be accesable by the karaf command line",
+ required = true,
+ multiValued = false)
+ private String certFile = "";
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The ODL keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / ODL alias default is controller as the configuration",
+ required = false,
+ multiValued = false)
+ private String alias = "controller";
+
+ public AddCertODLKeyStore(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ final FileInputStream fInputStream = new FileInputStream(certFile);
+ final byte[] certBytes = new byte[fInputStream.available()];
+ fInputStream.read(certBytes);
+ fInputStream.close();
+ final String certificate = new String(certBytes, StandardCharsets.UTF_8);
+ if (certProvider.addCertificateODLKeyStore(keyStorePassword, alias, certificate)) {
+ return alias + " certificate successfully added to ODL keystore";
+ } else {
+ return "Failed to add " + alias + " certificate to ODL keystore";
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import java.io.FileInputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+
+@Command(name = "add-trust-cert", scope = "aaa", description = "Add node certificaet to trust key store.")
+
+/**
+*
+* @author mserngawy
+* AddCertTrustStore adding certificate to the ODL keyStore
+*/
+public class AddCertTrustStore extends OsgiCommandSupport {
+
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-cert",
+ aliases = { "--CertFile" },
+ description = "The node certificate file.\n-file / --should be accesable by the karaf command line",
+ required = true,
+ multiValued = false)
+ private String certFile = "";
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The Trust keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / node alias should be unique",
+ required = true,
+ multiValued = false)
+ private String alias = "";
+
+ public AddCertTrustStore(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ final FileInputStream fInputStream = new FileInputStream(certFile);
+ final byte[] certBytes = new byte[fInputStream.available()];
+ fInputStream.read(certBytes);
+ fInputStream.close();
+ final String certificate = new String(certBytes, StandardCharsets.UTF_8);
+ if (certProvider.addCertificateTrustStore(keyStorePassword, alias, certificate)) {
+ return alias + " certificate successfully added to trust keystore";
+ } else {
+ return "Failed to add " + alias + " certificate to trust keystore";
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+
+@Command(name = "gen-odl-ks", scope = "aaa", description = "Create the default keystore for the opendaylight controller.")
+
+/**
+ *
+ * @author mserngawy
+ * CreateODLKeyStore create the ODL keystore with new configuration.
+ */
+public class CreateODLKeyStore extends OsgiCommandSupport{
+
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-keystore",
+ aliases = { "--KeyStore" },
+ description = "The keystore name.\n-keystore / --default is ctl.jks",
+ required = false,
+ multiValued = false)
+ private String keyStoreName = "ctl.jks";
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / --default is controller",
+ required = false,
+ multiValued = false)
+ private String alias = "controller";
+
+ @Option(name = "-validity",
+ aliases = { "--validity" },
+ description = "The validity.\n-validity of the keystore certificate / --default is 365",
+ required = false,
+ multiValued = false)
+ private int validity = 365;
+
+ @Option(name = "-dName",
+ aliases = { "--dName" },
+ description = "The dName.\n-dName / --should be in the following formate CN=, OU=, O=, L= C=",
+ required = false,
+ multiValued = false)
+ private String dName = "CN=ODL, OU=Dev, O=LinuxFoundation, L=QC. Montreal, C=CA";
+
+ public CreateODLKeyStore(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(certProvider.createODLKeyStore(keyStoreName, keyStorePassword, alias, dName, validity));
+ sb.append("\n");
+ sb.append("08-aaa-cert-config.xml file should be updated with new keystore info");
+ return sb.toString();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+
+@Command(name = "gen-trust-ks", scope = "aaa", description = "Create the trust keystore for the opendaylight controller.")
+
+/**
+ *
+ * @author mserngawy
+ * CreateTrustKeyStore create trust key store with new configuration
+ */
+public class CreateTrustKeyStore extends OsgiCommandSupport{
+
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-keystore",
+ aliases = { "--KeyStore" },
+ description = "The keystore name.\n-keystore / --default is truststore.jks",
+ required = false,
+ multiValued = false)
+ private String keyStoreName = "truststore.jks";
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / --default is node",
+ required = false,
+ multiValued = false)
+ private String alias = "node";
+
+ public CreateTrustKeyStore(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(certProvider.createTrustKeyStore(keyStoreName, keyStorePassword, alias));
+ sb.append("\n");
+ sb.append("08-aaa-cert-config.xml file should be updated with new keystore info");
+ return sb.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(name = "gen-cert-req", scope = "aaa", description = "generate a certificate request for the opendaylight controller.")
+
+/**
+ *
+ * @author mserngawy
+ * GenerateCertReq from the ODL key store to be signed by the Certificate Authority 'CA'
+ */
+public class GenerateCertReq extends OsgiCommandSupport{
+
+ private static final Logger LOG = LoggerFactory.getLogger(GenerateCertReq.class);
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / --default is controller",
+ required = false,
+ multiValued = false)
+ private String alias = "controller";
+
+ public GenerateCertReq(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ return certProvider.genODLKeyStorCertificateReq(keyStorePassword, alias);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+
+@Command(name = "get-odl-cert", scope = "aaa", description = "get self sign certificate for the opendaylight controller.")
+
+/**
+ *
+ * @author mserngawy
+ * GetODLSelfSignCert get the ODL key store self sign certificate.
+ */
+public class GetODLSelfSignCert extends OsgiCommandSupport{
+
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / --default is controller",
+ required = false,
+ multiValued = false)
+ private String alias = "controller";
+
+ public GetODLSelfSignCert(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ return certProvider.getODLKeyStorCertificate(keyStorePassword, alias);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies. 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.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.aaa.cert.api.IAaaCertProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(name = "get-node-cert", scope = "aaa", description = "get node certificate form the opendaylight trust keystore .")
+
+/**
+ *
+ * @author mserngawy
+ * GetTrustStoreCert get a certain certificate stored in the trust key store using the its alias
+ */
+public class GetTrustStoreCert extends OsgiCommandSupport{
+
+ private static final Logger LOG = LoggerFactory.getLogger(GetTrustStoreCert.class);
+ protected IAaaCertProvider certProvider;
+
+ @Option(name = "-storepass",
+ aliases = { "--KeyStorePass" },
+ description = "The keystore password.\n-storepass",
+ required = true,
+ multiValued = false)
+ private String keyStorePassword = "";
+
+ @Option(name = "-alias",
+ aliases = { "--alias" },
+ description = "The alias.\n-alias / --should be the node certificate alias",
+ required = true,
+ multiValued = false)
+ private String alias = "";
+
+ public GetTrustStoreCert(final IAaaCertProvider aaaCertProvider) {
+ this.certProvider = aaaCertProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ return certProvider.getCertificateTrustStore(keyStorePassword, alias);
+ }
+
+}
--- /dev/null
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <reference id="KeyStoreConsoleProvider" availability="mandatory"
+ activation="eager" interface="org.opendaylight.aaa.cert.api.IAaaCertProvider">
+ </reference>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.aaa.cli.CreateODLKeyStore">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.GetODLSelfSignCert">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.GenerateCertReq">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.CreateTrustKeyStore">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.GetTrustStoreCert">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.AddCertTrustStore">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.aaa.cli.AddCertODLKeyStore">
+ <argument ref="KeyStoreConsoleProvider" />
+ </action>
+ </command>
+ </command-bundle>
+
+</blueprint>
\ No newline at end of file
<classifier>config</classifier>
<type>xml</type>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cli</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>features-aaa-shiro</artifactId>
<type>xml</type>
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa-cert</artifactId>
+ <classifier>features</classifier>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa-cli</artifactId>
+ <classifier>features</classifier>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+-->
+
+<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.odlparent</groupId>
+ <artifactId>features-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa-cert</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>${project.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <properties>
+ <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
+ <controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-cert</artifactId>
+ <version>${project.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-aether-provider</artifactId>
+ <version>3.0.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin-li</artifactId>
+ <version>${openflowplugin.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcprov-jdk15on</artifactId>
+ </dependency>
+ </dependencies>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/aaa.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/aaa.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=aaa.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+-->
+<features name="odl-aaa-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+
+ <repository>mvn:org.opendaylight.mdsal/features-mdsal/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.aaa/features-aaa/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-li/{{VERSION}}/xml/features</repository>
+
+ <feature name='odl-aaa-cert' description='OpenDaylight :: AAA :: aaa opendaylight certificate Plugin'
+ version='${project.version}'>
+ <feature version='${controller.mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-southbound-li</feature>
+
+ <bundle>mvn:org.bouncycastle/bcprov-jdk15on/{{VERSION}}</bundle>
+ <bundle>mvn:commons-codec/commons-codec/{{VERSION}}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/08-aaa-cert-config.xml">mvn:org.opendaylight.aaa/aaa-cert/{{VERSION}}/xml/config</configfile>
+ <bundle>mvn:org.opendaylight.aaa/aaa-cert/{{VERSION}}</bundle>
+ </feature>
+
+</features>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+-->
+
+<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.odlparent</groupId>
+ <artifactId>features-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa-cli</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-parent</artifactId>
+ <version>${project.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>features-aaa-cert</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.aaa</groupId>
+ <artifactId>aaa-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-aether-provider</artifactId>
+ <version>3.0.5</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/aaa.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/aaa.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=aaa.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Inocybe Technology 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 INTERNAL
+-->
+<features name="odl-aaa-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+
+ <repository>mvn:org.opendaylight.aaa/features-aaa-cert/{{VERSION}}/xml/features</repository>
+
+ <feature name='odl-aaa-cli' description='OpenDaylight :: AAA :: aaa opendaylight command line'
+ version='${project.version}'>
+ <feature version="${project.version}">odl-aaa-cert</feature>
+ <bundle>mvn:org.opendaylight.aaa/aaa-cli/{{VERSION}}</bundle>
+ </feature>
+
+</features>
<module>api</module>
<module>authn</module>
<module>authz</module>
+ <module>aaa-cert</module>
+ <module>aaa-cli</module>
</modules>
</project>
<module>aaa-shiro</module>
<module>aaa-shiro-act</module>
<module>aaa-h2-store</module>
+ <module>aaa-cert</module>
+ <module>aaa-cli</module>
</modules>
<scm>