Initial OpenECOMP policy/engine commit
[policy/engine.git] / ECOMP-XACML / src / main / java / org / openecomp / policy / xacml / std / pip / engines / aaf / AAFEngine.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-XACML
4  * ================================================================================
5  * Copyright (C) 2017 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 package org.openecomp.policy.xacml.std.pip.engines.aaf;
21
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Properties;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.openecomp.policy.utils.AAFPolicyClient;
33 import org.openecomp.policy.utils.AAFPolicyException;
34
35 import com.att.research.xacml.api.Attribute;
36 import com.att.research.xacml.api.AttributeValue;
37 import com.att.research.xacml.api.Identifier;
38 import com.att.research.xacml.api.XACML3;
39 import com.att.research.xacml.api.pip.PIPException;
40 import com.att.research.xacml.api.pip.PIPFinder;
41 import com.att.research.xacml.api.pip.PIPRequest;
42 import com.att.research.xacml.api.pip.PIPResponse;
43 import com.att.research.xacml.std.IdentifierImpl;
44 import com.att.research.xacml.std.StdMutableAttribute;
45 import com.att.research.xacml.std.datatypes.DataTypes;
46 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
47 import com.att.research.xacml.std.pip.StdPIPRequest;
48 import com.att.research.xacml.std.pip.StdPIPResponse;
49 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
50
51 /**
52  * PIP Engine for Implementing {@link com.att.research.xacml.std.pip.engines.ConfigurableEngine} interface to provide
53  * attribute retrieval from AT&T AAF interface.  
54  * 
55  * @version $Revision$
56  */
57 public class AAFEngine extends StdConfigurableEngine {
58         
59         public static final String DEFAULT_DESCRIPTION          = "PIP for authenticating aaf attributes using the AT&T AAF REST interface";
60         public static final String DEFAULT_ISSUER                       = "att-aaf";
61         
62         private static final String SUCCESS = "Success";
63         
64         public static final String AAF_RESULT= "AAF_RESULT";
65         public static final String AAF_RESPONSE= "AAF_RESPONSE";
66         // 
67         public static final Identifier AAF_RESPONSE_ID = new IdentifierImpl(AAF_RESPONSE);
68         public static final Identifier AAF_RESULT_ID = new IdentifierImpl(AAF_RESULT);
69         
70         //
71         private static final PIPRequest PIP_REQUEST_UID = new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_ID"), XACML3.ID_DATATYPE_STRING);
72         private static final PIPRequest PIP_REQUEST_PASS =  new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_PASS"), XACML3.ID_DATATYPE_STRING);
73         private static final PIPRequest PIP_REQUEST_TYPE = new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_TYPE"), XACML3.ID_DATATYPE_STRING);
74         private static final PIPRequest PIP_REQUEST_INSTANCE = new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_INSTANCE"), XACML3.ID_DATATYPE_STRING);
75         private static final PIPRequest PIP_REQUEST_ACTION = new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_ACTION"), XACML3.ID_DATATYPE_STRING);
76         private static final PIPRequest PIP_REQUEST_ENV = new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new IdentifierImpl("AAF_ENVIRONMENT"), XACML3.ID_DATATYPE_STRING);
77         
78         private static final List<PIPRequest> mapRequiredAttributes     = new ArrayList<PIPRequest>();
79         static{ 
80                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_UID));
81                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_PASS));
82                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_TYPE));
83                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_INSTANCE));
84                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_ACTION));
85                 mapRequiredAttributes.add(new StdPIPRequest(PIP_REQUEST_ENV));
86         }
87         
88         private static final Map<PIPRequest, String> mapSupportedAttributes     = new HashMap<PIPRequest, String>();
89         static{
90                 mapSupportedAttributes.put(new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, AAF_RESPONSE_ID, XACML3.ID_DATATYPE_STRING), "response");
91                 mapSupportedAttributes.put(new StdPIPRequest(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, AAF_RESULT_ID, XACML3.ID_DATATYPE_BOOLEAN), "result");
92         }
93         
94         protected Log logger    = LogFactory.getLog(this.getClass());
95         
96         public AAFEngine(){
97         }
98         
99         private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
100                 PIPResponse pipResponse = null;
101                 try {
102                         pipResponse     = pipFinder.getMatchingAttributes(pipRequest, this);
103                         if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
104                                 this.logger.warn("Error retrieving " + pipRequest.getAttributeId().stringValue() + ": " + pipResponse.getStatus().toString());
105                                 pipResponse     = null;
106                         }
107                         if (pipResponse.getAttributes().size() == 0) {
108                                 this.logger.warn("No value for " + pipRequest.getAttributeId().stringValue());
109                                 pipResponse     = null;
110                         }
111                 } catch (PIPException ex) {
112                         this.logger.error("PIPException getting subject-id attribute: " + ex.getMessage(), ex);                 
113                 }
114                 return pipResponse;
115         }
116         
117         private String getValue(PIPResponse pipResponse){
118                 String result = null;
119                 Collection<Attribute> listAttributes = pipResponse.getAttributes();
120                 for(Attribute attribute: listAttributes){
121                         Iterator<AttributeValue<String>> iterAttributeValues = attribute.findValues(DataTypes.DT_STRING);
122                         if(iterAttributeValues!=null) {
123                                 while(iterAttributeValues.hasNext()){
124                                         result = iterAttributeValues.next().getValue();
125                                         break;
126                                 }
127                         }
128                 }
129                 return result;
130         }
131         
132         private synchronized String getResult(PIPFinder pipFinder) {
133                 PIPResponse pipResponseUID = this.getAttribute(PIP_REQUEST_UID, pipFinder);
134                 PIPResponse pipResponsePass = this.getAttribute(PIP_REQUEST_PASS, pipFinder);
135                 PIPResponse pipResponseType = this.getAttribute(PIP_REQUEST_TYPE, pipFinder);
136                 PIPResponse pipResponseAction = this.getAttribute(PIP_REQUEST_ACTION, pipFinder);
137                 PIPResponse pipResponseInstance = this.getAttribute(PIP_REQUEST_INSTANCE, pipFinder);
138                 PIPResponse pipResponseEnv = this.getAttribute(PIP_REQUEST_ENV, pipFinder);
139                 String response = null;
140                 // Evaluate AAF if we have all the required values. 
141                 if(pipResponseUID!=null && pipResponsePass!=null && pipResponseType != null && pipResponseAction!= null && pipResponseInstance!=null && pipResponseEnv!=null){
142                         // Check the Environment. 
143                         String environment = getValue(pipResponseEnv);
144                         if(environment == null){
145                                 response = "Environment Value is not set. ";
146                         }
147                         String userName = getValue(pipResponseUID);
148                         String pass = getValue(pipResponsePass);
149                         AAFPolicyClient aafClient = null;
150                         Properties properties = new Properties();
151                         if(environment.equalsIgnoreCase("PROD")){
152                                 properties.setProperty("ENVIRONMENT", "PROD");
153                         }else if(environment.equalsIgnoreCase("TEST")){
154                                 properties.setProperty("ENVIRONMENT", "TEST");
155                         }else{
156                                 properties.setProperty("ENVIRONMENT", "DEVL");
157                         }
158                         logger.debug("environment : " + environment);
159                         if(userName!=null && pass!=null){
160                                 try {
161                                         aafClient = AAFPolicyClient.getInstance(properties);
162                                 } catch (AAFPolicyException e) {
163                                         logger.error("AAF configuration failed. " + e.getMessage());
164                                 }
165                                 if(aafClient!=null){
166                                         if(aafClient.checkAuth(userName, pass)){
167                                                 String type = getValue(pipResponseType);
168                                                 String instance = getValue(pipResponseInstance);
169                                                 String action = getValue(pipResponseAction);
170                                                 if(aafClient.checkPerm(userName, pass, type, instance, action)){
171                                                         response = SUCCESS + "Permissions Validated";
172                                                 }else{
173                                                         response = "No Permissions for "+userName+" to: "+type+", "+instance+", "+action; 
174                                                 }
175                                         }else{
176                                                 response = "Authentication Failed for the given Values";
177                                         }
178                                 }
179                         }else{
180                                 response = "ID and Password are not given";
181                         }
182                         
183                 }else{
184                         response = "Insufficient Values to Evaluate AAF";
185                 }
186                 return response;
187         }
188         
189         private void addStringAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, String value) {
190                 if (value != null) {
191                         AttributeValue<String> attributeValue   = null;
192                         try {
193                                 attributeValue  = DataTypes.DT_STRING.createAttributeValue(value);
194                         } catch (Exception ex) {
195                                 this.logger.error("Failed to convert " + value + " to an AttributeValue<String>", ex);
196                         }
197                         if (attributeValue != null) {
198                                 stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, this.getIssuer(), false));
199                         }
200                 }
201         }
202
203         private void addBooleanAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, boolean value) {
204                 AttributeValue<Boolean> attributeValue  = null;
205                 try {
206                         attributeValue  = DataTypes.DT_BOOLEAN.createAttributeValue(value);
207                 } catch (Exception ex) {
208                         this.logger.error("Failed to convert " + value + " to an AttributeValue<Boolean>", ex);
209                 }
210                 if (attributeValue != null) {
211                         stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, this.getIssuer(), false));
212                 }
213         }
214         
215         @Override
216         public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
217                 /*
218                  * First check to see if the issuer is set and then match it
219                  */
220                 String string;
221                 if ((string = pipRequest.getIssuer()) != null) {
222                         if (!string.equals(this.getIssuer())) {
223                                 this.logger.debug("Requested issuer '" + string + "' does not match " + (this.getIssuer() == null ? "null" : "'" + this.getIssuer() + "'"));
224                                 return StdPIPResponse.PIP_RESPONSE_EMPTY;
225                         }
226                 }
227                 
228                 /*
229                  * Drop the issuer and see if the request matches any of our supported queries
230                  */
231                 PIPRequest pipRequestSupported  = (pipRequest.getIssuer() == null ? pipRequest : new StdPIPRequest(pipRequest.getCategory(), pipRequest.getAttributeId(), pipRequest.getDataTypeId()));
232                 if (!mapSupportedAttributes.containsKey(pipRequestSupported)) {
233                         this.logger.debug("Requested attribute '" + pipRequest.toString() + "' is not supported");
234                         return StdPIPResponse.PIP_RESPONSE_EMPTY;
235                 }
236                 StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse();
237                 String response = this.getResult(pipFinder);
238                 boolean result = false;
239                 if(response.contains(SUCCESS)){
240                         result = true;
241                 }
242                 this.addBooleanAttribute(stdPIPResponse, XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, AAF_RESULT_ID, result);
243                 this.addStringAttribute(stdPIPResponse, XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, AAF_RESPONSE_ID, response);
244                 return new StdPIPResponse(stdPIPResponse);
245         }
246
247         @Override
248         public void configure(String id, Properties properties) throws PIPException {
249                 super.configure(id, properties);
250                 if (this.getDescription() == null) {
251                         this.setDescription(DEFAULT_DESCRIPTION);
252                 }
253                 if (this.getIssuer() == null) {
254                         this.setIssuer(DEFAULT_ISSUER);
255                 }
256         }
257         
258         @Override
259         public Collection<PIPRequest> attributesRequired() {
260                 List<PIPRequest> attributes = new ArrayList<PIPRequest>();
261                 for (PIPRequest attribute: mapRequiredAttributes) {
262                         attributes.add(new StdPIPRequest(attribute));
263                 }
264                 return attributes;
265         }
266
267         @Override
268         public Collection<PIPRequest> attributesProvided() {
269                 List<PIPRequest> attributes = new ArrayList<PIPRequest>();
270                 for (PIPRequest attribute : mapSupportedAttributes.keySet()) {
271                         attributes.add(new StdPIPRequest(attribute));
272                 }
273                 return attributes;
274         }
275         
276 }