KEYCLOAK-19079 Add special case for kubeadmin without uid and OCP4

This commit is contained in:
Dominik 2021-09-13 17:15:56 +02:00 committed by Pedro Igor
parent 3abf9283a8
commit 97ee8832a3
3 changed files with 56 additions and 4 deletions

View file

@ -3,7 +3,6 @@ package org.keycloak.social.openshift;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider; import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
@ -16,7 +15,6 @@ import org.keycloak.connections.httpclient.HttpClientProvider;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import javax.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
@ -33,6 +31,7 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider<
public static final String OPENSHIFT_OAUTH_METADATA_ENDPOINT = "/.well-known/oauth-authorization-server"; public static final String OPENSHIFT_OAUTH_METADATA_ENDPOINT = "/.well-known/oauth-authorization-server";
public static final String PROFILE_RESOURCE = "/apis/user.openshift.io/v1/users/~"; public static final String PROFILE_RESOURCE = "/apis/user.openshift.io/v1/users/~";
public static final String DEFAULT_SCOPE = "user:info"; public static final String DEFAULT_SCOPE = "user:info";
private static final String KUBEADM_NAME = "kube:admin";
public OpenshiftV4IdentityProvider(KeycloakSession session, OpenshiftV4IdentityProviderConfig config) { public OpenshiftV4IdentityProvider(KeycloakSession session, OpenshiftV4IdentityProviderConfig config) {
super(session, config); super(session, config);
@ -91,7 +90,11 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider<
private BrokeredIdentityContext extractUserContext(JsonNode profile) { private BrokeredIdentityContext extractUserContext(JsonNode profile) {
JsonNode metadata = profile.get("metadata"); JsonNode metadata = profile.get("metadata");
logger.debugv("extractUserContext: metadata = {0}", metadata); logger.debugv("extractUserContext: metadata = {0}", metadata);
final BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(metadata, "uid")); final BrokeredIdentityContext user = new BrokeredIdentityContext(
getJsonProperty(metadata, "uid") != null
? getJsonProperty(metadata, "uid")
: tryGetKubeAdmin(metadata)
);
user.setUsername(getJsonProperty(metadata, "name")); user.setUsername(getJsonProperty(metadata, "name"));
user.setName(getJsonProperty(profile, "fullName")); user.setName(getJsonProperty(profile, "fullName"));
user.setIdpConfig(getConfig()); user.setIdpConfig(getConfig());
@ -99,6 +102,14 @@ public class OpenshiftV4IdentityProvider extends AbstractOAuth2IdentityProvider<
return user; return user;
} }
private String tryGetKubeAdmin(JsonNode metadata) {
String nameProperty = getJsonProperty(metadata, "name");
if(!KUBEADM_NAME.equals(nameProperty)){
return null;
}
return nameProperty;
}
private JsonNode fetchProfile(String accessToken) throws IOException { private JsonNode fetchProfile(String accessToken) throws IOException {
return SimpleHttp.doGet(getConfig().getUserInfoUrl(), this.session) return SimpleHttp.doGet(getConfig().getUserInfoUrl(), this.session)
.header("Authorization", "Bearer " + accessToken) .header("Authorization", "Bearer " + accessToken)

View file

@ -17,10 +17,14 @@
package org.keycloak.testsuite.pages.social; package org.keycloak.testsuite.pages.social;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys; import org.openqa.selenium.Keys;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebElement; import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.FindBy;
import static org.keycloak.testsuite.util.UIUtils.clickLink;
/** /**
* @author Vaclav Muzikar <vmuzikar@redhat.com> * @author Vaclav Muzikar <vmuzikar@redhat.com>
*/ */
@ -31,10 +35,33 @@ public class OpenShiftLoginPage extends AbstractSocialLoginPage {
@FindBy(name = "password") @FindBy(name = "password")
private WebElement passwordInput; private WebElement passwordInput;
private String userLoginLinkTitle;
private WebElement userLoginLink;
@Override @Override
public void login(String user, String password) { public void login(String user, String password) {
if(userLoginLinkTitle != null) {
setUserLoginLink(this.userLoginLinkTitle);
if(this.userLoginLink != null) {
clickLink(this.userLoginLink);
}
}
usernameInput.sendKeys(user); usernameInput.sendKeys(user);
passwordInput.sendKeys(password); passwordInput.sendKeys(password);
passwordInput.sendKeys(Keys.RETURN); passwordInput.sendKeys(Keys.RETURN);
} }
public void setUserLoginLinkTitle(String title) {
this.userLoginLinkTitle = title;
}
private void setUserLoginLink(String linkAttrTitle) {
try {
this.userLoginLink = driver.findElement(By.xpath("//a[contains(@title,'"+linkAttrTitle+"')]"));
} catch (NoSuchElementException ex) {
log.error("No link with title: '" + linkAttrTitle + "' found on page. If you use the OPENSHIFT4_KUBE_ADMIN provider, set property loginBtnTitle in properties file to an existing title on the page to fix this error.");
}
}
} }

View file

@ -88,6 +88,7 @@ import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.LINKEDIN;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.MICROSOFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.MICROSOFT;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.OPENSHIFT4_KUBE_ADMIN;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.PAYPAL; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.PAYPAL;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.STACKOVERFLOW; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.STACKOVERFLOW;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.TWITTER; import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.TWITTER;
@ -129,6 +130,7 @@ public class SocialLoginTest extends AbstractKeycloakTest {
STACKOVERFLOW("stackoverflow", StackOverflowLoginPage.class), STACKOVERFLOW("stackoverflow", StackOverflowLoginPage.class),
OPENSHIFT("openshift-v3", OpenShiftLoginPage.class), OPENSHIFT("openshift-v3", OpenShiftLoginPage.class),
OPENSHIFT4("openshift-v4", OpenShiftLoginPage.class), OPENSHIFT4("openshift-v4", OpenShiftLoginPage.class),
OPENSHIFT4_KUBE_ADMIN("openshift-v4", "openshift-v4-admin", OpenShiftLoginPage.class),
GITLAB("gitlab", GitLabLoginPage.class), GITLAB("gitlab", GitLabLoginPage.class),
BITBUCKET("bitbucket", BitbucketLoginPage.class), BITBUCKET("bitbucket", BitbucketLoginPage.class),
INSTAGRAM("instagram", InstagramLoginPage.class); INSTAGRAM("instagram", InstagramLoginPage.class);
@ -195,6 +197,10 @@ public class SocialLoginTest extends AbstractKeycloakTest {
log.infof("added '%s' identity provider", provider.id()); log.infof("added '%s' identity provider", provider.id());
currentTestProvider = provider; currentTestProvider = provider;
currentSocialLoginPage = Graphene.createPageFragment(currentTestProvider.pageObjectClazz(), driver.findElement(By.tagName("html"))); currentSocialLoginPage = Graphene.createPageFragment(currentTestProvider.pageObjectClazz(), driver.findElement(By.tagName("html")));
if(provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) {
((OpenShiftLoginPage) currentSocialLoginPage).setUserLoginLinkTitle(getConfig(currentTestProvider, "loginBtnTitle"));
}
} }
@Override @Override
@ -255,6 +261,14 @@ public class SocialLoginTest extends AbstractKeycloakTest {
testTokenExchange(); testTokenExchange();
} }
@Test
public void openshift4KubeAdminLogin() {
setTestProvider(OPENSHIFT4_KUBE_ADMIN);
performLogin();
assertUpdateProfile(true, true, true);
assertAccount();
}
@Test @Test
@UncaughtServerErrorExpected @UncaughtServerErrorExpected
public void openshift4LoginWithGroupsMapper() { public void openshift4LoginWithGroupsMapper() {
@ -426,7 +440,7 @@ public class SocialLoginTest extends AbstractKeycloakTest {
if (provider == STACKOVERFLOW) { if (provider == STACKOVERFLOW) {
idp.getConfig().put("key", getConfig(provider, "clientKey")); idp.getConfig().put("key", getConfig(provider, "clientKey"));
} }
if (provider == OPENSHIFT || provider == OPENSHIFT4) { if (provider == OPENSHIFT || provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) {
idp.getConfig().put("baseUrl", getConfig(provider, "baseUrl")); idp.getConfig().put("baseUrl", getConfig(provider, "baseUrl"));
} }
if (provider == PAYPAL) { if (provider == PAYPAL) {