diff options
Diffstat (limited to 'src/main/java/org/onap/music/authentication')
-rwxr-xr-x | src/main/java/org/onap/music/authentication/CachingUtil.java | 445 | ||||
-rw-r--r-- | src/main/java/org/onap/music/authentication/CadiAuthFilter.java | 110 | ||||
-rw-r--r-- | src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java (renamed from src/main/java/org/onap/music/authentication/MusicAuthentication.java) | 168 | ||||
-rw-r--r-- | src/main/java/org/onap/music/authentication/MusicAuthenticator.java | 62 |
4 files changed, 692 insertions, 93 deletions
diff --git a/src/main/java/org/onap/music/authentication/CachingUtil.java b/src/main/java/org/onap/music/authentication/CachingUtil.java new file mode 100755 index 00000000..5c379c6e --- /dev/null +++ b/src/main/java/org/onap/music/authentication/CachingUtil.java @@ -0,0 +1,445 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Modifications Copyright (c) 2018 IBM + * Modifications Copyright (c) 2019 Samsung + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.authentication; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MediaType; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.jcs.JCS; +import org.apache.commons.jcs.access.CacheAccess; +import org.mindrot.jbcrypt.BCrypt; +import org.onap.music.authentication.MusicAuthenticator.Operation; +import org.onap.music.datastore.PreparedQueryObject; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.eelf.logging.format.AppMessages; +import org.onap.music.eelf.logging.format.ErrorSeverity; +import org.onap.music.eelf.logging.format.ErrorTypes; +import org.onap.music.exceptions.MusicServiceException; +import org.onap.music.main.MusicCore; +import org.onap.music.main.MusicUtil; +import com.datastax.driver.core.DataType; +import com.datastax.driver.core.PreparedStatement; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; +import com.datastax.driver.core.exceptions.InvalidQueryException; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; + +/** + * All Caching related logic is handled by this class and a schedule cron runs to update cache. + * + * @author Vikram + * + */ +public class CachingUtil implements Runnable { + + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CachingUtil.class); + + /** keyspace & ns */ + private static CacheAccess<String, String> musicCache = JCS.getInstance("musicCache"); + /** cache to hold isaaf application */ + private static CacheAccess<String, String> appNameCache = JCS.getInstance("appNameCache"); + /** hold user creds for namespace */ + private static CacheAccess<String, Map<String, String>> musicValidateCache = JCS.getInstance("musicValidateCache"); + private static Map<String, Number> userAttempts = new HashMap<>(); + private static Map<String, Calendar> lastFailedTime = new HashMap<>(); + private static CacheAccess<String, String> adminUserCache = JCS.getInstance("adminUserCache"); + + public static CacheAccess<String, String> getAdminUserCache() { + return adminUserCache; + } + + public static void updateAdminUserCache(String authorization,String userId) { + adminUserCache.put(authorization,userId); + } + + private static final String USERNAME="username"; + private static final String PASSWORD="password"; + + + public void initializeAafCache() throws MusicServiceException { + logger.info(EELFLoggerDelegate.applicationLogger,"Resetting and initializing AAF Cache..."); + + String query = "SELECT uuid, application_name, keyspace_name, username, password FROM admin.keyspace_master WHERE is_api = ? allow filtering"; + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString(query); + try { + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.cboolean(), false)); + } catch (Exception e1) { + logger.error(EELFLoggerDelegate.errorLogger, e1.getMessage(),AppMessages.CACHEERROR, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR); + } + ResultSet rs = MusicCore.get(pQuery); + Iterator<Row> it = rs.iterator(); + Map<String, String> map = null; + while (it.hasNext()) { + Row row = it.next(); + String nameSpace = row.getString("keyspace_name"); + String userId = row.getString(USERNAME); + String password = row.getString(PASSWORD); + String keySpace = row.getString("application_name"); + try { + userAttempts.put(nameSpace, 0); + boolean responseObj = triggerAAF(nameSpace, userId, password); + if (responseObj) { + map = new HashMap<>(); + map.put(userId, password); + musicValidateCache.put(nameSpace, map); + musicCache.put(keySpace, nameSpace); + logger.debug("Cronjob: Cache Updated with AAF response for namespace " + + nameSpace); + } + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),"Something at AAF was changed for ns: " + nameSpace+" So not updating Cache for the namespace. "); + } + } + + } + + @Override + public void run() { + logger.info(EELFLoggerDelegate.applicationLogger,"Scheduled task invoked. Refreshing Cache..."); + try { + initializeAafCache(); + } catch (MusicServiceException e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(),AppMessages.UNKNOWNERROR, ErrorSeverity.INFO, ErrorTypes.GENERALSERVICEERROR); + } + } + + public static boolean authenticateAAFUser(String nameSpace, String userId, String password, + String keySpace) throws Exception { + + if (musicValidateCache.get(nameSpace) != null && musicCache.get(keySpace)!=null) { + if (keySpace != null && !musicCache.get(keySpace).equals(nameSpace)) { + logger.info(EELFLoggerDelegate.applicationLogger,"Create new application for the same namespace."); + } else if (musicValidateCache.get(nameSpace).get(userId).equals(password)) { + logger.info(EELFLoggerDelegate.applicationLogger,"Authenticated with cache value.."); + // reset invalid attempts to 0 + userAttempts.put(nameSpace, 0); + return true; + } else { + // call AAF update cache with new password + if (userAttempts.get(nameSpace) == null) + userAttempts.put(nameSpace, 0); + if ((Integer) userAttempts.get(nameSpace) >= 3) { + logger.info(EELFLoggerDelegate.applicationLogger,"Reached max attempts. Checking if time out.."); + logger.info(EELFLoggerDelegate.applicationLogger,"Failed time: "+lastFailedTime.get(nameSpace).getTime()); + Calendar calendar = Calendar.getInstance(); + long delayTime = (calendar.getTimeInMillis()-lastFailedTime.get(nameSpace).getTimeInMillis()); + logger.info(EELFLoggerDelegate.applicationLogger,"Delayed time: "+delayTime); + if( delayTime > 120000) { + logger.info(EELFLoggerDelegate.applicationLogger,"Resetting failed attempt."); + userAttempts.put(nameSpace, 0); + } else { + logger.info(EELFLoggerDelegate.applicationLogger,"No more attempts allowed. Please wait for atleast 2 min."); + throw new Exception("No more attempts allowed. Please wait for atleast 2 min."); + } + } + logger.error(EELFLoggerDelegate.errorLogger,"",AppMessages.CACHEAUTHENTICATION,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + logger.info(EELFLoggerDelegate.applicationLogger,"Check AAF again..."); + } + } + + boolean responseObj = false; + try { + responseObj = triggerAAF(nameSpace, userId, password); + }catch (Exception ex) { + logger.info("Exception while trigger aaf"); + logger.info("Exception: " + ex.getMessage()); + throw new Exception("Exception raised while triggering AAF authentication" +ex.getMessage()); + } + if (responseObj) { + logger.info(EELFLoggerDelegate.applicationLogger,"Valid user. Cache is updated for "+nameSpace); + Map<String, String> map = new HashMap<>(); + map.put(userId, password); + musicValidateCache.put(nameSpace, map); + musicCache.put(keySpace, nameSpace); + return true; + } + logger.info(EELFLoggerDelegate.applicationLogger,"Invalid user. Cache not updated"); + return false; + } + + private static boolean triggerAAF(String nameSpace, String userId, String password) + throws Exception { + logger.info(EELFLoggerDelegate.applicationLogger,"Inside AAF authorization"); + if (MusicUtil.getAafEndpointUrl() == null) { + logger.error(EELFLoggerDelegate.errorLogger,"AAF endpoint is not set. Please specify in the properties file.",AppMessages.UNKNOWNERROR,ErrorSeverity.WARN, ErrorTypes.GENERALSERVICEERROR); + throw new Exception("AAF endpoint is not set. Please specify in the properties file."); + } + Client client = Client.create(); + // WebResource webResource = + // client.resource("https://aaftest.test.att.com:8095/proxy/authz/nss/"+nameSpace); + WebResource webResource = client.resource(MusicUtil.getAafEndpointUrl().concat(nameSpace)); + String plainCreds = userId + ":" + password; + byte[] plainCredsBytes = plainCreds.getBytes(); + byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes); + String base64Creds = new String(base64CredsBytes); + + ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) + .header("Authorization", "Basic " + base64Creds) + .header("content-type", "application/json").get(ClientResponse.class); + logger.info(EELFLoggerDelegate.applicationLogger, "aaf response: "+response.toString()); + if (response.getStatus() != 200) { + if (userAttempts.get(nameSpace) == null) + userAttempts.put(nameSpace, 0); + if ((Integer) userAttempts.get(nameSpace) >= 2) { + lastFailedTime.put(nameSpace, Calendar.getInstance()); + userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); + throw new Exception( + "Reached max invalid attempts. Please contact admin and retry with valid credentials."); + } + userAttempts.put(nameSpace, ((Integer) userAttempts.get(nameSpace) + 1)); + throw new Exception( + "Unable to authenticate. Please check the AAF credentials against namespace."); + // TODO Allow for 2-3 times and forbid any attempt to trigger AAF with invalid values + // for specific time. + } + /*response.getHeaders().put(HttpHeaders.CONTENT_TYPE, + Arrays.asList(MediaType.APPLICATION_JSON)); + // AAFResponse output = response.getEntity(AAFResponse.class); + response.bufferEntity(); + String x = response.getEntity(String.class); + AAFResponse responseObj = new ObjectMapper().readValue(x, AAFResponse.class);*/ + + return true; + } + + public static void updateMusicCache(String keyspace, String nameSpace) { + logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for keyspace " + keyspace + " with nameSpace " + nameSpace); + musicCache.put(keyspace, nameSpace); + } + + public static void updateCadiCache(String user, String keyspace) { + musicCache.put(user, keyspace); + } + + public static String getKSFromCadiCache(String user) { + return musicCache.get(user); + } + + public static void updateMusicValidateCache(String nameSpace, String userId, String password) { + logger.info(EELFLoggerDelegate.applicationLogger,"Updating musicCache for nameSpacce " + nameSpace + " with userId " + userId); + Map<String, String> map = new HashMap<>(); + map.put(userId, password); + musicValidateCache.put(nameSpace, map); + } + + public static void updateisAAFCache(String namespace, String isAAF) { + appNameCache.put(namespace, isAAF); + } + + public static String isAAFApplication(String namespace) throws MusicServiceException { + String isAAF = appNameCache.get(namespace); + if (isAAF == null) { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT is_aaf from admin.keyspace_master where application_name = '" + + namespace + "' allow filtering"); + Row rs = null; + try { + rs = MusicCore.get(pQuery).one(); + } catch(InvalidQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage()); + throw new MusicServiceException("Please make sure admin.keyspace_master table is configured."); + } + try { + isAAF = String.valueOf(rs.getBool("is_aaf")); + if(isAAF != null) + appNameCache.put(namespace, isAAF); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR,ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + } + } + return isAAF; + } + + public static String getUuidFromMusicCache(String keyspace) throws MusicServiceException { + String uuid = null; + if (uuid == null) { + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT uuid from admin.keyspace_master where keyspace_name = '" + + keyspace + "' allow filtering"); + Row rs = MusicCore.get(pQuery).one(); + try { + uuid = rs.getUUID("uuid").toString(); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception occurred during uuid retrieval from DB."+e.getMessage()); + } + } + return uuid; + } + + public static String getAppName(String keyspace) throws MusicServiceException { + String appName = null; + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "SELECT application_name from admin.keyspace_master where keyspace_name = '" + + keyspace + "' allow filtering"); + Row rs = MusicCore.get(pQuery).one(); + try { + appName = rs.getString("application_name"); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger, e.getMessage(), AppMessages.QUERYERROR, ErrorSeverity.ERROR, ErrorTypes.QUERYERROR); + } + return appName; + } + + @Deprecated + public static Map<String, Object> validateRequest(String nameSpace, String userId, + String password, String keyspace, String aid, String operation) { + Map<String, Object> resultMap = new HashMap<>(); + if (!"createKeySpace".equals(operation)) { + if (nameSpace == null) { + resultMap.put("Exception", "Application namespace is mandatory."); + } + } + return resultMap; + } + + public static Map<String, Object> validateRequest(String nameSpace, String userId, + String password, String keyspace, String aid, Operation operation) { + Map<String, Object> resultMap = new HashMap<>(); + if (Operation.CREATE_KEYSPACE!=operation) { + if (nameSpace == null) { + resultMap.put("Exception", "Application namespace is mandatory."); + } + } + return resultMap; + } + + public static Map<String, Object> verifyOnboarding(String ns, String userId, String password) { + Map<String, Object> resultMap = new HashMap<>(); + if (ns == null || userId == null || password == null) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: "+userId+" :: password: "+password); + resultMap.put("Exception", + "One or more required headers appName(ns), userId, password is missing. Please check."); + return resultMap; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "select * from admin.keyspace_master where application_name = ? allow filtering"); + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), ns)); + } catch(Exception e) { + resultMap.put("Exception", + "Unable to process input data. Invalid input data type. Please check ns, userId and password values. "+e.getMessage()); + return resultMap; + } + Row rs = null; + try { + rs = MusicCore.get(queryObject).one(); + } catch (MusicServiceException e) { + String errorMsg = "Unable to process operation. Error is "+e.getMessage(); + logger.error(EELFLoggerDelegate.errorLogger, errorMsg); + resultMap.put("Exception", errorMsg); + return resultMap; + } catch (InvalidQueryException e) { + logger.error(EELFLoggerDelegate.errorLogger,"Exception admin keyspace not configured."+e.getMessage()); + resultMap.put("Exception", "Please make sure admin.keyspace_master table is configured."); + return resultMap; + } + if (rs == null) { + logger.error(EELFLoggerDelegate.errorLogger,"Application is not onboarded. Please contact admin."); + resultMap.put("Exception", "Application is not onboarded. Please contact admin."); + } else { + if(!(rs.getString(USERNAME).equals(userId)) || !(BCrypt.checkpw(password, rs.getString(PASSWORD)))) { + logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.AUTHENTICATIONERROR, ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); + logger.error(EELFLoggerDelegate.errorLogger,"Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + resultMap.put("Exception", "Namespace, UserId and password doesn't match. namespace: "+ns+" and userId: "+userId); + return resultMap; + } + } + return resultMap; + } + + public static Map<String, Object> authenticateAIDUser(String nameSpace, String userId, String password, + String keyspace) { + Map<String, Object> resultMap = new HashMap<>(); + String pwd = null; + if((musicCache.get(keyspace) != null) && (musicValidateCache.get(nameSpace) != null) + && (musicValidateCache.get(nameSpace).containsKey(userId))) { + if(!musicCache.get(keyspace).equals(nameSpace)) { + resultMap.put("Exception", "Namespace and keyspace doesn't match"); + return resultMap; + } + if(!BCrypt.checkpw(password,musicValidateCache.get(nameSpace).get(userId))) { + resultMap.put("Exception", "Namespace, userId and password doesn't match"); + return resultMap; + } + return resultMap; + } + PreparedQueryObject queryObject = new PreparedQueryObject(); + queryObject.appendQueryString( + "select * from admin.keyspace_master where keyspace_name = ? allow filtering"); + try { + queryObject.addValue(MusicUtil.convertToActualDataType(DataType.text(), keyspace)); + } catch (Exception e) { + logger.error(EELFLoggerDelegate.errorLogger,"Adding value to query object failed: " + e.getMessage()); + } + Row rs = null; + try { + rs = MusicCore.get(queryObject).one(); + } catch (MusicServiceException e) { + String errMsg = "Unable to process operation. Error is "+e.getMessage(); + logger.error(EELFLoggerDelegate.errorLogger, errMsg); + resultMap.put("Exception", errMsg); + return resultMap; + } + if(rs == null) { + resultMap.put("Exception", "Please make sure keyspace:"+keyspace+" exists."); + return resultMap; + } + else { + String user = rs.getString(USERNAME); + pwd = rs.getString(PASSWORD); + String ns = rs.getString("application_name"); + if(!ns.equals(nameSpace)) { + resultMap.put("Exception", "Namespace and keyspace doesn't match"); + return resultMap; + } + if(!user.equals(userId)) { + resultMap.put("Exception", "Invalid userId :"+userId); + return resultMap; + } + if(!BCrypt.checkpw(password, pwd)) { + resultMap.put("Exception", "Invalid password"); + return resultMap; + } + } + CachingUtil.updateMusicCache(keyspace, nameSpace); + CachingUtil.updateMusicValidateCache(nameSpace, userId, pwd); + return resultMap; + } +} diff --git a/src/main/java/org/onap/music/authentication/CadiAuthFilter.java b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java new file mode 100644 index 00000000..56371c7d --- /dev/null +++ b/src/main/java/org/onap/music/authentication/CadiAuthFilter.java @@ -0,0 +1,110 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.authentication; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + +import com.att.eelf.configuration.EELFLogger; +import org.onap.aaf.cadi.CadiWrap; +import org.onap.aaf.cadi.Permission; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.music.eelf.logging.EELFLoggerDelegate; +import org.onap.music.main.MusicCore; + +public class CadiAuthFilter extends CadiFilter { + + private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(CadiAuthFilter.class); + + public CadiAuthFilter(PropAccess access) throws ServletException { + super(true, access); + } + + public void init(FilterConfig filterConfig) throws ServletException { + super.init(filterConfig); + } + + + private boolean matchPattern(String requestedPath, String includeUrl) { + includeUrl = includeUrl.substring(1); + String[] path = requestedPath.split("/"); + if (path.length > 1) { + String[] roleFunctionArray = includeUrl.split("/"); + boolean match = true; + for (int i = 0; i < roleFunctionArray.length; i++) { + if (match) { + if (!"*".equals(roleFunctionArray[i])) { + Pattern p = Pattern.compile(Pattern.quote(path[i]), Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(roleFunctionArray[i]); + match = m.matches(); + } else if (roleFunctionArray[i].equals("*")) { + match = true; + } + + } + } + if (match) + return match; + } else { + if (requestedPath.matches(includeUrl)) + return true; + else if ("*".equals(includeUrl)) + return true; + } + return false; + } + + + public static List<AAFPermission> getAAFPermissions(HttpServletRequest request) { + CadiWrap wrapReq = (CadiWrap) request; + List<Permission> perms = wrapReq.getPermissions(wrapReq.getUserPrincipal()); + List<AAFPermission> aafPermsList = new ArrayList<>(); + for (Permission perm : perms) { + AAFPermission aafPerm = (AAFPermission) perm; + aafPermsList.add(aafPerm); + logger.info(aafPerm.toString()); + logger.info(aafPerm.getType()); + } + return aafPermsList; + } + + public static List<AAFPermission> getAAFPermissions(ServletRequest request) { + CadiWrap wrapReq = (CadiWrap) request; + List<Permission> perms = wrapReq.getPermissions(wrapReq.getUserPrincipal()); + List<AAFPermission> aafPermsList = new ArrayList<>(); + for (Permission perm : perms) { + AAFPermission aafPerm = (AAFPermission) perm; + aafPermsList.add(aafPerm); + } + return aafPermsList; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/music/authentication/MusicAuthentication.java b/src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java index 1d845b3c..2d0d4e59 100644 --- a/src/main/java/org/onap/music/authentication/MusicAuthentication.java +++ b/src/main/java/org/onap/music/authentication/MusicAAFAuthentication.java @@ -34,7 +34,7 @@ import org.onap.music.eelf.logging.format.AppMessages; import org.onap.music.eelf.logging.format.ErrorSeverity; import org.onap.music.eelf.logging.format.ErrorTypes; import org.onap.music.exceptions.MusicServiceException; -import org.onap.music.main.CachingUtil; +import org.onap.music.authentication.MusicAuthenticator.Operation; import org.onap.music.main.MusicCore; import org.onap.music.main.MusicUtil; @@ -44,70 +44,99 @@ import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; -public class MusicAuthentication { +public class MusicAAFAuthentication implements MusicAuthenticator { - private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAuthentication.class); + private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(MusicAAFAuthentication.class); - /** - * authenticate user logic - * - * @param nameSpace - * @param userId - * @param password - * @param keyspace - * @param aid - * @param operation - * @return - * @throws Exception - */ - public static Map<String, Object> autheticateUser(String nameSpace, String userId, - String password, String keyspace, String aid, String operation) - throws Exception { + @Override + public boolean authenticateAdmin(String authorization) { + logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: "); + String userId = MusicUtil.extractBasicAuthentication(authorization).get(MusicUtil.USERID); + if(MusicUtil.getIsCadi()) { + CachingUtil.updateAdminUserCache(authorization, userId); + return true; + } + CacheAccess<String, String> adminCache = CachingUtil.getAdminUserCache(); + if (authorization == null) { + logger.error(EELFLoggerDelegate.errorLogger, "Authorization cannot be empty..."); + return false; + } + if (adminCache.get(authorization) != null && adminCache.get(authorization).equals(userId)) { + logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: Validated against admincache.. "); + return true; + } + else { + Client client = Client.create(); + String aafUrl = MusicUtil.getAafAdminUrl(); + if (aafUrl==null) { + logger.error(EELFLoggerDelegate.errorLogger, "Admin url is not set, please set in properties"); + return false; + } + + WebResource webResource = client.resource( + MusicUtil.getAafAdminUrl().concat(userId).concat("/").concat(MusicUtil.getAdminAafRole())); + + ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) + .header("Authorization", authorization).get(ClientResponse.class); + if (response.getStatus() == 200) { + CachingUtil.updateAdminUserCache(authorization, userId); + return true; + } + } + return false; + } + + @Override + public boolean authenticateUser(String namespace, String authorization, String keyspace, + String aid, Operation operation) { logger.info(EELFLoggerDelegate.applicationLogger,"Inside User Authentication......."); + Map<String,String> userCredentials = MusicUtil.extractBasicAuthentication(authorization); + String userId = userCredentials.get(MusicUtil.USERID); + String password = userCredentials.get(MusicUtil.PASSWORD); + Map<String, Object> resultMap = new HashMap<>(); String uuid = null; if(! MusicUtil.getIsCadi()) { - resultMap = CachingUtil.validateRequest(nameSpace, userId, password, keyspace, aid, + resultMap = CachingUtil.validateRequest(namespace, userId, password, keyspace, aid, operation); if (!resultMap.isEmpty()) - return resultMap; + return false; String isAAFApp = null; try { - isAAFApp= CachingUtil.isAAFApplication(nameSpace); + isAAFApp= CachingUtil.isAAFApplication(namespace); } catch(MusicServiceException e) { logger.error(e.getErrorMessage(), e); resultMap.put("Exception", e.getMessage()); - return resultMap; + return false; } if(isAAFApp == null) { - resultMap.put("Exception", "Namespace: "+nameSpace+" doesn't exist. Please make sure ns(appName)" + resultMap.put("Exception", "Namespace: "+namespace+" doesn't exist. Please make sure ns(appName)" + " is correct and Application is onboarded."); - return resultMap; + return false; } boolean isAAF = Boolean.parseBoolean(isAAFApp); if (userId == null || password == null) { logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"One or more required headers is missing. userId: " + userId - + " :: password: " + password); + logger.error(EELFLoggerDelegate.errorLogger,"UserId/Password or more required headers is missing."); resultMap.put("Exception", "UserId and Password are mandatory for the operation " + operation); - return resultMap; + return false; } - if(!isAAF && !(operation.equals("createKeySpace"))) { - resultMap = CachingUtil.authenticateAIDUser(nameSpace, userId, password, keyspace); + if(!isAAF && !(operation==Operation.CREATE_KEYSPACE)) { + resultMap = CachingUtil.authenticateAIDUser(namespace, userId, password, keyspace); if (!resultMap.isEmpty()) - return resultMap; + return false; } - if (isAAF && nameSpace != null && userId != null && password != null) { + if (isAAF && namespace != null && userId != null && password != null) { boolean isValid = true; try { - isValid = CachingUtil.authenticateAAFUser(nameSpace, userId, password, keyspace); + isValid = CachingUtil.authenticateAAFUser(namespace, userId, password, keyspace); } catch (Exception e) { logger.error(EELFLoggerDelegate.errorLogger,"Error while aaf authentication for user:" + userId); logger.error(EELFLoggerDelegate.errorLogger,"Error: "+ e.getMessage()); logger.error(EELFLoggerDelegate.errorLogger,e.getMessage(), AppMessages.AUTHENTICATIONERROR ,ErrorSeverity.WARN, ErrorTypes.AUTHENTICATIONERROR); - logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + nameSpace); + logger.error(EELFLoggerDelegate.errorLogger,"Got exception while AAF authentication for namespace " + namespace); resultMap.put("Exception", e.getMessage()); } if (!isValid) { @@ -115,7 +144,7 @@ public class MusicAuthentication { resultMap.put("Exception", "User not authenticated..."); } if (!resultMap.isEmpty()) - return resultMap; + return false; } } else { @@ -123,79 +152,32 @@ public class MusicAuthentication { String cachedKS = CachingUtil.getKSFromCadiCache(userId); if(cachedKS != null && !cachedKS.equals(keyspace)) { resultMap.put("Exception", "User not authenticated to access this keyspace..."); + return false; } } - if (operation.equals("createKeySpace")) { - logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace."); - PreparedQueryObject pQuery = new PreparedQueryObject(); - pQuery.appendQueryString( - "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering"); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), nameSpace)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); - pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), - MusicUtil.DEFAULTKEYSPACENAME)); - + if (operation==Operation.CREATE_KEYSPACE) { try { + logger.info(EELFLoggerDelegate.applicationLogger,"AID is not provided. Creating new UUID for keyspace."); + PreparedQueryObject pQuery = new PreparedQueryObject(); + pQuery.appendQueryString( + "select uuid from admin.keyspace_master where application_name=? and username=? and keyspace_name=? allow filtering"); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), namespace)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), userId)); + pQuery.addValue(MusicUtil.convertToActualDataType(DataType.text(), + MusicUtil.DEFAULTKEYSPACENAME)); Row rs = MusicCore.get(pQuery).one(); uuid = rs.getUUID("uuid").toString(); resultMap.put("uuid", "existing"); } catch (Exception e) { logger.error(EELFLoggerDelegate.applicationLogger,"No UUID found in DB. So creating new UUID."); - uuid = CachingUtil.generateUUID(); + uuid = MusicUtil.generateUUID(); resultMap.put("uuid", "new"); } resultMap.put("aid", uuid); CachingUtil.updateCadiCache(userId, keyspace); } - - return resultMap; - } - - - public static boolean authenticateAdmin(String id,String password) { - return (id.equals(MusicUtil.getAdminId()) && password.equals(MusicUtil.getAdminPass())); - } - - public static boolean authenticateAdmin(Map<String,String> adminCredentials) { - if(adminCredentials.containsKey("ERROR")) - return false; - String admin_id = adminCredentials.get(MusicUtil.USERID); - String admin_password = adminCredentials.get(MusicUtil.PASSWORD); - return (admin_id.equals(MusicUtil.getAdminId()) && admin_password.equals(MusicUtil.getAdminPass())); - } - - public static boolean authenticateAdmin(String authorization) throws Exception { - logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: "+authorization); - String userId = MusicUtil.extractBasicAuthentication(authorization).get(MusicUtil.USERID); - if(MusicUtil.getIsCadi()) { - CachingUtil.updateAdminUserCache(authorization, userId); - return true; - } - CacheAccess<String, String> adminCache = CachingUtil.getAdminUserCache(); - if (authorization == null) { - logger.error(EELFLoggerDelegate.errorLogger, "Authorization cannot be empty..."+authorization); - throw new Exception("Authorization cannot be empty"); - } - if (adminCache.get(authorization) != null && adminCache.get(authorization).equals(userId)) { - logger.info(EELFLoggerDelegate.applicationLogger, "MusicCore.authenticateAdmin: Validated against admincache.. "+authorization); - return true; - } - else { - Client client = Client.create(); - WebResource webResource = client.resource( - MusicUtil.getAafAdminUrl().concat(userId).concat("/").concat(MusicUtil.getAdminAafRole())); - ; - - ClientResponse response = webResource.accept(MediaType.APPLICATION_JSON) - .header("Authorization", authorization).get(ClientResponse.class); - if (response.getStatus() == 200) { - CachingUtil.updateAdminUserCache(authorization, userId); - return true; - } - } - return false; - + return true; } } diff --git a/src/main/java/org/onap/music/authentication/MusicAuthenticator.java b/src/main/java/org/onap/music/authentication/MusicAuthenticator.java new file mode 100644 index 00000000..78f76ab1 --- /dev/null +++ b/src/main/java/org/onap/music/authentication/MusicAuthenticator.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START========================================== + * org.onap.music + * =================================================================== + * Copyright (c) 2019 AT&T Intellectual Property + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================= + * ==================================================================== + */ + +package org.onap.music.authentication; + +public interface MusicAuthenticator { + public enum Operation{ + CREATE_KEYSPACE, + DROP_KEYSPACE, + CREATE_TABLE, + CREATE_INDEX, + INSERT_INTO_TABLE, + UPDATE_TABLE, + DELETE_FROM_TABLE, + DROP_TABLE, + SELECT_CRITICAL, + SELECT, + CREATE_LOCKREF, + ACQUIRE_LOCK, + CURRENT_LOCK, + DELETE_LOCK + } + + /** + * Authenticate a user account + * @param namespace - user's namespace + * @param authorization - basicAuth representation of username/password + * @param keyspace - keyspace user is trying to access + * @param aid - aid that identifies the user + * @param operation - operation that user is trying to do + * @return true if user has access + */ + public boolean authenticateUser(String namespace, String authorization, + String keyspace, String aid, Operation operation); + + /** + * Authenticate an administrative account + * @param authorization - basicAuth representation of username/password + * @return true if user has admin privileges + */ + public boolean authenticateAdmin(String authorization); + +} |