2 * ============LICENSE_START====================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
22 package com.att.aaf.cadi.cass;
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import java.util.Arrays;
27 import java.util.HashMap;
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;
41 public class AAFAuthenticator extends AAFBase implements ISaslAwareAuthenticator {
43 public boolean requireAuthentication() {
48 * Invoked to authenticate an user
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");
56 AAFAuthenticatedUser aau = new AAFAuthenticatedUser(access,username);
57 String fullName=aau.getFullName();
58 access.log(Level.DEBUG, "Authenticating", aau.getName(),"(", fullName,")");
60 String password = (String)credentials.get("password");
61 if (password == null) {
62 throw new AuthenticationException("'password' is missing");
63 } else if(password.startsWith("bsf:")) {
65 password = Symm.base64noSplit.depass(password);
66 } catch (IOException e) {
67 throw new AuthenticationException("AAF bnf: Password cannot be decoded");
69 } else if(password.startsWith("enc:")) {
71 password = access.decrypt(password, true);
72 } catch (IOException e) {
73 throw new AuthenticationException("AAF Encrypted Password cannot be decrypted");
78 access.log(Level.DEBUG, "Validating",fullName, "with LocalTaf", password);
79 if(localLur.validate(fullName, Type.PASSWORD, password.getBytes(),null)) {
80 aau.setAnonymous(true);
82 access.log(Level.DEBUG, fullName, "is authenticated locally");
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);
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) {
100 } catch(Exception ex) {
101 access.log(ex,"Exception validating user");
102 throw new AuthenticationException("Exception validating user");
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");
112 public void alter(String username, Map<IAuthenticator.Option, Object> options) throws RequestExecutionException {
113 access.log(Level.INFO,"Use AAF CLI to alter user");
116 public void drop(String username) throws RequestExecutionException {
117 access.log(Level.INFO,"Use AAF CLI to delete user");
120 public SaslAuthenticator newAuthenticator() {
121 return new ISaslAwareAuthenticator.SaslAuthenticator() {
122 private boolean complete = false;
123 private Map<String, String> credentials;
125 public byte[] evaluateResponse(byte[] clientResponse) throws AuthenticationException {
126 this.credentials = decodeCredentials(clientResponse);
127 this.complete = true;
131 public boolean isComplete() {
132 return this.complete;
135 public AuthenticatedUser getAuthenticatedUser() throws AuthenticationException {
136 return AAFAuthenticator.this.authenticate(this.credentials);
139 private Map<String, String> decodeCredentials(byte[] bytes) throws AuthenticationException {
140 access.log(Level.DEBUG,"Decoding credentials from client token");
143 int end = bytes.length;
144 for (int i = bytes.length - 1; i >= 0; i--) {
149 pass = Arrays.copyOfRange(bytes, i + 1, end);
150 } else if (user == null) {
151 user = Arrays.copyOfRange(bytes, i + 1, end);
157 throw new AuthenticationException("Authentication ID must not be null");
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");
163 Map<String,String> credentials = new HashMap<String,String>();
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());