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

Add ability to use internal network for keycloak. #18225

Merged
merged 3 commits into from
Nov 26, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ che.infra.openshift.oauth_identity_provider=NULL
# is used
che.keycloak.auth_server_url=http://${CHE_HOST}:5050/auth

# Internal network service Url to keycloak identity provider server
che.keycloak.auth_internal_server_url=NULL

# Keycloak realm is used to authenticate users
# Can be set to NULL only if `che.keycloak.oidcProvider`
# is used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public IdentityProviderConfigFactory(
+ "</strong> \n"
+ "identity provider by visiting the "
+ "<a href='"
// Here should be used public url. User should have it to make manual actions in the
// browser.
+ keycloakSettings.get().get(AUTH_SERVER_URL_SETTING)
+ "/realms/"
+ keycloakSettings.get().get(REALM_SETTING)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ public class KeycloakJwkProvider implements Provider<JwkProvider> {

@Inject
public KeycloakJwkProvider(KeycloakSettings keycloakSettings) throws MalformedURLException {
final String jwksUrl = keycloakSettings.get().get(KeycloakConstants.JWKS_ENDPOINT_SETTING);

final String jwksUrl =
keycloakSettings.getInternalSettings().get(KeycloakConstants.JWKS_ENDPOINT_SETTING);

if (jwksUrl == null) {
throw new ConfigurationException("Jwks endpoint url not found in keycloak settings");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public KeycloakProfileRetriever(
KeycloakSettings keycloakSettings, HttpJsonRequestFactory requestFactory) {
this.requestFactory = requestFactory;
this.keyclockCurrentUserInfoUrl =
keycloakSettings.get().get(KeycloakConstants.USERINFO_ENDPOINT_SETTING);
keycloakSettings.getInternalSettings().get(KeycloakConstants.USERINFO_ENDPOINT_SETTING);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
package org.eclipse.che.multiuser.keycloak.server;

import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_INTERNAL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.REALM_SETTING;

import com.google.common.io.CharStreams;
Expand Down Expand Up @@ -101,7 +101,8 @@ public String getAccountLinkingURL(
byte[] check = md.digest(input.getBytes(StandardCharsets.UTF_8));
final String hash = Base64.getUrlEncoder().encodeToString(check);

return UriBuilder.fromUri(keycloakSettings.get().get(AUTH_SERVER_URL_SETTING))
return UriBuilder.fromUri(
keycloakSettings.getInternalSettings().get(AUTH_SERVER_URL_INTERNAL_SETTING))
.path("/realms/{realm}/broker/{provider}/link")
.queryParam("nonce", nonce)
.queryParam("hash", hash)
Expand All @@ -127,7 +128,8 @@ public KeycloakTokenResponse getIdentityProviderToken(String oauthProvider)
throws ForbiddenException, BadRequestException, IOException, NotFoundException,
ServerException, UnauthorizedException {
String url =
UriBuilder.fromUri(keycloakSettings.get().get(AUTH_SERVER_URL_SETTING))
UriBuilder.fromUri(
keycloakSettings.getInternalSettings().get(AUTH_SERVER_URL_INTERNAL_SETTING))
.path("/realms/{realm}/broker/{provider}/token")
.build(keycloakSettings.get().get(REALM_SETTING), oauthProvider)
.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
*/
package org.eclipse.che.multiuser.keycloak.server;

import static com.google.common.base.MoreObjects.firstNonNull;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_INTERNAL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.CLIENT_ID_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.FIXED_REDIRECT_URL_FOR_DASHBOARD;
Expand Down Expand Up @@ -54,13 +56,26 @@ public class KeycloakSettings {
private static final Logger LOG = LoggerFactory.getLogger(KeycloakSettings.class);
private static final String DEFAULT_USERNAME_CLAIM = "preferred_username";

/**
* Public Keycloak connection settings. It contains information about keycloak api urls and
* information required to make Keycloak connection using public domain hostname. This info will
* be shared with frontend.
*/
private final Map<String, String> settings;
/**
* Internal network Keycloak connection settings. It contains information about keycloak api urls
* and information required to make connection using k8s/openshift internal services hostname.
* This info will be used only on the Che server side. If using internal network is disabled, then
* will be included settings with public domain hostname.
*/
private final Map<String, String> internalSettings;
AndrienkoAleksandr marked this conversation as resolved.
Show resolved Hide resolved

@Inject
public KeycloakSettings(
@Named("che.api") String cheServerEndpoint,
@Nullable @Named(JS_ADAPTER_URL_SETTING) String jsAdapterUrl,
@Nullable @Named(AUTH_SERVER_URL_SETTING) String serverURL,
@Nullable @Named(AUTH_SERVER_URL_INTERNAL_SETTING) String serverInternalURL,
@Nullable @Named(REALM_SETTING) String realm,
@Named(CLIENT_ID_SETTING) String clientId,
@Nullable @Named(OIDC_PROVIDER_SETTING) String oidcProvider,
Expand All @@ -70,10 +85,14 @@ public KeycloakSettings(
@Nullable @Named(GITHUB_ENDPOINT_SETTING) String gitHubEndpoint,
@Named(USE_FIXED_REDIRECT_URLS_SETTING) boolean useFixedRedirectUrls) {

serverInternalURL = firstNonNull(serverInternalURL, serverURL);

if (serverURL == null && oidcProvider == null) {
throw new RuntimeException(
"Either the '"
+ AUTH_SERVER_URL_SETTING
+ "'or'"
+ AUTH_SERVER_URL_INTERNAL_SETTING
+ "' or '"
+ OIDC_PROVIDER_SETTING
+ "' property should be set");
Expand All @@ -83,7 +102,7 @@ public KeycloakSettings(
throw new RuntimeException("The '" + REALM_SETTING + "' property should be set");
}

String wellKnownEndpoint = oidcProvider != null ? oidcProvider : serverURL + "/realms/" + realm;
String wellKnownEndpoint = firstNonNull(oidcProvider, serverInternalURL + "/realms/" + realm);
if (!wellKnownEndpoint.endsWith("/")) {
wellKnownEndpoint = wellKnownEndpoint + "/";
}
Expand All @@ -109,10 +128,16 @@ public KeycloakSettings(
LOG.info("openid configuration = {}", openIdConfiguration);

Map<String, String> settings = Maps.newHashMap();
Map<String, String> internalSettings = Maps.newHashMap();
settings.put(
USERNAME_CLAIM_SETTING, usernameClaim == null ? DEFAULT_USERNAME_CLAIM : usernameClaim);
settings.put(CLIENT_ID_SETTING, clientId);
settings.put(REALM_SETTING, realm);

if (serverInternalURL != null) {
skabashnyuk marked this conversation as resolved.
Show resolved Hide resolved
internalSettings.put(AUTH_SERVER_URL_INTERNAL_SETTING, serverInternalURL);
}

if (serverURL != null) {
settings.put(AUTH_SERVER_URL_SETTING, serverURL);
settings.put(PROFILE_ENDPOINT_SETTING, serverURL + "/realms/" + realm + "/account");
Expand All @@ -132,14 +157,24 @@ public KeycloakSettings(
if (tokenEndpoint != null) {
settings.put(TOKEN_ENDPOINT_SETTING, tokenEndpoint);
}

String userInfoEndpoint = (String) openIdConfiguration.get("userinfo_endpoint");
if (userInfoEndpoint != null) {
settings.put(USERINFO_ENDPOINT_SETTING, userInfoEndpoint);
if (serverURL != null) {
String internalInfoEndpoint = userInfoEndpoint.replace(serverURL, serverInternalURL);
internalSettings.put(USERINFO_ENDPOINT_SETTING, internalInfoEndpoint);
}
}
String jwksUriEndpoint = (String) openIdConfiguration.get("jwks_uri");
if (jwksUriEndpoint != null) {
settings.put(JWKS_ENDPOINT_SETTING, jwksUriEndpoint);
if (serverURL != null) {
String internalJwksUriEndpoint = jwksUriEndpoint.replace(serverURL, serverInternalURL);
internalSettings.put(JWKS_ENDPOINT_SETTING, internalJwksUriEndpoint);
}
}

settings.put(OSO_ENDPOINT_SETTING, osoEndpoint);
settings.put(GITHUB_ENDPOINT_SETTING, gitHubEndpoint);

Expand All @@ -161,9 +196,14 @@ public KeycloakSettings(
settings.put(JS_ADAPTER_URL_SETTING, jsAdapterUrl);

this.settings = Collections.unmodifiableMap(settings);
this.internalSettings = Collections.unmodifiableMap(internalSettings);
}

public Map<String, String> get() {
return settings;
}

public Map<String, String> getInternalSettings() {
return internalSettings;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import org.eclipse.che.multiuser.keycloak.server.KeycloakProfileRetriever;

/**
* Fetches user profile from Keycloack server.
* Fetches user profile from Keycloak server.
*
* @author Max Shaposhnik (mshaposh@redhat.com)
* @author Sergii Leshchenko
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.eclipse.che.dto.server.DtoFactory.newDto;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_INTERNAL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.REALM_SETTING;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
Expand Down Expand Up @@ -67,10 +67,12 @@ public class KeycloakServiceClientTest {
public void setUp() throws Exception {
keycloakServiceClient = new KeycloakServiceClient(keycloakSettings, jwtParser);
Map<String, String> conf = new HashMap<>();
conf.put(
AUTH_SERVER_URL_SETTING,
Map<String, String> confInternal = new HashMap<>();
confInternal.put(
AUTH_SERVER_URL_INTERNAL_SETTING,
RestAssured.baseURI + ":" + RestAssured.port + RestAssured.basePath);
conf.put(REALM_SETTING, "che");
when(keycloakSettings.getInternalSettings()).thenReturn(confInternal);
when(keycloakSettings.get()).thenReturn(conf);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class KeycloakConstants {
private static final String KEYCLOAK_SETTINGS_ENDPOINT_PATH = "/keycloak/settings";

public static final String AUTH_SERVER_URL_SETTING = KEYCLOAK_SETTING_PREFIX + "auth_server_url";
public static final String AUTH_SERVER_URL_INTERNAL_SETTING =
KEYCLOAK_SETTING_PREFIX + "auth_internal_server_url";

public static final String REALM_SETTING = KEYCLOAK_SETTING_PREFIX + "realm";
public static final String CLIENT_ID_SETTING = KEYCLOAK_SETTING_PREFIX + "client_id";
public static final String OIDC_PROVIDER_SETTING = KEYCLOAK_SETTING_PREFIX + "oidc_provider";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@

import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.ws.rs.HttpMethod.POST;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.AUTH_SERVER_URL_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.REALM_SETTING;
import static org.eclipse.che.multiuser.keycloak.shared.KeycloakConstants.*;

import com.google.common.base.Strings;
import com.google.gson.JsonElement;
Expand Down Expand Up @@ -76,9 +75,14 @@ public KeycloakUserRemover(
this.keycloakPassword = keycloakPassword;
this.requestFactory = requestFactory;
if (userRemovalEnabled) {
String serverUrl = keycloakSettings.get().get(AUTH_SERVER_URL_SETTING);
String serverUrl =
keycloakSettings.getInternalSettings().get(AUTH_SERVER_URL_INTERNAL_SETTING);
if (serverUrl == null) {
throw new ConfigurationException(AUTH_SERVER_URL_SETTING + " is not configured");
throw new ConfigurationException(
AUTH_SERVER_URL_SETTING
+ " or "
+ AUTH_SERVER_URL_INTERNAL_SETTING
+ " is not configured");
}
String realm = keycloakSettings.get().get(REALM_SETTING);
if (realm == null) {
Expand Down