Ravi Nori has uploaded a new change for review. Change subject: aaa: Encrypt password returned to user, add support for Login On Behalf ......................................................................
aaa: Encrypt password returned to user, add support for Login On Behalf Will be merged to first patch Change-Id: I1422774b0fbf52a59299f521ad92c6d576f7a1b2 Bug-Url: https://bugzilla.redhat.com/1092744 Signed-off-by: Ravi Nori <rn...@redhat.com> --- M backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenInfo.java M backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenServlet.java M backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/utils/SSOUtils.java 3 files changed, 93 insertions(+), 26 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/91/42291/1 diff --git a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenInfo.java b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenInfo.java index 26b4a93..d849e9e 100644 --- a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenInfo.java +++ b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenInfo.java @@ -1,8 +1,6 @@ package org.ovirt.engine.core.sso.servlets; import org.apache.commons.lang.StringUtils; -import org.ovirt.engine.api.extensions.ExtMap; -import org.ovirt.engine.api.extensions.aaa.Authz; import org.ovirt.engine.core.sso.utils.OAuthException; import org.ovirt.engine.core.sso.utils.SSOUtils; import org.slf4j.Logger; @@ -39,7 +37,7 @@ } String password = null; if (SSOUtils.scopeAsList(scope).contains("ovirt-auth-password-access")) { - password = (String) sessionData.get(SSOUtils.PASSWORD); + password = SSOUtils.encrypt(request.getServletContext(), (String) sessionData.get(SSOUtils.PASSWORD)); } SSOUtils.sendJsonData(response, SSOUtils.scopeAsList(scope).contains("ovirt-auth-validate") ? Collections.<String, Object>emptyMap() : @@ -63,11 +61,10 @@ Map<String, Object> ovirt = new HashMap<>(); ovirt.put("version", SSOUtils.SSO_VERSION); - ExtMap principalRecord = (ExtMap) sessionData.get(SSOUtils.SSO_PRINCIPAL_RECORD_ATTR_NAME); - ovirt.put("principal_id", principalRecord.<String>get(Authz.PrincipalRecord.ID)); - ovirt.put("email", principalRecord.<String>get(Authz.PrincipalRecord.EMAIL)); - ovirt.put("group_ids", principalRecord.get(Authz.PrincipalRecord.GROUPS, Collections.<ExtMap>emptyList())); + ovirt.put("principal_id", sessionData.get(SSOUtils.SSO_PRINCIPAL_ID_ATTR_NAME)); + ovirt.put("email", sessionData.get(SSOUtils.SSO_EMAIL_ATTR_NAME)); + ovirt.put("group_ids", sessionData.get(SSOUtils.SSO_GROUP_IDS_ATTR_NAME)); if (StringUtils.isNotEmpty(password)) { ovirt.put("password", password); } diff --git a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenServlet.java b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenServlet.java index 517dbb2..f4f5eca 100644 --- a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenServlet.java +++ b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/servlets/OAuthTokenServlet.java @@ -40,7 +40,7 @@ issueTokenForAuthCode(request, response, clientIdAndSecret[0]); break; case "password": - issueTokenForPasswd(request, response); + handlePasswordGrantType(request, response, scope); break; case "urn:ovirt:params:oauth:grant-type:http": String redirectUri = SSOUtils.getRequestParameter(request, SSOUtils.REDIRECT_URI, SSOUtils.REDIRECT_URI); @@ -75,6 +75,27 @@ SSOUtils.sendJsonData(response, buildResponse(sessionData)); } + private void handlePasswordGrantType(HttpServletRequest request, HttpServletResponse response, String scope) throws Exception { + if (SSOUtils.scopeAsList(scope).contains("ovirt-auth-on-behalf")) { + issueTokenForLoginOnBehalf(request, response); + } else { + issueTokenForPasswd(request, response); + } + } + + private static void issueTokenForLoginOnBehalf(HttpServletRequest request, HttpServletResponse response) throws Exception { + log.debug("Entered issueTokenForLoginOnBehalf"); + Map<String, Object> payload = SSOUtils.readJson(SSOUtils.getRequestParameter(request, "payload", null)); + payload.put(SSOUtils.VALID_TO, "" + Integer.MAX_VALUE); + String token = SSOUtils.persistAuthInfoInContextWithToken(request, false, null, payload); + Map<String, Object> sessionData = SSOUtils.getSessionData(request.getServletContext(), token); + if (sessionData == null) { + throw new OAuthException(SSOUtils.ERR_CODE_INVALID_GRANT, "The provided authorization grant for the username and password has expired"); + } + log.debug("Sending json response"); + SSOUtils.sendJsonData(response, buildResponse(sessionData)); + } + private static void issueTokenForPasswd(HttpServletRequest request, HttpServletResponse response) throws Exception { log.debug("Entered issueTokenForPasswd"); Credentials credentials = null; @@ -82,11 +103,11 @@ credentials = SSOUtils.translateUser(SSOUtils.getRequestParameter(request, "username", "username"), SSOUtils.getRequestParameter(request, "password", "password"), (SSOConfig) request.getServletContext().getAttribute(SSOUtils.SSO_CONFIG)); - String code = null; + String token = null; if (credentials != null && credentials.isValid()) { - code = AuthenticationUtils.handleCredentials(request, false, credentials); + token = AuthenticationUtils.handleCredentials(request, false, credentials); } - Map<String, Object> sessionData = SSOUtils.getSessionData(request.getServletContext(), code); + Map<String, Object> sessionData = SSOUtils.getSessionData(request.getServletContext(), token); if (sessionData == null) { throw new OAuthException(SSOUtils.ERR_CODE_INVALID_GRANT, "The provided authorization grant for the username and password has expired"); } diff --git a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/utils/SSOUtils.java b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/utils/SSOUtils.java index 07c4398..2576d46 100644 --- a/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/utils/SSOUtils.java +++ b/backend/manager/modules/enginesso/src/main/java/org/ovirt/engine/core/sso/utils/SSOUtils.java @@ -4,7 +4,6 @@ import org.apache.commons.lang.StringUtils; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.DeserializationConfig.Feature; -import org.ovirt.engine.api.extensions.Base; import org.ovirt.engine.api.extensions.ExtMap; import org.ovirt.engine.api.extensions.aaa.Authn; import org.ovirt.engine.api.extensions.aaa.Authz; @@ -12,16 +11,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.crypto.Cipher; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; +import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,10 +37,10 @@ public static final String LOGIN_MSG = "loginMsg"; public static final String PARAMS_MAP = "paramsMap"; - public static final String SSO_AUTHZ_ATTR_NAME = "AUTHZ_NAME"; - public static final String SSO_PROFILE_ATTR_NAME = "PROFILE_NAME"; - public static final String SSO_PRINCIPAL_RECORD_ATTR_NAME = "PRINCIPAL_RECORD"; - public static final String SSO_AUTH_RECORD_ATTR_NAME = "AUTH_RECORD"; + public static final String SSO_PROFILE_ATTR_NAME = "profile"; + public static final String SSO_PRINCIPAL_ID_ATTR_NAME = "principal_id"; + public static final String SSO_EMAIL_ATTR_NAME = "email"; + public static final String SSO_GROUP_IDS_ATTR_NAME = "group_ids"; public static final String SSO_VERSION = "0"; public static final String SSO_CONFIG = "config"; public static final String SSO_SESSION_DATA = "session_data"; @@ -94,7 +101,7 @@ public static boolean isUserAuthenticated(HttpSession session) { Map<String, Object> sessionData = getSessionData(session); - return sessionData == null ? false : sessionData.get(SSO_PRINCIPAL_RECORD_ATTR_NAME) != null; + return sessionData == null ? false : sessionData.get(SSO_PRINCIPAL_ID_ATTR_NAME) != null; } public static void redirectToModule(HttpServletRequest request, @@ -194,6 +201,13 @@ .enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); mapper.getSerializationConfig().addMixInAnnotations(ExtMap.class, JsonExtMapMixIn.class); return mapper.writeValueAsString(obj); + } + + public static Map<String, Object> readJson(String payload) throws IOException { + ObjectMapper mapper = new ObjectMapper().configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); + mapper.getDeserializationConfig().addMixInAnnotations(ExtMap.class, JsonExtMapMixIn.class); + return mapper.readValue(payload.getBytes(), HashMap.class); } public static String getParameter(HttpServletRequest request, String paramName) { @@ -338,6 +352,23 @@ ExtensionProxy authz, ExtMap authRecord, ExtMap principalRecord) { + String validTo = authRecord.get(Authn.AuthRecord.VALID_TO); + String principal = principalRecord.get(Authz.PrincipalRecord.PRINCIPAL); + + Map<String, Object> payload = new HashMap<>(); + payload.put(USER_ID, principal != null ? principal : principalRecord.<String>get(Authz.PrincipalRecord.NAME)); + payload.put(SSO_PRINCIPAL_ID_ATTR_NAME, principalRecord.get(Authz.PrincipalRecord.ID)); + payload.put(SSO_EMAIL_ATTR_NAME, principalRecord.<String>get(Authz.PrincipalRecord.EMAIL)); + payload.put(SSO_GROUP_IDS_ATTR_NAME, principalRecord.get(Authz.PrincipalRecord.GROUPS, Collections.<ExtMap>emptyList())); + payload.put(VALID_TO, StringUtils.isEmpty(validTo) ? "" + Integer.MAX_VALUE : validTo); + payload.put(SSO_PROFILE_ATTR_NAME, profileName); + return persistAuthInfoInContextWithToken(request, isInteractive, password, payload); + } + + public static String persistAuthInfoInContextWithToken(HttpServletRequest request, + boolean isInteractive, + String password, + Map<String, Object> payload) { Map<String, Object> sessionData = new HashMap<>(); String authCode = generateAuthorizationToken(); String accessToken = generateAuthorizationToken(); @@ -347,18 +378,16 @@ sessionData.put(SSO_SESSION, session); } - String principal = principalRecord.get(Authz.PrincipalRecord.PRINCIPAL); String clientId = getClientId(request); - String authzName = authz.getContext().get(Base.ContextKeys.INSTANCE_NAME); // Info for token registry sessionData.put(CLIENT_ID, clientId); sessionData.put(ACTIVE, true); sessionData.put(AUTHORIZATION_CODE, authCode); sessionData.put(ACCESS_TOKEN, accessToken); - String validTo = authRecord.get(Authn.AuthRecord.VALID_TO); - sessionData.put(VALID_TO, StringUtils.isEmpty(validTo) ? ""+ Integer.MAX_VALUE : validTo); - sessionData.put(USER_ID, principal != null ? principal : principalRecord.<String>get(Authz.PrincipalRecord.NAME)); + + sessionData.put(VALID_TO, payload.get(VALID_TO)); + sessionData.put(USER_ID, payload.get(USER_ID)); sessionData.put(SCOPE, getParameter(request, SCOPE)); if (StringUtils.isNotEmpty(password)) { sessionData.put(PASSWORD, password); @@ -366,10 +395,10 @@ sessionData.put(REDIRECT_URI, getParameter(request, REDIRECT_URI)); // info for token payload - sessionData.put(SSO_PROFILE_ATTR_NAME, profileName); - sessionData.put(SSO_AUTHZ_ATTR_NAME, authzName); - sessionData.put(SSO_AUTH_RECORD_ATTR_NAME, authRecord); - sessionData.put(SSO_PRINCIPAL_RECORD_ATTR_NAME, principalRecord); + sessionData.put(SSO_PROFILE_ATTR_NAME, payload.get(SSO_PROFILE_ATTR_NAME)); + sessionData.put(SSO_PRINCIPAL_ID_ATTR_NAME, payload.get(SSO_PRINCIPAL_ID_ATTR_NAME)); + sessionData.put(SSO_EMAIL_ATTR_NAME, payload.get(SSO_EMAIL_ATTR_NAME)); + sessionData.put(SSO_GROUP_IDS_ATTR_NAME, payload.get(SSO_GROUP_IDS_ATTR_NAME)); sessionData.put(TOKEN_LAST_ACCESS, System.nanoTime()); ((Map<String, Map>) request.getServletContext().getAttribute(SSO_SESSION_DATA)).put(accessToken, sessionData); @@ -445,4 +474,24 @@ public static List<String> scopeAsList(String scope) { return Arrays.asList(scope.trim().split("\\s *")); } + + public static String encrypt(ServletContext ctx, String rawText) + throws IOException, GeneralSecurityException { + + SSOConfig ssoConfig = (SSOConfig) ctx.getAttribute(SSO_CONFIG); + String certPath = ssoConfig.getSsoLocalConfig().getProperty("SSO_PKI_ENGINE_CERT", true); + if (StringUtils.isEmpty(certPath)) { + certPath = ssoConfig.getSsoLocalConfig().getProperty("ENGINE_PKI_ENGINE_CERT"); + } + + Certificate cert; + try (InputStream in = new FileInputStream(new File(certPath))) { + cert = CertificateFactory.getInstance("X.509").generateCertificate(in); + } + + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, cert.getPublicKey()); + + return Base64.encodeBase64String(cipher.doFinal(rawText.getBytes("UTF-8"))); + } } -- To view, visit https://gerrit.ovirt.org/42291 To unsubscribe, visit https://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I1422774b0fbf52a59299f521ad92c6d576f7a1b2 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Ravi Nori <rn...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches