Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(frontend): align frontend sso code with refactors #9506

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 49 additions & 61 deletions datahub-frontend/app/auth/AuthModule.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
package auth;

import static auth.AuthUtils.*;
import static auth.sso.oidc.OidcConfigs.*;
import static utils.ConfigUtil.*;

import auth.sso.SsoConfigs;
import auth.sso.SsoManager;
import auth.sso.oidc.OidcConfigs;
import auth.sso.oidc.OidcProvider;
import client.AuthServiceClient;
import com.datahub.authentication.Actor;
import com.datahub.authentication.ActorType;
Expand All @@ -23,14 +19,11 @@
import config.ConfigurationProvider;
import controllers.SsoCallbackController;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.pac4j.core.client.Client;
import org.pac4j.core.client.Clients;
import org.pac4j.core.config.Config;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.play.LogoutController;
Expand All @@ -45,6 +38,7 @@
import utils.ConfigUtil;

/** Responsible for configuring, validating, and providing authentication related components. */
@Slf4j
public class AuthModule extends AbstractModule {

/**
Expand All @@ -58,6 +52,7 @@ public class AuthModule extends AbstractModule {
private static final String PAC4J_SESSIONSTORE_PROVIDER_CONF = "pac4j.sessionStore.provider";
private static final String ENTITY_CLIENT_RETRY_INTERVAL = "entityClient.retryInterval";
private static final String ENTITY_CLIENT_NUM_RETRIES = "entityClient.numRetries";
private static final String GET_SSO_SETTINGS_ENDPOINT = "auth/getSsoSettings";

private final com.typesafe.config.Config _configs;

Expand Down Expand Up @@ -111,6 +106,7 @@ protected void configure() {
Authentication.class,
SystemEntityClient.class,
AuthServiceClient.class,
org.pac4j.core.config.Config.class,
com.typesafe.config.Config.class));
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(
Expand All @@ -124,34 +120,20 @@ protected void configure() {

@Provides
@Singleton
protected Config provideConfig(SsoManager ssoManager) {
if (ssoManager.isSsoEnabled()) {
final Clients clients = new Clients();
final List<Client> clientList = new ArrayList<>();
clientList.add(ssoManager.getSsoProvider().client());
clients.setClients(clientList);
final Config config = new Config(clients);
config.setHttpActionAdapter(new PlayHttpActionAdapter());
return config;
}
return new Config();
protected Config provideConfig() {
Config config = new Config();
config.setHttpActionAdapter(new PlayHttpActionAdapter());
return config;
}

@Provides
@Singleton
protected SsoManager provideSsoManager() {
SsoManager manager = new SsoManager();
// Seed the SSO manager with a default SSO provider.
if (isSsoEnabled(_configs)) {
SsoConfigs ssoConfigs = new SsoConfigs(_configs);
if (ssoConfigs.isOidcEnabled()) {
// Register OIDC Provider, add to list of managers.
OidcConfigs oidcConfigs = new OidcConfigs(_configs);
OidcProvider oidcProvider = new OidcProvider(oidcConfigs);
// Set the default SSO provider to this OIDC client.
manager.setSsoProvider(oidcProvider);
}
}
protected SsoManager provideSsoManager(
Authentication systemAuthentication, CloseableHttpClient httpClient) {
SsoManager manager =
new SsoManager(
_configs, systemAuthentication, getSsoSettingsRequestUrl(_configs), httpClient);
manager.initializeSsoProvider();
return manager;
}

Expand Down Expand Up @@ -191,33 +173,16 @@ protected SystemEntityClient provideEntityClient(
configurationProvider.getCache().getClient().getEntityClient());
}

@Provides
@Singleton
protected CloseableHttpClient provideHttpClient() {
return HttpClients.createDefault();
}

@Provides
@Singleton
protected AuthServiceClient provideAuthClient(
Authentication systemAuthentication, CloseableHttpClient httpClient) {
// Init a GMS auth client
final String metadataServiceHost =
_configs.hasPath(METADATA_SERVICE_HOST_CONFIG_PATH)
? _configs.getString(METADATA_SERVICE_HOST_CONFIG_PATH)
: Configuration.getEnvironmentVariable(GMS_HOST_ENV_VAR, DEFAULT_GMS_HOST);
final String metadataServiceHost = getMetadataServiceHost(_configs);

final int metadataServicePort =
_configs.hasPath(METADATA_SERVICE_PORT_CONFIG_PATH)
? _configs.getInt(METADATA_SERVICE_PORT_CONFIG_PATH)
: Integer.parseInt(
Configuration.getEnvironmentVariable(GMS_PORT_ENV_VAR, DEFAULT_GMS_PORT));
final int metadataServicePort = getMetadataServicePort(_configs);

final Boolean metadataServiceUseSsl =
_configs.hasPath(METADATA_SERVICE_USE_SSL_CONFIG_PATH)
? _configs.getBoolean(METADATA_SERVICE_USE_SSL_CONFIG_PATH)
: Boolean.parseBoolean(
Configuration.getEnvironmentVariable(GMS_USE_SSL_ENV_VAR, DEFAULT_GMS_USE_SSL));
final boolean metadataServiceUseSsl = doesMetadataServiceUseSsl(_configs);

return new AuthServiceClient(
metadataServiceHost,
Expand All @@ -227,6 +192,12 @@ protected AuthServiceClient provideAuthClient(
httpClient);
}

@Provides
@Singleton
protected CloseableHttpClient provideHttpClient() {
return HttpClients.createDefault();
}

private com.linkedin.restli.client.Client buildRestliClient() {
final String metadataServiceHost =
utils.ConfigUtil.getString(
Expand Down Expand Up @@ -255,16 +226,33 @@ private com.linkedin.restli.client.Client buildRestliClient() {
metadataServiceSslProtocol);
}

protected boolean isSsoEnabled(com.typesafe.config.Config configs) {
// If OIDC is enabled, we infer SSO to be enabled.
return configs.hasPath(OIDC_ENABLED_CONFIG_PATH)
&& Boolean.TRUE.equals(Boolean.parseBoolean(configs.getString(OIDC_ENABLED_CONFIG_PATH)));
protected boolean doesMetadataServiceUseSsl(com.typesafe.config.Config configs) {
return configs.hasPath(METADATA_SERVICE_USE_SSL_CONFIG_PATH)
? configs.getBoolean(METADATA_SERVICE_USE_SSL_CONFIG_PATH)
: Boolean.parseBoolean(
Configuration.getEnvironmentVariable(GMS_USE_SSL_ENV_VAR, DEFAULT_GMS_USE_SSL));
}

protected boolean isMetadataServiceAuthEnabled(com.typesafe.config.Config configs) {
// If OIDC is enabled, we infer SSO to be enabled.
return configs.hasPath(METADATA_SERVICE_AUTH_ENABLED_CONFIG_PATH)
&& Boolean.TRUE.equals(
Boolean.parseBoolean(configs.getString(METADATA_SERVICE_AUTH_ENABLED_CONFIG_PATH)));
protected String getMetadataServiceHost(com.typesafe.config.Config configs) {
return configs.hasPath(METADATA_SERVICE_HOST_CONFIG_PATH)
? configs.getString(METADATA_SERVICE_HOST_CONFIG_PATH)
: Configuration.getEnvironmentVariable(GMS_HOST_ENV_VAR, DEFAULT_GMS_HOST);
}

protected Integer getMetadataServicePort(com.typesafe.config.Config configs) {
return configs.hasPath(METADATA_SERVICE_PORT_CONFIG_PATH)
? configs.getInt(METADATA_SERVICE_PORT_CONFIG_PATH)
: Integer.parseInt(
Configuration.getEnvironmentVariable(GMS_PORT_ENV_VAR, DEFAULT_GMS_PORT));
}

protected String getSsoSettingsRequestUrl(com.typesafe.config.Config configs) {
final String protocol = doesMetadataServiceUseSsl(configs) ? "https" : "http";
final String metadataServiceHost = getMetadataServiceHost(configs);
final Integer metadataServicePort = getMetadataServicePort(configs);

return String.format(
"%s://%s:%s/%s",
protocol, metadataServiceHost, metadataServicePort, GET_SSO_SETTINGS_ENDPOINT);
}
}
20 changes: 20 additions & 0 deletions datahub-frontend/app/auth/AuthUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,26 @@ public class AuthUtils {
public static final String TITLE = "title";
public static final String INVITE_TOKEN = "inviteToken";
public static final String RESET_TOKEN = "resetToken";
public static final String BASE_URL = "baseUrl";
public static final String OIDC_ENABLED = "oidcEnabled";
public static final String CLIENT_ID = "clientId";
public static final String CLIENT_SECRET = "clientSecret";
public static final String DISCOVERY_URI = "discoveryUri";

public static final String USER_NAME_CLAIM = "userNameClaim";
public static final String USER_NAME_CLAIM_REGEX = "userNameClaimRegex";
public static final String SCOPE = "scope";
public static final String CLIENT_NAME = "clientName";
public static final String CLIENT_AUTHENTICATION_METHOD = "clientAuthenticationMethod";
public static final String JIT_PROVISIONING_ENABLED = "jitProvisioningEnabled";
public static final String PRE_PROVISIONING_REQUIRED = "preProvisioningRequired";
public static final String EXTRACT_GROUPS_ENABLED = "extractGroupsEnabled";
public static final String GROUPS_CLAIM = "groupsClaim";
public static final String RESPONSE_TYPE = "responseType";
public static final String RESPONSE_MODE = "responseMode";
public static final String USE_NONCE = "useNonce";
public static final String READ_TIMEOUT = "readTimeout";
public static final String EXTRACT_JWT_ACCESS_TOKEN_CLAIMS = "extractJwtAccessTokenClaims";

/**
* Determines whether the inbound request should be forward to downstream Metadata Service. Today,
Expand Down
75 changes: 63 additions & 12 deletions datahub-frontend/app/auth/sso/SsoConfigs.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package auth.sso;

import static auth.ConfigUtil.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

/** Class responsible for extracting and validating top-level SSO related configurations. */
import static auth.AuthUtils.*;


/**
* Class responsible for extracting and validating top-level SSO related configurations. TODO:
* Refactor SsoConfigs to have OidcConfigs and other identity provider specific configs as instance
* variables. SSoManager should ideally not know about identity provider specific configs.
*/
public class SsoConfigs {

/** Required configs */
Expand All @@ -22,16 +30,11 @@ public class SsoConfigs {
private final String _authSuccessRedirectPath;
private final Boolean _oidcEnabled;

public SsoConfigs(final com.typesafe.config.Config configs) {
_authBaseUrl = getRequired(configs, AUTH_BASE_URL_CONFIG_PATH);
_authBaseCallbackPath =
getOptional(configs, AUTH_BASE_CALLBACK_PATH_CONFIG_PATH, DEFAULT_BASE_CALLBACK_PATH);
_authSuccessRedirectPath =
getOptional(configs, AUTH_SUCCESS_REDIRECT_PATH_CONFIG_PATH, DEFAULT_SUCCESS_REDIRECT_PATH);
_oidcEnabled =
configs.hasPath(OIDC_ENABLED_CONFIG_PATH)
&& Boolean.TRUE.equals(
Boolean.parseBoolean(configs.getString(OIDC_ENABLED_CONFIG_PATH)));
public SsoConfigs(Builder<?> builder) {
_authBaseUrl = builder._authBaseUrl;
_authBaseCallbackPath = builder._authBaseCallbackPath;
_authSuccessRedirectPath = builder._authSuccessRedirectPath;
_oidcEnabled = builder._oidcEnabled;
}

public String getAuthBaseUrl() {
Expand All @@ -49,4 +52,52 @@ public String getAuthSuccessRedirectPath() {
public Boolean isOidcEnabled() {
return _oidcEnabled;
}

public static class Builder<T extends Builder<T>> {
protected String _authBaseUrl = null;
private String _authBaseCallbackPath = DEFAULT_BASE_CALLBACK_PATH;
private String _authSuccessRedirectPath = DEFAULT_SUCCESS_REDIRECT_PATH;
protected Boolean _oidcEnabled = false;
private final ObjectMapper _objectMapper = new ObjectMapper();
protected JsonNode jsonNode = null;

// No need to check if changes are made since this method is only called at start-up.
public Builder from(final com.typesafe.config.Config configs) {
if (configs.hasPath(AUTH_BASE_URL_CONFIG_PATH)) {
_authBaseUrl = configs.getString(AUTH_BASE_URL_CONFIG_PATH);
}
if (configs.hasPath(AUTH_BASE_CALLBACK_PATH_CONFIG_PATH)) {
_authBaseCallbackPath = configs.getString(AUTH_BASE_CALLBACK_PATH_CONFIG_PATH);
}
if (configs.hasPath(OIDC_ENABLED_CONFIG_PATH)) {
_oidcEnabled =
Boolean.TRUE.equals(Boolean.parseBoolean(configs.getString(OIDC_ENABLED_CONFIG_PATH)));
}
if (configs.hasPath(AUTH_SUCCESS_REDIRECT_PATH_CONFIG_PATH)) {
_authSuccessRedirectPath = configs.getString(AUTH_SUCCESS_REDIRECT_PATH_CONFIG_PATH);
}
return this;
}

public Builder from(String ssoSettingsJsonStr) {
try {
jsonNode = _objectMapper.readTree(ssoSettingsJsonStr);
} catch (Exception e) {
throw new RuntimeException(
String.format("Failed to parse ssoSettingsJsonStr %s into JSON", ssoSettingsJsonStr));
}
if (jsonNode.has(BASE_URL)) {
_authBaseUrl = jsonNode.get(BASE_URL).asText();
}
if (jsonNode.has(OIDC_ENABLED)) {
_oidcEnabled = jsonNode.get(OIDC_ENABLED).asBoolean();
}

return this;
}

public SsoConfigs build() {
return new SsoConfigs(this);
}
}
}
Loading
Loading