390c3089417fab12a2b0c0ed4ce8b7e4da935908
[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.FORBIDDEN_403);
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                                                                         
116                                                                         resp.setStatus(HttpStatus.OK_200);
117                                                                 } else {
118                                                                         // DME2 at this version crashes without some sort of response
119                                                                         resp.getOutputStream().print("");
120                                                                         resp.setStatus(HttpStatus.FORBIDDEN_403);
121                                                                 }
122                                                         } finally {
123                                                                 tt.done();
124                                                         }
125                                                 }
126                                         }
127                                 } else if(p == null) {
128                                         trans.error().log("Transaction not Authenticated... no Principal");
129                                         resp.setStatus(HttpStatus.FORBIDDEN_403);
130                                 } else {
131                                         trans.checkpoint("Basic Auth Check Failed: This wasn't a Basic Auth Trans");
132                                         // For Auth Security questions, we don't give any info to client on why failed
133                                         resp.setStatus(HttpStatus.FORBIDDEN_403);
134                                 }
135                         }
136                 },"text/plain","*/*","*");
137                 
138                 /** 
139                  *  returns whether a given Credential is valid
140                  */
141                 authzAPI.route(POST, "/authn/validate", API.CRED_REQ, new Code(facade,"Is given Credential valid?",true) {
142                         @Override
143                         public void handle(
144                                         AuthzTrans trans, 
145                                         HttpServletRequest req,
146                                         HttpServletResponse resp) throws Exception {
147                                 
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                                         resp.setStatus(HttpStatus.FORBIDDEN_403);
155                                 }
156                         }
157                 });  
158
159                 /** 
160                  *  returns whether a given Credential is valid
161                  */
162                 authzAPI.route(GET, "/authn/cert/id/:id", API.CERTS, new Code(facade,"Get Cert Info by ID",true) {
163                         @Override
164                         public void handle(
165                                         AuthzTrans trans, 
166                                         HttpServletRequest req,
167                                         HttpServletResponse resp) throws Exception {
168                                 
169                                 Result<Void> r = context.getCertInfoByID(trans, req, resp, pathParam(req,":id") );
170                                 if(r.isOK()) {
171                                                 resp.setStatus(HttpStatus.OK_200); 
172                                 } else {
173                                                 // For Security, we don't give any info out on why failed, other than forbidden
174                                                 resp.setStatus(HttpStatus.FORBIDDEN_403);
175                                 }
176                         }
177                 });  
178
179
180
181
182         }
183         
184         /**
185          * Normal Init level APIs
186          * 
187          * @param authzAPI
188          * @param facade
189          * @throws Exception
190          */
191         public static void init(AAF_Service authzAPI, AuthzFacade facade) throws Exception {
192                 /**
193                  * Create a new ID/Credential
194                  */
195                 authzAPI.route(POST,"/authn/cred",API.CRED_REQ,new Code(facade,"Add a New ID/Credential", true) {
196                         @Override
197                         public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {                               Result<Void> r = context.createUserCred(trans, req);
198                                 if(r.isOK()) {
199                                         resp.setStatus(HttpStatus.CREATED_201);
200                                 } else {
201                                         context.error(trans,resp,r);
202                                 }
203                         }
204                 });
205                 
206                 /** 
207                  *  gets all credentials by Namespace
208                  */
209                 authzAPI.route(GET, "/authn/creds/ns/:ns", API.USERS, new Code(facade,"Get Creds for a Namespace",true) {
210                         @Override
211                         public void handle(
212                                         AuthzTrans trans, 
213                                         HttpServletRequest req,
214                                         HttpServletResponse resp) throws Exception {
215                                 
216                                 Result<Void> r = context.getCredsByNS(trans, resp, pathParam(req, "ns"));
217                                 if(r.isOK()) {
218                                         resp.setStatus(HttpStatus.OK_200); 
219                                 } else {
220                                         context.error(trans,resp,r);
221                                 }
222                         }
223
224                 });
225                 
226                 /** 
227                  *  gets all credentials by ID
228                  */
229                 authzAPI.route(GET, "/authn/creds/id/:id", API.USERS, new Code(facade,"Get Creds by ID",true) {
230                         @Override
231                         public void handle(
232                                         AuthzTrans trans, 
233                                         HttpServletRequest req,
234                                         HttpServletResponse resp) throws Exception {
235                                 
236                                 Result<Void> r = context.getCredsByID(trans, resp, pathParam(req, "id"));
237                                 if(r.isOK()) {
238                                         resp.setStatus(HttpStatus.OK_200); 
239                                 } else {
240                                         context.error(trans,resp,r);
241                                 }
242                         }
243
244                 });
245
246
247                 /**
248                  * Update ID/Credential (aka reset)
249                  */
250                 authzAPI.route(PUT,"/authn/cred",API.CRED_REQ,new Code(facade,"Update an ID/Credential", true) {
251                         @Override
252                         public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
253                                 
254                                 Result<Void> r = context.changeUserCred(trans, req);
255                                 if(r.isOK()) {
256                                         resp.setStatus(HttpStatus.OK_200);
257                                 } else {
258                                         context.error(trans,resp,r);
259                                 }
260                         }
261                 });
262
263                 /**
264                  * Extend ID/Credential
265                  * This behavior will accelerate getting out of P1 outages due to ignoring renewal requests, or
266                  * other expiration issues.
267                  * 
268                  * Scenario is that people who are solving Password problems at night, are not necessarily those who
269                  * know what the passwords are supposed to be.  Also, changing Password, without changing Configurations
270                  * using that password only exacerbates the P1 Issue.
271                  */
272                 authzAPI.route(PUT,"/authn/cred/:days",API.CRED_REQ,new Code(facade,"Extend an ID/Credential", true) {
273                         @Override
274                         public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
275                                 Result<Void> r = context.extendUserCred(trans, req, pathParam(req, "days"));
276                                 if(r.isOK()) {
277                                         resp.setStatus(HttpStatus.OK_200);
278                                 } else {
279                                         context.error(trans,resp,r);
280                                 }
281                         }
282                 });
283
284                 /**
285                  * Delete a ID/Credential by Object
286                  */
287                 authzAPI.route(DELETE,"/authn/cred",API.CRED_REQ,new Code(facade,"Delete a Credential", true) {
288                         @Override
289                         public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
290                                 Result<Void> r = context.deleteUserCred(trans, req);
291                                 if(r.isOK()) {
292                                         resp.setStatus(HttpStatus.OK_200);
293                                 } else {
294                                         context.error(trans,resp,r);
295                                 }
296                         }
297                 });
298
299         }
300 }