Add Certs, Docker Build
[aaf/authz.git] / cadi / cass / src / main / java / com / att / aaf / cadi / cass / AAFAuthenticator.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 com.att.aaf.cadi.cass;
23
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.Map;
29
30 import org.apache.cassandra.auth.AuthenticatedUser;
31 import org.apache.cassandra.auth.IAuthenticator;
32 import org.apache.cassandra.auth.ISaslAwareAuthenticator;
33 import org.apache.cassandra.exceptions.AuthenticationException;
34 import org.apache.cassandra.exceptions.InvalidRequestException;
35 import org.apache.cassandra.exceptions.RequestExecutionException;
36 import org.onap.aaf.cadi.Symm;
37 import org.onap.aaf.cadi.Access.Level;
38 import org.onap.aaf.cadi.CredVal.Type;
39 import org.onap.aaf.cadi.config.Config;
40
41 public class AAFAuthenticator extends AAFBase implements ISaslAwareAuthenticator  {
42
43         public boolean requireAuthentication() {
44                  return true;
45          }
46           
47           /**
48            * Invoked to authenticate an user
49            */
50           public AuthenticatedUser authenticate(Map<String, String> credentials) throws AuthenticationException {
51                     String username = (String)credentials.get("username");
52                     if (username == null) {
53                       throw new AuthenticationException("'username' is missing");
54                     }
55                     
56                     AAFAuthenticatedUser aau = new AAFAuthenticatedUser(access,username);
57                     String fullName=aau.getFullName();
58                     access.log(Level.DEBUG, "Authenticating", aau.getName(),"(", fullName,")");
59                     
60                     String password = (String)credentials.get("password");
61                     if (password == null) {
62                       throw new AuthenticationException("'password' is missing");
63                     } else if(password.startsWith("bsf:")) {
64                         try {
65                                         password = Symm.base64noSplit.depass(password);
66                                 } catch (IOException e) {
67                                         throw new AuthenticationException("AAF bnf: Password cannot be decoded");
68                                 }
69                         } else if(password.startsWith("enc:")) {
70                                 try {
71                                         password = access.decrypt(password, true);
72                                 } catch (IOException e) {
73                                         throw new AuthenticationException("AAF Encrypted Password cannot be decrypted");
74                                 }
75                     }
76                     
77                     if(localLur!=null) {
78                         access.log(Level.DEBUG, "Validating",fullName, "with LocalTaf", password); 
79                         if(localLur.validate(fullName, Type.PASSWORD, password.getBytes(),null)) {
80                                     aau.setAnonymous(true);
81                                     aau.setLocal(true);
82                                     access.log(Level.DEBUG, fullName, "is authenticated locally"); 
83                                 return aau;
84                         }
85                     }
86                     
87                     String aafResponse;
88                     try {
89                         access.log(Level.DEBUG, "Validating",fullName, "with AAF");//, password); 
90                         aafResponse = aafAuthn.validate(fullName, password,null);
91                             if(aafResponse != null) { // Reason for failing.
92                                 access.log(Level.AUDIT, "AAF reports ",fullName,":",aafResponse);
93                                 throw new AuthenticationException(aafResponse);
94                             }
95                             access.log(Level.AUDIT, fullName, "is authenticated"); //,password);
96                             // This tells Cassandra to skip checking it's own tables for User Entries.
97                             aau.setAnonymous(true);
98                     } catch (AuthenticationException ex) {
99                         throw ex;
100                     } catch(Exception ex) {
101                         access.log(ex,"Exception validating user");                             
102                         throw new AuthenticationException("Exception validating user");
103                     }
104                     
105                     return aau; 
106           }
107           
108           public void create(String username, Map<IAuthenticator.Option, Object> options) throws InvalidRequestException, RequestExecutionException {
109                   access.log(Level.INFO,"Use AAF CLI to create user");
110           }
111           
112           public void alter(String username, Map<IAuthenticator.Option, Object> options) throws RequestExecutionException {
113                   access.log(Level.INFO,"Use AAF CLI to alter user");
114           }
115           
116           public void drop(String username) throws RequestExecutionException {
117                   access.log(Level.INFO,"Use AAF CLI to delete user");
118           }
119           
120           public SaslAuthenticator newAuthenticator() {
121                   return new ISaslAwareAuthenticator.SaslAuthenticator() {
122                     private boolean complete = false;
123                     private Map<String, String> credentials;
124
125                     public byte[] evaluateResponse(byte[] clientResponse) throws AuthenticationException {
126                       this.credentials = decodeCredentials(clientResponse);
127                       this.complete = true;
128                       return null;
129                     }
130
131                     public boolean isComplete() {
132                       return this.complete;
133                     }
134
135                     public AuthenticatedUser getAuthenticatedUser() throws AuthenticationException {
136                       return AAFAuthenticator.this.authenticate(this.credentials);
137                     }
138
139                     private Map<String, String> decodeCredentials(byte[] bytes) throws AuthenticationException {
140                         access.log(Level.DEBUG,"Decoding credentials from client token");
141                       byte[] user = null;
142                       byte[] pass = null;
143                       int end = bytes.length;
144                       for (int i = bytes.length - 1; i >= 0; i--) {
145                         if (bytes[i] != 0) {
146                           continue;
147                         }
148                         if (pass == null) {
149                           pass = Arrays.copyOfRange(bytes, i + 1, end);
150                         } else if (user == null) {
151                           user = Arrays.copyOfRange(bytes, i + 1, end);
152                         }        
153                         end = i;
154                       }
155
156                       if (user == null) {
157                         throw new AuthenticationException("Authentication ID must not be null");
158                       }
159                       // SONAR thinks this code won't be hit, and keeps calling it a "Blocker" (???)  so we delete
160 //                    if (pass == null) {
161 //                      throw new AuthenticationException("Password must not be null");
162 //                    }
163                       Map<String,String> credentials = new HashMap<String,String>();
164                       try {
165                           credentials.put(IAuthenticator.USERNAME_KEY, new String(user, Config.UTF_8));
166                           credentials.put(IAuthenticator.PASSWORD_KEY, new String(pass, Config.UTF_8));
167                                 } catch (UnsupportedEncodingException e) {
168                                         throw new AuthenticationException(e.getMessage());
169                                 }
170                       return credentials;
171                     }
172                   };      
173           }
174
175 }
176