Collection syntax change because of Sonar
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / oauth / TokenMgr.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.oauth;
23
24 import java.io.IOException;
25 import java.nio.file.Path;
26 import java.security.GeneralSecurityException;
27 import java.security.Principal;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.concurrent.ConcurrentHashMap;
31
32 import org.onap.aaf.cadi.CadiException;
33 import org.onap.aaf.cadi.LocatorException;
34 import org.onap.aaf.cadi.PropAccess;
35 import org.onap.aaf.cadi.Access.Level;
36 import org.onap.aaf.cadi.client.Result;
37 import org.onap.aaf.cadi.config.Config;
38 import org.onap.aaf.cadi.persist.Persist;
39 import org.onap.aaf.misc.env.APIException;
40 import org.onap.aaf.misc.rosetta.env.RosettaDF;
41 import org.onap.aaf.misc.rosetta.env.RosettaEnv;
42
43 import aaf.v2_0.Perms;
44 import aafoauth.v2_0.Introspect;
45
46 public class TokenMgr extends Persist<Introspect, TokenPerm> {
47         protected static Map<String,TokenPerm> tpmap = new ConcurrentHashMap<>();
48         protected static Map<String,TokenMgr> tmmap = new HashMap<>(); // synchronized in getInstance
49         protected static Map<String,String> currentToken = new HashMap<>(); // synchronized in getTP
50         public static RosettaDF<Perms> permsDF;
51         public static RosettaDF<Introspect> introspectDF;
52
53         private final TokenPermLoader tpLoader;
54         
55         private TokenMgr(PropAccess access, String tokenURL, String introspectURL) throws APIException, CadiException {
56                 super(access,new RosettaEnv(access.getProperties()),Introspect.class,"introspect");
57                 synchronized(access) {
58                         if(permsDF==null) {
59                                 permsDF = env.newDataFactory(Perms.class);
60                                 introspectDF = env.newDataFactory(Introspect.class);
61                         }
62                 }
63                 if("dbToken".equals(tokenURL) && "dbIntrospect".equals(introspectURL)) {
64                         tpLoader = new TokenPermLoader() { // null Loader
65                                 @Override
66                                 public Result<TokenPerm> load(String accessToken, byte[] cred)
67                                                 throws APIException, CadiException, LocatorException {
68                                         return Result.err(404, "DBLoader");
69                                 }
70                         };
71                 } else {
72                         RemoteTokenPermLoader rtpl = new RemoteTokenPermLoader(tokenURL, introspectURL); // default is remote
73                         String i = access.getProperty(Config.AAF_APPID,null);
74                         String p = access.getProperty(Config.AAF_APPPASS, null);
75                         if(i==null || p==null) {
76                                 throw new CadiException(Config.AAF_APPID + " and " + Config.AAF_APPPASS + " must be set to initialize TokenMgr");
77                         }
78                         rtpl.introCL.client_creds(i,p);
79                         tpLoader = rtpl;
80                 }
81         }
82
83         private TokenMgr(PropAccess access, TokenPermLoader tpl) throws APIException, CadiException {
84                 super(access,new RosettaEnv(access.getProperties()),Introspect.class,"incoming");
85                 synchronized(access) {
86                         if(permsDF==null) {
87                                 permsDF = env.newDataFactory(Perms.class);
88                                 introspectDF = env.newDataFactory(Introspect.class);
89                         }
90                 }
91                 tpLoader = tpl;
92         }
93
94         public static synchronized TokenMgr getInstance(final PropAccess access, final String tokenURL, final String introspectURL) throws APIException, CadiException {
95                 String key;
96                 TokenMgr tm = tmmap.get(key=tokenURL+'/'+introspectURL);
97                 if(tm==null) {
98                         tmmap.put(key, tm=new TokenMgr(access,tokenURL,introspectURL));
99                 }
100                 return tm;
101         }
102         
103         public Result<OAuth2Principal> toPrincipal(final String accessToken, final byte[] hash) throws APIException, CadiException, LocatorException {
104                 Result<TokenPerm> tp = get(accessToken, hash, new Loader<TokenPerm>() {
105                         @Override
106                         public Result<TokenPerm> load(String key) throws APIException, CadiException, LocatorException {
107                                 try {
108                                         return tpLoader.load(accessToken,hash);
109                                 } catch (APIException | LocatorException e) {
110                                         throw new CadiException(e);
111                                 }
112                         }
113                 });
114                 if(tp.isOK()) {
115                         return Result.ok(200, new OAuth2Principal(tp.value,hash));
116                 } else {
117                         return Result.err(tp);
118                 }
119         }
120         
121         public Result<TokenPerm> get(final String accessToken, final byte[] hash) throws APIException, CadiException, LocatorException {
122                 return get(accessToken,hash,new Loader<TokenPerm>() {
123                         @Override
124                         public Result<TokenPerm> load(String key) throws APIException, CadiException, LocatorException {
125                                 return tpLoader.load(key,hash);
126                         }
127                         
128                 });
129 //              return tpLoader.load(accessToken,hash);
130         }
131
132         public interface TokenPermLoader{
133                 public Result<TokenPerm> load(final String accessToken, final byte[] cred) throws APIException, CadiException, LocatorException;
134         }
135         
136         private class RemoteTokenPermLoader implements TokenPermLoader {
137                 private TokenClientFactory tcf;
138                 private TokenClient tokenCL, introCL;
139
140                 public RemoteTokenPermLoader(final String tokenURL, final String introspectURL) throws APIException, CadiException {
141                         try {
142                                 tcf = TokenClientFactory.instance(access);
143                                 int timeout = Integer.parseInt(access.getProperty(Config.AAF_CONN_TIMEOUT, Config.AAF_CONN_TIMEOUT_DEF));
144                                 tokenCL = tcf.newClient(tokenURL, 
145                                                                                 timeout);
146                                 if(introspectURL.equals(tokenURL)) {
147                                         introCL = tokenCL;
148                                 } else {
149                                         introCL = tcf.newClient(introspectURL, 
150                                                         timeout);
151                                 }
152
153                         } catch (GeneralSecurityException | IOException | NumberFormatException | LocatorException e) {
154                                 throw new CadiException(e);
155                         }
156                 }
157                  
158                 public Result<TokenPerm> load(final String accessToken, final byte[] cred) throws APIException, CadiException, LocatorException {
159                         long start = System.currentTimeMillis();
160                         try {
161                                 Result<Introspect> ri = introCL.introspect(accessToken);
162                                 if(ri.isOK()) {
163                                         return Result.ok(ri.code, new TokenPerm(TokenMgr.this,permsDF,ri.value,cred,getPath(accessToken)));
164                                 } else {
165                                         return Result.err(ri);
166                                 }
167                         } finally {
168                                 access.printf(Level.INFO, "Token loaded in %d ms",System.currentTimeMillis()-start);
169                         }
170                 }
171         }
172
173         public void clear(Principal p, StringBuilder report) {
174                 TokenPerm tp = tpmap.remove(p.getName());
175                 if(tp==null) {
176                         report.append("Nothing to clear");
177                 } else {
178                         report.append("Cleared ");
179                         report.append(p.getName());
180                 }
181         }
182
183         @Override
184         protected TokenPerm newCacheable(Introspect i, long expires, byte[] hash, Path path) throws APIException {
185                 // Note: Introspect drives the Expiration... ignoring expires.
186                 return new TokenPerm(this,permsDF,i,hash,path);
187         }
188
189         public TokenPerm putIntrospect(Introspect intro, byte[] cred) throws APIException {
190                 return newCacheable(intro, intro.getExp(), cred, getPath(intro.getAccessToken()));
191         }
192
193 }