Improved multi Proxy DNSLocator based
[aaf/authz.git] / auth / auth-service / src / main / java / org / onap / aaf / auth / service / api / API_Creds.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.service.api;
23
24 import static org.onap.aaf.auth.rserv.HttpMethods.DELETE;
25 import static org.onap.aaf.auth.rserv.HttpMethods.GET;
26 import static org.onap.aaf.auth.rserv.HttpMethods.POST;
27 import static org.onap.aaf.auth.rserv.HttpMethods.PUT;
28
29 import java.security.Principal;
30 import java.util.Date;
31
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.direct.DirectAAFUserPass;
37 import org.onap.aaf.auth.env.AuthzTrans;
38 import org.onap.aaf.auth.layer.Result;
39 import org.onap.aaf.auth.rserv.HttpMethods;
40 import org.onap.aaf.auth.service.AAF_Service;
41 import org.onap.aaf.auth.service.Code;
42 import org.onap.aaf.auth.service.facade.AuthzFacade;
43 import org.onap.aaf.auth.service.mapper.Mapper.API;
44 import org.onap.aaf.cadi.CredVal;
45 import org.onap.aaf.cadi.CredVal.Type;
46 import org.onap.aaf.cadi.Symm;
47 import org.onap.aaf.cadi.principal.BasicPrincipal;
48 import org.onap.aaf.cadi.principal.X509Principal;
49 import org.onap.aaf.cadi.taf.basic.BasicHttpTaf;
50 import org.onap.aaf.misc.env.Env;
51 import org.onap.aaf.misc.env.TimeTaken;
52
53 /**
54  * Initialize All Dispatches related to Credentials (AUTHN)
55  * @author Jonathan
56  *
57  */
58 public class API_Creds {
59     // Hide Public Interface
60     private API_Creds() {}
61     // needed to validate Creds even when already Authenticated x509
62     /**
63      * TIME SENSITIVE APIs
64      * 
65      * These will be first in the list
66      * 
67      * @param env
68      * @param authzAPI
69      * @param facade
70      * @param directAAFUserPass 
71      * @throws Exception
72      */
73     public static void timeSensitiveInit(Env env, AAF_Service authzAPI, AuthzFacade facade, final DirectAAFUserPass directAAFUserPass) throws Exception {
74         /**
75          * Basic Auth, quick Validation
76          * 
77          * Responds OK or NotAuthorized
78          */
79         authzAPI.route(env, HttpMethods.GET, "/authn/basicAuth", new Code(facade,"Is given BasicAuth valid?",true) {
80             @Override
81             public void handle(
82                     AuthzTrans trans, 
83                     HttpServletRequest req,
84                     HttpServletResponse resp) throws Exception {
85
86                 Principal p = trans.getUserPrincipal();
87                 if (p instanceof BasicPrincipal) {
88                     // the idea is that if call is made with this credential, and it's a BasicPrincipal, it's ok
89                     // otherwise, it wouldn't have gotten here.
90                     resp.setStatus(HttpStatus.OK_200);
91                 } else if (p instanceof X509Principal) {
92                     // have to check Basic Auth here, because it might be CSP.
93                     String authz = req.getHeader("Authorization");
94                     if (authz.startsWith("Basic ")) {
95                         BasicHttpTaf bht = ((X509Principal)p).getBasicHttpTaf(); 
96                         if (bht!=null) {
97                             BasicPrincipal bp = new BasicPrincipal(authz,"");
98                             CredVal cv = bht.getCredVal(bp.getDomain());
99                             if (cv!=null) {
100                                 if (cv.validate(bp.getName(), Type.PASSWORD, bp.getCred(), null) ) {
101                                     resp.setStatus(HttpStatus.OK_200);
102                                 } else {
103                                     resp.setStatus(HttpStatus.UNAUTHORIZED_401);
104                                 }
105                             }
106                         } else {
107                             String decoded = Symm.base64noSplit.decode(authz.substring(6));
108                             int colon = decoded.indexOf(':');
109                             TimeTaken tt = trans.start("Direct Validation", Env.REMOTE);
110                             try {
111                                 if (directAAFUserPass.validate(
112                                         decoded.substring(0,colon), 
113                                         CredVal.Type.PASSWORD , 
114                                         decoded.substring(colon+1).getBytes(),trans)) {
115                                     resp.setStatus(HttpStatus.OK_200);
116                                 } else {
117                                     // DME2 at this version crashes without some sort of response
118                                     resp.getOutputStream().print("");
119                                     resp.setStatus(HttpStatus.FORBIDDEN_403);
120                                 }
121                             } finally {
122                                 tt.done();
123                             }
124                         }
125                     }
126                 } else if (p == null) {
127                     trans.error().log("Transaction not Authenticated... no Principal");
128                     resp.setStatus(HttpStatus.FORBIDDEN_403);
129                 } else {
130                     trans.checkpoint("Basic Auth Check Failed: This wasn't a Basic Auth Trans");
131                     // For Auth Security questions, we don't give any info to client on why failed
132                     resp.setStatus(HttpStatus.FORBIDDEN_403);
133                 }
134             }
135         },"text/plain","*/*","*");
136         
137         /** 
138          *  returns whether a given Credential is valid
139          */
140         authzAPI.route(POST, "/authn/validate", API.CRED_REQ, new Code(facade,"Is given Credential valid?",true) {
141             @Override
142             public void handle(
143                     AuthzTrans trans, 
144                     HttpServletRequest req,
145                     HttpServletResponse resp) throws Exception {
146                 // will be a valid Entity.  Do we need to add permission
147                 //if(trans.fish("ns","password","request")) or the like
148                 Result<Date> r = context.doesCredentialMatch(trans, req, resp);
149                 if (r.isOK()) {
150                     resp.setStatus(HttpStatus.OK_200);
151                 } else {
152                     // For Security, we don't give any info out on why failed, other than forbidden
153                     // Can't do "401", because that is on the call itself
154                         // 403 Implies you MAY NOT Ask.
155                     resp.setStatus(HttpStatus.NOT_ACCEPTABLE_406);
156                 }
157             }
158         });  
159
160         /** 
161          *  returns whether a given Credential is valid
162          */
163         authzAPI.route(GET, "/authn/cert/id/:id", API.CERTS, new Code(facade,"Get Cert Info by ID",true) {
164             @Override
165             public void handle(
166                     AuthzTrans trans, 
167                     HttpServletRequest req,
168                     HttpServletResponse resp) throws Exception {
169                 
170                 Result<Void> r = context.getCertInfoByID(trans, req, resp, pathParam(req,":id") );
171                 if (r.isOK()) {
172                         resp.setStatus(HttpStatus.OK_200); 
173                 } else {
174                         // For Security, we don't give any info out on why failed, other than forbidden
175                         resp.setStatus(HttpStatus.FORBIDDEN_403);
176                 }
177             }
178         });  
179
180
181
182
183     }
184     
185     /**
186      * Normal Init level APIs
187      * 
188      * @param authzAPI
189      * @param facade
190      * @throws Exception
191      */
192     public static void init(AAF_Service authzAPI, AuthzFacade facade) throws Exception {
193         /**
194          * Create a new ID/Credential
195          */
196         authzAPI.route(POST,"/authn/cred",API.CRED_REQ,new Code(facade,"Add a New ID/Credential", true) {
197             @Override
198             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {                
199                 Result<Void> r = context.createUserCred(trans, req);
200                 if (r.isOK()) {
201                     resp.setStatus(HttpStatus.CREATED_201);
202                 } else {
203                     context.error(trans,resp,r);
204                 }
205             }
206         });
207         
208         /** 
209          *  gets all credentials by Namespace
210          */
211         authzAPI.route(GET, "/authn/creds/ns/:ns", API.USERS, new Code(facade,"Get Creds for a Namespace",true) {
212             @Override
213             public void handle(
214                     AuthzTrans trans, 
215                     HttpServletRequest req,
216                     HttpServletResponse resp) throws Exception {
217                 
218                 Result<Void> r = context.getCredsByNS(trans, resp, pathParam(req, "ns"));
219                 if (r.isOK()) {
220                     resp.setStatus(HttpStatus.OK_200); 
221                 } else {
222                     context.error(trans,resp,r);
223                 }
224             }
225
226         });
227         
228         /** 
229          *  gets all credentials by ID
230          */
231         authzAPI.route(GET, "/authn/creds/id/:id", API.USERS, new Code(facade,"Get Creds by ID",true) {
232             @Override
233             public void handle(
234                     AuthzTrans trans, 
235                     HttpServletRequest req,
236                     HttpServletResponse resp) throws Exception {
237                 
238                 Result<Void> r = context.getCredsByID(trans, resp, pathParam(req, "id"));
239                 if (r.isOK()) {
240                     resp.setStatus(HttpStatus.OK_200); 
241                 } else {
242                     context.error(trans,resp,r);
243                 }
244             }
245
246         });
247
248
249         /**
250          * Update ID/Credential (aka reset)
251          */
252         authzAPI.route(PUT,"/authn/cred",API.CRED_REQ,new Code(facade,"Update an ID/Credential", true) {
253             @Override
254             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
255                 
256                 Result<Void> r = context.changeUserCred(trans, req);
257                 if (r.isOK()) {
258                     resp.setStatus(HttpStatus.OK_200);
259                 } else {
260                     context.error(trans,resp,r);
261                 }
262             }
263         });
264
265         /**
266          * Extend ID/Credential
267          * This behavior will accelerate getting out of P1 outages due to ignoring renewal requests, or
268          * other expiration issues.
269          * 
270          * Scenario is that people who are solving Password problems at night, are not necessarily those who
271          * know what the passwords are supposed to be.  Also, changing Password, without changing Configurations
272          * using that password only exacerbates the P1 Issue.
273          */
274         authzAPI.route(PUT,"/authn/cred/:days",API.CRED_REQ,new Code(facade,"Extend an ID/Credential", true) {
275             @Override
276             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
277                 Result<Void> r = context.extendUserCred(trans, req, pathParam(req, "days"));
278                 if (r.isOK()) {
279                     resp.setStatus(HttpStatus.OK_200);
280                 } else {
281                     context.error(trans,resp,r);
282                 }
283             }
284         });
285
286         /**
287          * Delete a ID/Credential by Object
288          */
289         authzAPI.route(DELETE,"/authn/cred",API.CRED_REQ,new Code(facade,"Delete a Credential", true) {
290             @Override
291             public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
292                 Result<Void> r = context.deleteUserCred(trans, req);
293                 if (r.isOK()) {
294                     resp.setStatus(HttpStatus.OK_200);
295                 } else {
296                     context.error(trans,resp,r);
297                 }
298             }
299         });
300
301     }
302 }