Enhancement to use the common CryptoUtils
[policy/engine.git] / ONAP-PDP-REST / src / main / java / org / onap / policy / pdp / rest / config / PDPApiAuth.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PDP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdp.rest.config;
22
23 import com.att.research.xacml.util.XACMLProperties;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Base64;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Properties;
37 import java.util.StringTokenizer;
38 import org.onap.policy.api.PolicyEngineException;
39 import org.onap.policy.common.logging.eelf.MessageCodes;
40 import org.onap.policy.common.logging.flexlogger.FlexLogger;
41 import org.onap.policy.common.logging.flexlogger.Logger;
42 import org.onap.policy.rest.XACMLRestProperties;
43 import org.onap.policy.utils.AAFPolicyClient;
44 import org.onap.policy.utils.AAFPolicyException;
45 import org.onap.policy.utils.PeCryptoUtils;
46 import org.onap.policy.utils.PolicyUtils;
47 import org.onap.policy.xacml.api.XACMLErrorConstants;
48
49 public class PDPApiAuth {
50     private static final Logger LOGGER = FlexLogger.getLogger(PDPApiAuth.class);
51
52     private static String environment = null;
53     private static Path clientPath = null;
54     private static Map<String, ArrayList<String>> clientMap = null;
55     private static Long oldModified = null;
56     private static AAFPolicyClient aafClient = null;
57
58     private PDPApiAuth() {
59         // Private Constructor
60     }
61
62     /*
63      * Set Property by reading the properties File.
64      */
65     public static void setProperty() {
66         environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL");
67         String clientFile = XACMLProperties.getProperty(XACMLRestProperties.PROP_PEP_IDFILE);
68         if (clientFile != null) {
69             clientPath = Paths.get(clientFile);
70         }
71         try {
72             aafClient = AAFPolicyClient.getInstance(XACMLProperties.getProperties());
73         } catch (AAFPolicyException | IOException e) {
74             LOGGER.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "AAF Client Not instantiated properly.");
75         }
76     }
77
78     /*
79      * Return Environment value of the PDP servlet.
80      */
81     public static String getEnvironment() {
82         if (environment == null) {
83             setProperty();
84         }
85         return environment;
86     }
87
88     /*
89      * Security check for authentication and authorizations.
90      */
91     public static boolean checkPermissions(String clientEncoding, String requestID, String resource) {
92         try {
93             String[] userNamePass = PolicyUtils.decodeBasicEncoding(clientEncoding);
94             if (userNamePass == null || userNamePass.length == 0) {
95                 String usernameAndPassword = null;
96                 byte[] decodedBytes = Base64.getDecoder().decode(clientEncoding);
97                 usernameAndPassword = new String(decodedBytes, "UTF-8");
98                 StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
99                 String username = tokenizer.nextToken();
100                 String password = tokenizer.nextToken();
101                 userNamePass = new String[] {username, password};
102             }
103             LOGGER.info("User " + userNamePass[0] + " is Accessing Policy Engine API.");
104             Boolean result = false;
105             // Check Backward Compatibility.
106             try {
107                 /*
108                  * If AAF is NOT enabled in the properties we will allow the user to continue to use the
109                  * client.properties file to authenticate. Note: Disabling AAF is for testing purposes and not intended
110                  * for production.
111                  */
112                 if ("false".equals(XACMLProperties.getProperty("enable_aaf"))) {
113                     result = clientAuth(userNamePass);
114                 }
115             } catch (Exception e) {
116                 LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e);
117             }
118             if (!result) {
119                 String aafPolicyNameSpace = XACMLProperties.getProperty("policy.aaf.namespace");
120                 String aafResource = XACMLProperties.getProperty("policy.aaf.root.permission");
121                 String type = null;
122                 if (!userNamePass[0].contains("@") && aafPolicyNameSpace != null) {
123                     userNamePass[0] = userNamePass[0] + "@" + reverseNamespace(aafPolicyNameSpace);
124                 } else {
125                     LOGGER.info("No AAF NameSpace specified in properties");
126                 }
127                 if (aafResource != null) {
128                     type = aafResource + "." + resource;
129                 } else {
130                     LOGGER.warn("No AAF Resource specified in properties");
131                     return false;
132                 }
133                 LOGGER.info("Contacting AAF in : " + environment);
134                 result = aafClient.checkAuthPerm(userNamePass[0], userNamePass[1], type, environment, "*");
135             }
136             return result;
137         } catch (Exception e) {
138             LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e);
139             return false;
140         }
141     }
142
143     private static Boolean clientAuth(String[] userNamePass) {
144         if (clientPath == null) {
145             setProperty();
146         }
147         if (!clientPath.toFile().exists()) {
148             return false;
149         } else if (clientPath.toString().endsWith(".properties")) {
150             try {
151                 readProps(clientPath);
152                 if (clientMap.containsKey(userNamePass[0])
153                         && clientMap.get(userNamePass[0]).get(0).equals(userNamePass[1])) {
154                     return true;
155                 }
156             } catch (PolicyEngineException e) {
157                 LOGGER.error(MessageCodes.ERROR_PERMISSIONS, e);
158                 return false;
159             }
160         }
161         return false;
162     }
163
164     private static String reverseNamespace(String namespace) {
165         final List<String> components = Arrays.asList(namespace.split("\\."));
166         Collections.reverse(components);
167         return String.join(".", components);
168     }
169
170     private static Map<String, ArrayList<String>> readProps(Path clientPath) throws PolicyEngineException {
171         if (oldModified != null) {
172             Long newModified = clientPath.toFile().lastModified();
173             if (newModified == oldModified) {
174                 return clientMap;
175             }
176         }
177         InputStream in;
178         Properties clientProp = new Properties();
179         try {
180             in = new FileInputStream(clientPath.toFile());
181             clientProp.load(in);
182         } catch (IOException e) {
183             LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR, e);
184             throw new PolicyEngineException(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Cannot Load the Properties file",
185                     e);
186         }
187         // Read the Properties and Load the Clients and their scopes.
188         clientMap = new HashMap<>();
189         //
190         for (Object propKey : clientProp.keySet()) {
191             String clientID = (String) propKey;
192             String clientValue = clientProp.getProperty(clientID);
193             if (clientValue != null && clientValue.contains(",")) {
194                 ArrayList<String> clientValues = new ArrayList<>(Arrays.asList(clientValue.split("\\s*,\\s*")));
195                 if (clientValues.get(0) != null || clientValues.get(1) != null || clientValues.get(0).isEmpty()
196                         || clientValues.get(1).isEmpty()) {
197                     clientValues.set(0, PeCryptoUtils.decrypt(clientValues.get(0)));
198                     clientMap.put(clientID, clientValues);
199                 }
200             }
201         }
202         if (clientMap.isEmpty()) {
203             LOGGER.debug(XACMLErrorConstants.ERROR_PERMISSIONS
204                     + "No Clients ID , Client Key and Scopes are available. Cannot serve any Clients !!");
205             throw new PolicyEngineException("Empty Client file");
206         }
207         oldModified = clientPath.toFile().lastModified();
208         return clientMap;
209     }
210 }