9888c838b6fb923613b902c1545c88f9706bc933
[ccsdk/sli/adaptors.git] / aai-service / provider / src / main / java / org / onap / ccsdk / sli / adaptors / aai / AAIServiceProvider.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
6  *                         reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 /**
22  * @author Rich Tabedzki
23  *
24  */
25 package org.onap.ccsdk.sli.adaptors.aai;
26
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.IOException;
30 import java.lang.reflect.Method;
31 import java.util.Optional;
32 import java.util.Properties;
33 import java.util.Vector;
34
35 import org.onap.ccsdk.sli.core.utils.JREFileResolver;
36 import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
37 import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
38 import org.onap.ccsdk.sli.core.utils.common.BundleContextFileResolver;
39 import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
40 import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
41 import org.osgi.framework.BundleContext;
42 import org.osgi.framework.FrameworkUtil;
43 import org.osgi.framework.ServiceReference;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * Responsible for determining the properties file to use and instantiating the <code>DBResourceManager</code>
49  * Service.  The priority for properties file resolution is as follows:
50  *
51  * <ol>
52  *     <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
53  *     <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
54  *     <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
55  *     <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
56  * </ol>
57  *
58  * Encryption Support
59  * <ol>
60  *    <li>Uses ecryption provided by <code>AAAEncryptionService</code></li>
61  *    <li>AAA Configuration file is <code>aaa-cert-config.xml</code></li>
62  * </ol>
63  *
64  */
65 public class AAIServiceProvider implements UtilsProvider {
66
67     private static final Logger LOG = LoggerFactory.getLogger(AAIServiceProvider.class);
68
69     /**
70      * The name of the properties file for database configuration
71      */
72     private static final String AAISEERVICE_PROP_FILE_NAME = "aaiclient.properties";
73
74     /**
75      * The name of the pwd key
76      */
77     private static final String AAICLIENT_PROPERTY_NAME = "org.onap.ccsdk.sli.adaptors.aai.client.psswd";
78
79     /**
80      * A prioritized list of strategies for resolving dblib properties files.
81      */
82     private Vector<PropertiesFileResolver> dblibPropertiesFileResolvers = new Vector<>();
83
84     /**
85      * The configuration properties for the db connection.
86      */
87     private Properties properties;
88
89     /**
90      * Set up the prioritized list of strategies for resolving dblib properties files.
91      */
92     public AAIServiceProvider() {
93         dblibPropertiesFileResolvers.add(new SdncConfigEnvVarFileResolver(
94                 "Using property file (1) from environment variable"
95             ));
96         dblibPropertiesFileResolvers.add(new JREFileResolver(
97             "Using property file (2) from JRE argument", AAIServiceProvider.class
98         ));
99         dblibPropertiesFileResolvers.add(new BundleContextFileResolver(
100             "Using property file (3) from JRE argument", AAIServiceProvider.class
101         ));
102         dblibPropertiesFileResolvers.add(new KarafRootFileResolver(
103             "Using property file (4) from karaf root", this
104         ));
105         dblibPropertiesFileResolvers.add(new CoreDefaultFileResolver(
106             "Using property file (5) from default directory"
107         ));
108
109         // determines properties file as according to the priority described in the class header comment
110         final File propertiesFile = determinePropertiesFile();
111         if (propertiesFile != null) {
112             try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
113                 properties = new Properties();
114                 properties.load(fileInputStream);
115
116                 if(properties.containsKey(AAICLIENT_PROPERTY_NAME)) {
117                     String sensitive = properties.getProperty(AAICLIENT_PROPERTY_NAME);
118                     if(sensitive != null && sensitive.startsWith("ENC:")) {
119                         try {
120                             sensitive = sensitive.substring(4);
121                             String postsense = decrypt(sensitive);
122                             properties.setProperty(AAICLIENT_PROPERTY_NAME, postsense);
123                         } catch(Exception exc) {
124                             LOG.error("Failed to translate property", exc);
125                         }
126                     }
127                 }
128             } catch (final IOException e) {
129                 LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
130                         new AAIServiceException("Failed to load properties for file: "
131                                 + propertiesFile.toString(), e));
132             }
133         }
134     }
135
136     /**
137      *
138      * @param value
139      * @return decrypted string if successful or the original value if unsuccessful
140      */
141     private String decrypt(String value) {
142         try {
143             BundleContext bctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
144
145             ServiceReference sref = bctx.getServiceReference("org.opendaylight.aaa.encrypt.AAAEncryptionService");
146             if(sref == null) {
147                 LOG.warn("Could not acquire service reference for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
148                 return value;
149             }
150             Object encrSvc = bctx.getService(sref);
151             if(encrSvc == null) {
152                 LOG.warn("Could not access service for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
153                 return value;
154             }
155
156             Method gs2Method = encrSvc.getClass().getMethod("decrypt", new Class[] { "".getClass() });
157             Object unmasked = gs2Method.invoke(encrSvc, new Object[] { value });
158             return unmasked.toString();
159
160         } catch (Exception exc) {
161             LOG.error("Failure", exc);
162             return value;
163         }
164     }
165
166     /**
167      * Extract db config properties.
168      *
169      * @return the db config properties
170      */
171     public Properties getProperties() {
172         return properties;
173     }
174
175     /**
176      * Reports the method chosen for properties resolution to the <code>Logger</code>.
177      *
178      * @param message Some user friendly message
179      * @param fileOptional The file location of the chosen properties file
180      * @return the file location of the chosen properties file
181      */
182     private static File reportSuccess(final String message, final Optional<File> fileOptional) {
183         if(fileOptional.isPresent()) {
184             final File file = fileOptional.get();
185             LOG.info("{} {}", message, file.getPath());
186             return file;
187         }
188         return null;
189     }
190
191     /**
192      * Reports fatal errors.  This is the case in which no properties file could be found.
193      *
194      * @param message An appropriate fatal error message
195      * @param dblibConfigurationException An exception describing what went wrong during resolution
196      */
197     private static void reportFailure(final String message,
198                                       final AAIServiceException dblibConfigurationException) {
199
200         LOG.error("{}", message, dblibConfigurationException);
201     }
202
203     /**
204      * Determines the dblib properties file to use based on the following priority:
205      * <ol>
206      *     <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
207      *     <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
208      *     <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
209      *     <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
210      * </ol>
211      */
212     File determinePropertiesFile() {
213
214         for (final PropertiesFileResolver dblibPropertiesFileResolver : dblibPropertiesFileResolvers) {
215             final Optional<File> fileOptional = dblibPropertiesFileResolver.resolveFile(AAISEERVICE_PROP_FILE_NAME);
216             if (fileOptional.isPresent()) {
217                 return reportSuccess(dblibPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
218             }
219         }
220
221         reportFailure("Missing configuration properties resource(3)",
222                 new AAIServiceException("Missing configuration properties resource(3): "
223                         + AAISEERVICE_PROP_FILE_NAME));
224         return null;
225     }
226 }