2bb497a0c96cf5b433de152c867f82bb6b6a9bc5
[aaf/authz.git] / auth / auth-locate / src / main / java / org / onap / aaf / auth / locate / api / API_AAFAccess.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.auth.locate.api;
23
24 import static org.onap.aaf.auth.layer.Result.OK;
25
26 import java.io.IOException;
27 import java.net.ConnectException;
28 import java.net.URI;
29 import java.security.Principal;
30
31 import javax.servlet.ServletOutputStream;
32 import javax.servlet.http.HttpServletRequest;
33 import javax.servlet.http.HttpServletResponse;
34
35 import org.eclipse.jetty.http.HttpStatus;
36 import org.onap.aaf.auth.cache.Cache.Dated;
37 import org.onap.aaf.auth.env.AuthzTrans;
38 import org.onap.aaf.auth.layer.Result;
39 import org.onap.aaf.auth.locate.AAF_Locate;
40 import org.onap.aaf.auth.locate.BasicAuthCode;
41 import org.onap.aaf.auth.locate.LocateCode;
42 import org.onap.aaf.auth.locate.facade.LocateFacade;
43 import org.onap.aaf.auth.locate.mapper.Mapper.API;
44 import org.onap.aaf.auth.rserv.HttpMethods;
45 import org.onap.aaf.cadi.CadiException;
46 import org.onap.aaf.cadi.Locator;
47 import org.onap.aaf.cadi.Locator.Item;
48 import org.onap.aaf.cadi.LocatorException;
49 import org.onap.aaf.cadi.aaf.AAFPermission;
50 import org.onap.aaf.cadi.client.Future;
51 import org.onap.aaf.cadi.client.Rcli;
52 import org.onap.aaf.cadi.client.Retryable;
53 import org.onap.aaf.misc.env.APIException;
54 import org.onap.aaf.misc.env.Env;
55 import org.onap.aaf.misc.env.TimeTaken;
56 import org.owasp.encoder.Encode;
57
58 public class API_AAFAccess {
59 //    private static String service, version, envContext;
60
61     private static final String GET_PERMS_BY_USER = "Get Perms by User";
62     private static final String USER_HAS_PERM ="User Has Perm";
63 //    private static final String USER_IN_ROLE ="User Has Role";
64
65     /**
66      * Normal Init level APIs
67      *
68      * @param gwAPI
69      * @param facade
70      * @throws Exception
71      */
72     public static void init(final AAF_Locate gwAPI, LocateFacade facade) throws Exception {
73
74
75         gwAPI.route(HttpMethods.GET,"/authz/perms/user/:user",API.VOID,new LocateCode(facade,GET_PERMS_BY_USER, true) {
76             @Override
77             public void handle(final AuthzTrans trans, final HttpServletRequest req, final HttpServletResponse resp) throws Exception {
78                 TimeTaken tt = trans.start(GET_PERMS_BY_USER, Env.SUB);
79                 try {
80                     final String accept = req.getHeader("ACCEPT");
81                     final String user = pathParam(req,":user");
82                     if (!user.contains("@")) {
83                         context.error(trans,resp,Result.ERR_BadData,"User [%s] must be fully qualified with domain",user);
84                         return;
85                     }
86                     final String key = trans.user() + user + (accept!=null&&accept.contains("xml")?"-xml":"-json");
87                     TimeTaken tt2 = trans.start("Cache Lookup",Env.SUB);
88                     Dated d;
89                     try {
90                         d = gwAPI.cacheUser.get(key);
91                     } finally {
92                         tt2.done();
93                     }
94
95                     if (d==null || d.data.isEmpty()) {
96                         tt2 = trans.start("AAF Service Call",Env.REMOTE);
97                         try {
98                             gwAPI.clientAsUser(trans.getUserPrincipal(), new Retryable<Void>() {
99                                 @Override
100                                 public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
101                                     Future<String> fp = client.read("/authz/perms/user/"+user,accept);
102                                     if (fp.get(5000)) {
103                                         gwAPI.cacheUser.put(key, new Dated(new User(fp.code(),fp.body()),gwAPI.expireIn));
104                                         resp.setStatus(HttpStatus.OK_200);
105                                         ServletOutputStream sos;
106                                         try {
107                                             sos = resp.getOutputStream();
108                                             sos.print(Encode.forJava(fp.value));
109                                         } catch (IOException e) {
110                                             throw new CadiException(e);
111                                         }
112                                     } else {
113                                         gwAPI.cacheUser.put(key, new Dated(new User(fp.code(),fp.body()),gwAPI.expireIn));
114                                         context.error(trans,resp,fp.code(),fp.body());
115                                     }
116                                     return null;
117                                 }
118                             });
119                         } finally {
120                             tt2.done();
121                         }
122                     } else {
123                         User u = (User)d.data.get(0);
124                         resp.setStatus(u.code);
125                         ServletOutputStream sos = resp.getOutputStream();
126                         sos.print(Encode.forJava(u.resp));
127                     }
128                 } finally {
129                     tt.done();
130                 }
131             }
132         });
133
134
135         gwAPI.route(gwAPI.env,HttpMethods.GET,"/authn/basicAuth",new BasicAuthCode(gwAPI.aafAuthn,facade)
136                 ,"text/plain","*/*","*");
137
138         /**
139          * Query User Has Perm is DEPRECATED
140          *
141          * Need to move towards NS declaration... is this even being used?
142          * @deprecated
143          */
144         gwAPI.route(HttpMethods.GET,"/ask/:user/has/:type/:instance/:action",API.VOID,new LocateCode(facade,USER_HAS_PERM, true) {
145             @Override
146             public void handle(final AuthzTrans trans, final HttpServletRequest req, HttpServletResponse resp) throws Exception {
147                 try {
148                     String type = pathParam(req,":type");
149                     int idx = type.lastIndexOf('.');
150                     String ns = type.substring(0,idx);
151                     type = type.substring(idx+1);
152                     resp.getOutputStream().print(
153                             gwAPI.aafLurPerm.fish(new Principal() {
154                                 public String getName() {
155                                     return pathParam(req,":user");
156                                 };
157                             }, new AAFPermission(
158                                 ns,
159                                 type,
160                                 pathParam(req,":instance"),
161                                 pathParam(req,":action"))));
162                     resp.setStatus(HttpStatus.OK_200);
163                 } catch (Exception e) {
164                     context.error(trans, resp, Result.ERR_General, e.getMessage());
165                 }
166             }
167         });
168
169         gwAPI.route(HttpMethods.GET,"/gui/:path*",API.VOID,new LocateCode(facade,"Short Access PROD GUI for AAF", true) {
170             @Override
171             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
172                 try {
173                     redirect(trans, req, resp, context,
174                             gwAPI.getGUILocator(),
175                             "gui/"+pathParam(req,":path"));
176                 } catch (LocatorException e) {
177                     context.error(trans, resp, Result.ERR_BadData, e.getMessage());
178                 } catch (Exception e) {
179                     context.error(trans, resp, Result.ERR_General, e.getMessage());
180                 }
181             }
182         });
183
184         gwAPI.route(HttpMethods.GET,"/aaf/:version/:path*",API.VOID,new LocateCode(facade,"Access PROD GUI for AAF", true) {
185             @Override
186             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
187                 try {
188                     redirect(trans, req, resp, context,
189                             gwAPI.getGUILocator(),
190                             pathParam(req,":path"));
191                 } catch (LocatorException e) {
192                     context.error(trans, resp, Result.ERR_BadData, e.getMessage());
193                 } catch (Exception e) {
194                     context.error(trans, resp, Result.ERR_General, e.getMessage());
195                 }
196             }
197         });
198     }
199
200     public static void initDefault(final AAF_Locate gwAPI, LocateFacade facade) throws Exception {
201
202         /**
203          * "login" url
204          */
205         gwAPI.route(HttpMethods.GET,"/login",API.VOID,new LocateCode(facade,"Access Login GUI for AAF", true) {
206             @Override
207             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
208                 try {
209                     redirect(trans, req, resp, context,
210                             gwAPI.getGUILocator(),
211                             "login");
212                 } catch (LocatorException e) {
213                     context.error(trans, resp, Result.ERR_BadData, e.getMessage());
214                 } catch (Exception e) {
215                     context.error(trans, resp, Result.ERR_General, e.getMessage());
216                 }
217             }
218         });
219
220
221         /**
222          * Default URL
223          */
224         gwAPI.route(HttpMethods.GET,"/",API.VOID,new LocateCode(facade,"Access GUI for AAF", true) {
225             @Override
226             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
227                 try {
228                     redirect(trans, req, resp, context,
229                             gwAPI.getGUILocator(),
230                             "gui/home");
231                 } catch (Exception e) {
232                     context.error(trans, resp, Result.ERR_General, e.getMessage());
233                 }
234             }
235         });
236
237         /**
238          * Configuration
239          */
240         gwAPI.route(HttpMethods.GET,"/configure/:id/:type",API.CONFIG,new LocateCode(facade,"Deliver Configuration Properties to AAF", true) {
241             @Override
242             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
243                 try {
244                     Result<Void> r = facade.getConfig(trans, req, resp, pathParam(req, ":id"),pathParam(req,":type"));
245                     switch(r.status) {
246                         case OK:
247                             resp.setStatus(HttpStatus.OK_200);
248                             break;
249                         default:
250                             context.error(trans,resp,r);
251                     }
252
253                 } catch (Exception e) {
254                     context.error(trans, resp, Result.ERR_General, e.getMessage());
255                 }
256             }
257         });
258     }
259
260     private static void redirect(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, LocateFacade context, Locator<URI> loc, String path) throws IOException {
261         try {
262             if (loc.hasItems()) {
263                 Item item = loc.best();
264                 URI uri = loc.get(item);
265                 StringBuilder redirectURL = new StringBuilder(uri.toString());
266                 redirectURL.append('/');
267                 redirectURL.append(path);
268                 String str = req.getQueryString();
269                 if (str!=null) {
270                     redirectURL.append('?');
271                     redirectURL.append(str);
272                 }
273                 trans.info().log("Redirect to",redirectURL);              
274                 resp.sendRedirect(redirectURL.toString());
275             } else {
276                 context.error(trans, resp, Result.err(Result.ERR_NotFound,"No Locations found for redirection"));
277             }
278         } catch (LocatorException e) {
279             context.error(trans, resp, Result.err(Result.ERR_NotFound,"No Endpoints found for %s",req.getPathInfo()));
280         }
281     }
282
283     private static class User {
284         public final int code;
285         public final String resp;
286
287         public User(int code, String resp) {
288             this.code = code;
289             this.resp = resp;
290         }
291     }
292 }