Mass whitespace changes (Style Warnings)
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / aaf / v2_0 / AAFCon.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 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
22 package org.onap.aaf.cadi.aaf.v2_0;
23
24 import java.net.URI;
25 import java.util.Map;
26 import java.util.concurrent.ConcurrentHashMap;
27
28 import org.onap.aaf.cadi.AbsUserCache;
29 import org.onap.aaf.cadi.Access;
30 import org.onap.aaf.cadi.CadiException;
31 import org.onap.aaf.cadi.CadiWrap;
32 import org.onap.aaf.cadi.Connector;
33 import org.onap.aaf.cadi.Locator;
34 import org.onap.aaf.cadi.LocatorException;
35 import org.onap.aaf.cadi.Lur;
36 import org.onap.aaf.cadi.PropAccess;
37 import org.onap.aaf.cadi.SecuritySetter;
38 import org.onap.aaf.cadi.aaf.AAFPermission;
39 import org.onap.aaf.cadi.aaf.marshal.CertsMarshal;
40 import org.onap.aaf.cadi.client.Future;
41 import org.onap.aaf.cadi.client.Rcli;
42 import org.onap.aaf.cadi.client.Retryable;
43 import org.onap.aaf.cadi.config.Config;
44 import org.onap.aaf.cadi.config.SecurityInfoC;
45 import org.onap.aaf.cadi.lur.EpiLur;
46 import org.onap.aaf.cadi.principal.BasicPrincipal;
47 import org.onap.aaf.cadi.principal.TaggedPrincipal;
48 import org.onap.aaf.cadi.util.FQI;
49 import org.onap.aaf.cadi.util.Vars;
50 import org.onap.aaf.misc.env.APIException;
51 import org.onap.aaf.misc.env.Data.TYPE;
52 import org.onap.aaf.misc.rosetta.env.RosettaDF;
53 import org.onap.aaf.misc.rosetta.env.RosettaEnv;
54
55 import aaf.v2_0.Certs;
56 import aaf.v2_0.Error;
57 import aaf.v2_0.Perms;
58 import aaf.v2_0.Users;
59
60 public abstract class AAFCon<CLIENT> implements Connector {
61     final public Access access;
62     // Package access
63     final public int timeout, cleanInterval, connTimeout;
64     final public int highCount, userExpires, usageRefreshTriggerCount;
65     private Map<String,Rcli<CLIENT>> clients = new ConcurrentHashMap<>();
66     final public RosettaDF<Perms> permsDF;
67     final public RosettaDF<Certs> certsDF;
68     final public RosettaDF<Users> usersDF;
69     final public RosettaDF<Error> errDF;
70     private String realm;
71     public final String app;
72     protected SecurityInfoC<CLIENT> si;
73
74     private AAFLurPerm lur;
75
76     final public RosettaEnv env;
77     protected abstract URI initURI();
78     protected abstract void setInitURI(String uriString) throws CadiException;
79     /*
80     protected abstract SecuritySetter<CLIENT>  bestSS(SecurityInfoC<CLIENT> si) throws CadiException;
81     */
82     
83     /**
84      * Use this call to get the appropriate client based on configuration (HTTP, future)
85      * 
86      * @param apiVersion
87      * @return
88      * @throws CadiException
89      */
90     public Rcli<CLIENT> client(String apiVersion) throws CadiException {
91         Rcli<CLIENT> client = clients.get(apiVersion);
92         if (client==null) {
93             client = rclient(initURI(),si.defSS);
94             client.apiVersion(apiVersion)
95                   .readTimeout(connTimeout);
96             clients.put(apiVersion, client);
97         } 
98         return client;
99     }
100
101     public Rcli<CLIENT> client(URI uri) throws CadiException {
102         return rclient(uri,si.defSS).readTimeout(connTimeout);
103     }
104     
105     /**
106      * Use this API when you have permission to have your call act as the end client's ID.
107      * 
108      *  Your calls will get 403 errors if you do not have this permission.  it is a special setup, rarely given.
109      * 
110      * @param apiVersion
111      * @param req
112      * @return
113      * @throws CadiException
114      */
115     public Rcli<CLIENT> clientAs(String apiVersion, TaggedPrincipal p) throws CadiException {
116         Rcli<CLIENT> cl = client(apiVersion);
117         return cl.forUser(transferSS(p));
118     }
119     
120     protected AAFCon(AAFCon<CLIENT> copy) {
121         access = copy.access;
122         timeout = copy.timeout;
123         cleanInterval = copy.cleanInterval;
124         connTimeout = copy.connTimeout;
125         highCount = copy.highCount;
126         userExpires = copy.userExpires;
127         usageRefreshTriggerCount = copy.usageRefreshTriggerCount;
128         permsDF = copy.permsDF;
129         certsDF = copy.certsDF;
130         usersDF = copy.usersDF;
131         errDF = copy.errDF;
132         app = copy.app;
133         si = copy.si;
134         env = copy.env;
135         realm = copy.realm;
136     }
137     
138     protected AAFCon(Access access, String tag, SecurityInfoC<CLIENT> si) throws CadiException{
139         if (tag==null) {
140             throw new CadiException("AAFCon cannot be constructed without a property tag or URL");
141         } else {
142             String str = access.getProperty(tag,null);
143             if (str==null) {
144                 if (tag.contains("://")) { // assume a URL
145                     str = tag;
146                 } else {
147                     throw new CadiException("A URL or " + tag + " property is required.");
148                 }
149             }
150             setInitURI(str);
151         }
152         try {
153             this.access = access;
154             this.si = si;
155             if (si.defSS.getID().equals(SecurityInfoC.DEF_ID)) { // it's the Preliminary SS, try to get a better one
156                 String mechid = access.getProperty(Config.AAF_APPID, null);
157                 if (mechid==null) {
158                     mechid=access.getProperty(Config.OAUTH_CLIENT_ID,null);
159                 }
160                 String encpass = access.getProperty(Config.AAF_APPPASS, null);
161                 if (encpass==null) {
162                     encpass = access.getProperty(Config.OAUTH_CLIENT_SECRET,null);
163                 }
164                 if (encpass==null) {
165                     String alias = access.getProperty(Config.CADI_ALIAS, mechid);
166                     if (alias==null) {
167                         access.printf(Access.Level.WARN,"%s, %s or %s required before use.", Config.CADI_ALIAS, Config.AAF_APPID, Config.OAUTH_CLIENT_ID);
168                         set(si.defSS);
169                     } else {
170                         si.defSS=x509Alias(alias);
171                         set(si.defSS);
172                     }
173                 } else {
174                     if (mechid!=null) {
175                         si.defSS=basicAuth(mechid, encpass);
176                         set(si.defSS);
177                     } else {
178                         si.defSS=new SecuritySetter<CLIENT>() {
179
180                             @Override
181                             public String getID() {
182                                 return "";
183                             }
184
185                             @Override
186                             public void setSecurity(CLIENT client) throws CadiException {
187                                 throw new CadiException("AAFCon has not been initialized with Credentials (SecuritySetter)");
188                             }
189
190                             @Override
191                             public int setLastResponse(int respCode) {
192                                 return 0;
193                             }
194                         };
195                         set(si.defSS);
196                     }
197                 }
198             }
199             
200             timeout = Integer.parseInt(access.getProperty(Config.AAF_CALL_TIMEOUT, Config.AAF_CALL_TIMEOUT_DEF));
201             cleanInterval = Integer.parseInt(access.getProperty(Config.AAF_CLEAN_INTERVAL, Config.AAF_CLEAN_INTERVAL_DEF));
202             highCount = Integer.parseInt(access.getProperty(Config.AAF_HIGH_COUNT, Config.AAF_HIGH_COUNT_DEF).trim());
203             connTimeout = Integer.parseInt(access.getProperty(Config.AAF_CONN_TIMEOUT, Config.AAF_CONN_TIMEOUT_DEF).trim());
204             userExpires = Integer.parseInt(access.getProperty(Config.AAF_USER_EXPIRES, Config.AAF_USER_EXPIRES_DEF).trim());
205             usageRefreshTriggerCount = Integer.parseInt(access.getProperty(Config.AAF_USER_EXPIRES, Config.AAF_USER_EXPIRES_DEF).trim())-1; // zero based
206     
207             app=FQI.reverseDomain(si.defSS.getID());
208             //TODO Get Realm from AAF
209             realm="people.osaaf.org";
210     
211             env = new RosettaEnv();
212             permsDF = env.newDataFactory(Perms.class);
213             usersDF = env.newDataFactory(Users.class);
214             certsDF = env.newDataFactory(Certs.class);
215             certsDF.rootMarshal(new CertsMarshal()); // Speedier Marshaling
216             errDF = env.newDataFactory(Error.class);
217         } catch (APIException e) {
218             throw new CadiException("AAFCon cannot be configured",e);
219         }
220     }
221     
222     public RosettaEnv env() {
223         return env;
224     }
225     
226     /**
227      * Return the backing AAFCon, if there is a Lur Setup that is AAF.
228      * 
229      * If there is no AAFLur setup, it will return "null"
230      * @param servletRequest
231      * @return
232      */
233     public static final AAFCon<?> obtain(Object servletRequest) {
234         if (servletRequest instanceof CadiWrap) {
235             Lur lur = ((CadiWrap)servletRequest).getLur();
236             if (lur != null) {
237                 if (lur instanceof EpiLur) {
238                     AbsAAFLur<?> aal = (AbsAAFLur<?>) ((EpiLur)lur).subLur(AbsAAFLur.class);
239                     if (aal!=null) {
240                         return aal.aaf;
241                     }
242                 } else {
243                     if (lur instanceof AbsAAFLur) {
244                         return ((AbsAAFLur<?>)lur).aaf;
245                     }
246                 }
247             }
248         }
249         return null;
250     }
251     
252     public abstract AAFCon<CLIENT> clone(String url) throws CadiException, LocatorException;
253     
254     public AAFAuthn<CLIENT> newAuthn() throws APIException {
255         try {
256             return new AAFAuthn<>(this);
257         } catch (Exception e) {
258             throw new APIException(e);
259         }
260     }
261
262     public AAFAuthn<CLIENT> newAuthn(AbsUserCache<AAFPermission> c) {
263         return new AAFAuthn<>(this, c);
264     }
265
266     public AAFLurPerm newLur() throws CadiException {
267         try {
268             if (lur==null) {
269                 lur = new AAFLurPerm(this);
270                 return lur;
271             } else {
272                 return new AAFLurPerm(this,lur);
273             }
274         } catch (CadiException e) {
275             throw e;
276         } catch (Exception e) {
277             throw new CadiException(e);
278         }
279     }
280     
281     public AAFLurPerm newLur(AbsUserCache<AAFPermission> c) throws APIException {
282         try {
283             return new AAFLurPerm(this,c);
284         } catch (APIException e) {
285             throw e;
286         } catch (Exception e) {
287             throw new APIException(e);
288         }
289     }
290
291     protected abstract Rcli<CLIENT> rclient(URI uri, SecuritySetter<CLIENT> ss) throws CadiException;
292     
293     public abstract Rcli<CLIENT> rclient(Locator<URI> loc, SecuritySetter<CLIENT> ss) throws CadiException;
294
295     public Rcli<CLIENT> client(Locator<URI> locator) throws CadiException {
296         return rclient(locator,si.defSS);
297     }
298     
299     public abstract<RET> RET best(Retryable<RET> retryable) throws LocatorException, CadiException, APIException;
300
301     public abstract<RET> RET bestForUser(GetSetter get, Retryable<RET> retryable) throws LocatorException, CadiException, APIException;
302
303     public abstract SecuritySetter<CLIENT> basicAuth(String user, String password) throws CadiException;
304     
305     public abstract SecuritySetter<CLIENT> transferSS(TaggedPrincipal principal) throws CadiException;
306     
307     public abstract SecuritySetter<CLIENT> basicAuthSS(BasicPrincipal principal) throws CadiException;
308     
309     public abstract SecuritySetter<CLIENT> tokenSS(final String client_id, final String accessToken) throws CadiException;
310     
311     public abstract SecuritySetter<CLIENT> x509Alias(String alias) throws APIException, CadiException;
312     
313
314     public String getRealm() {
315         return realm;
316
317     }
318     
319     /**
320      * This interface allows the AAFCon, even though generic, to pass in correctly typed values based on the above SS commands.
321      * @author Jonathan
322      *
323      */
324     public interface GetSetter {
325         public<CLIENT> SecuritySetter<CLIENT> get(AAFCon<CLIENT> con) throws CadiException;
326     }
327
328     public SecuritySetter<CLIENT> set(final SecuritySetter<CLIENT> ss) {
329         si.set(ss);
330         for (Rcli<CLIENT> client : clients.values()) {
331             client.setSecuritySetter(ss);
332         }
333         return ss;
334     }
335     
336     public SecurityInfoC<CLIENT> securityInfo() {
337         return si;
338     }
339
340     public String defID() {
341         if (si!=null) {
342             return si.defSS.getID();
343         }
344         return "unknown";
345     }
346     
347     public void invalidate() throws CadiException {
348         for (Rcli<CLIENT> client : clients.values()) {
349             client.invalidate();
350         }
351         clients.clear();
352     }
353
354     public String readableErrMsg(Future<?> f) {
355         String text = f.body();
356         if (text==null || text.length()==0) {
357             text = f.code() + ": **No Message**";
358         } else if (text.contains("%")) {
359             try {
360                 Error err = errDF.newData().in(TYPE.JSON).load(f.body()).asObject();
361                 return Vars.convert(err.getText(),err.getVariables());
362             } catch (APIException e){
363                 access.log(e);
364             }
365         }
366         return text;
367     }
368     
369     public static AAFCon<?> newInstance(PropAccess pa) throws CadiException, LocatorException {
370         // Potentially add plugin for other kinds of Access
371         return new AAFConHttp(pa);
372     }
373 }