Merge changes Ia268965a,Iefa79f99
[controller.git] / opendaylight / netconf / netconf-util / src / main / java / org / opendaylight / controller / netconf / util / osgi / NetconfConfigUtil.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.controller.netconf.util.osgi;
10
11 import com.google.common.base.Optional;
12 import org.opendaylight.protocol.util.SSLUtil;
13 import org.osgi.framework.BundleContext;
14
15 import javax.net.ssl.KeyManagerFactory;
16 import javax.net.ssl.SSLContext;
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.InputStream;
20 import java.net.InetSocketAddress;
21
22 import static com.google.common.base.Preconditions.checkNotNull;
23 import static com.google.common.base.Preconditions.checkState;
24
25 public class NetconfConfigUtil {
26     private static final String PREFIX_PROP = "netconf.";
27
28     private enum InfixProp {
29         tcp, tls, ssh
30     }
31
32     private static final String PORT_SUFFIX_PROP = ".port";
33     private static final String ADDRESS_SUFFIX_PROP = ".address";
34
35     private static final String NETCONF_TLS_KEYSTORE_PROP = PREFIX_PROP + InfixProp.tls + ".keystore";
36     private static final String NETCONF_TLS_KEYSTORE_PASSWORD_PROP = NETCONF_TLS_KEYSTORE_PROP + ".password";
37
38     public static InetSocketAddress extractTCPNetconfAddress(BundleContext context, String exceptionMessageIfNotFound) {
39
40         Optional<InetSocketAddress> inetSocketAddressOptional = extractSomeNetconfAddress(context, InfixProp.tcp);
41         if (inetSocketAddressOptional.isPresent() == false) {
42             throw new IllegalStateException("Netconf tcp address not found." + exceptionMessageIfNotFound);
43         }
44         return inetSocketAddressOptional.get();
45     }
46
47     public static Optional<InetSocketAddress> extractSSHNetconfAddress(BundleContext context) {
48         return extractSomeNetconfAddress(context, InfixProp.ssh);
49     }
50
51
52     public static Optional<TLSConfiguration> extractTLSConfiguration(BundleContext context) {
53         Optional<InetSocketAddress> address = extractSomeNetconfAddress(context, InfixProp.tls);
54         if (address.isPresent()) {
55             String keystoreFileName = context.getProperty(NETCONF_TLS_KEYSTORE_PROP);
56             File keystoreFile = new File(keystoreFileName);
57             checkState(keystoreFile.exists() && keystoreFile.isFile() && keystoreFile.canRead(),
58                     "Keystore file %s does not exist or is not readable file", keystoreFileName);
59             keystoreFile = keystoreFile.getAbsoluteFile();
60             String keystorePassword = context.getProperty(NETCONF_TLS_KEYSTORE_PASSWORD_PROP);
61             checkNotNull(keystoreFileName, "Property %s must be defined for tls netconf server",
62                     NETCONF_TLS_KEYSTORE_PROP);
63             keystorePassword = keystorePassword != null ? keystorePassword : "";
64             return Optional.of(new TLSConfiguration(address.get(), keystoreFile, keystorePassword));
65         } else {
66             return Optional.absent();
67         }
68     }
69
70     public static class TLSConfiguration {
71         private final InetSocketAddress address;
72         private final File keystoreFile;
73         private final String keystorePassword;
74         private final SSLContext sslContext;
75
76         TLSConfiguration(InetSocketAddress address, File keystoreFile, String keystorePassword) {
77             this.address = address;
78             this.keystoreFile = keystoreFile;
79             this.keystorePassword = keystorePassword;
80             try {
81                 try (InputStream keyStoreIS = new FileInputStream(keystoreFile)) {
82                     try (InputStream trustStoreIS = new FileInputStream(keystoreFile)) {
83                         sslContext = SSLUtil.initializeSecureContext("password", keyStoreIS, trustStoreIS, KeyManagerFactory.getDefaultAlgorithm());
84                     }
85                 }
86             } catch (Exception e) {
87                 throw new RuntimeException("Cannot initialize ssl context for netconf file " + keystoreFile, e);
88             }
89         }
90
91         public SSLContext getSslContext() {
92             return sslContext;
93         }
94
95         public InetSocketAddress getAddress() {
96             return address;
97         }
98
99         public File getKeystoreFile() {
100             return keystoreFile;
101         }
102
103         public String getKeystorePassword() {
104             return keystorePassword;
105         }
106     }
107
108     /**
109      * @param context
110      *            from which properties are being read.
111      * @param infixProp
112      *            either tcp or tls
113      * @return absent if address is missing, value if address and port are
114      *         valid.
115      * @throws IllegalStateException
116      *             if address or port are invalid
117      */
118     private static Optional<InetSocketAddress> extractSomeNetconfAddress(BundleContext context,
119             InfixProp infixProp) {
120         String address = context.getProperty(PREFIX_PROP + infixProp + ADDRESS_SUFFIX_PROP);
121         if (address == null) {
122             return Optional.absent();
123         }
124         String portKey = PREFIX_PROP + infixProp + PORT_SUFFIX_PROP;
125         String portString = context.getProperty(portKey);
126         checkNotNull(portString, "Netconf port must be specified in properties file with " + portKey);
127         try {
128             int port = Integer.valueOf(portString);
129             return Optional.of(new InetSocketAddress(address, port));
130         } catch (RuntimeException e) {
131             throw new IllegalStateException("Cannot create " + infixProp + " netconf address from address:" + address
132                     + " and port:" + portString, e);
133         }
134     }
135 }