Delete OpenShift 3.x identity provider (#34331)

Closes #34330

Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
Stian Thorgersen 2024-12-06 11:24:47 +01:00 committed by GitHub
parent dfb2735edc
commit 5bc4ab1429
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 5 additions and 274 deletions

View File

@ -21,7 +21,7 @@ endif::[]
= Option to create certificates for generated EC keys
A new option, `Generate certificate`, exists for EC-DSA and Ed-DSA key providers. When the generated key is created by a realm administrator, a
A new option, `Generate certificate`, exists for EC-DSA and Ed-DSA key providers. When the generated key is created by a realm administrator, a
certificate might be generated for this key. The certificate information is available in the Admin Console and in the JWK representation of this key, which is available
from JWKS endpoint with the realm keys.
@ -53,4 +53,6 @@ by the LDAP provider.
For information on how to migrate, see the link:{upgradingguide_link}[{upgradingguide_name}], and the https://www.keycloak.org/server/caching[Configuring distributed caches] guide.
= OpenShift v3 identity brokering removed
As OpenShift v3 reached end-of-life a while back, support for identity brokering with OpenShift v3 has been removed from Keycloak.

View File

@ -22,7 +22,7 @@ When you configure an identity provider, the identity provider appears on the {p
image:images/identity-provider-login-page.png[]
Social::
Social providers enable social authentication in your realm. With {project_name}, users can log in to your application using a social network account. Supported providers include Twitter, Facebook, Google, LinkedIn, Instagram, Microsoft, PayPal, Openshift v3, GitHub, GitLab, Bitbucket, and Stack Overflow.
Social providers enable social authentication in your realm. With {project_name}, users can log in to your application using a social network account. Supported providers include Twitter, Facebook, Google, LinkedIn, Instagram, Microsoft, PayPal, Openshift v4, GitHub, GitLab, Bitbucket, and Stack Overflow.
Protocol-based::
Protocol-based providers rely on specific protocols to authenticate and authorize users. Using these providers, you can connect to any identity provider compliant with a specific protocol. {project_name} provides support for SAML v2.0 and OpenID Connect v1.0 protocols. You can configure and broker any identity provider based on these open standards.

View File

@ -1,40 +1,3 @@
==== OpenShift 3
.Procedure
. Click *Identity Providers* in the menu.
. From the *Add provider* list, select *Openshift v3*.
+
.Add identity provider
image:images/openshift-add-identity-provider.png[Add Identity Provider]
+
. Copy the value of *Redirect URI* to your clipboard.
. Register your client using the `oc` command-line tool.
+
[source,subs="attributes+"]
----
$ oc create -f <(echo '
kind: OAuthClient
apiVersion: v1
metadata:
name: kc-client <1>
secret: "..." <2>
redirectURIs:
- "http://www.example.com/" <3>
grantMethod: prompt <4>
')
----
<1> The `name` of your OAuth client. Passed as `client_id` request parameter when making requests to `_<openshift_master>_/oauth/authorize` and `_<openshift_master>_/oauth/token`.
<2> The `secret` {project_name} uses for the `client_secret` request parameter.
<3> The `redirect_uri` parameter specified in requests to `_<openshift_master>_/oauth/authorize` and `_<openshift_master>_/oauth/token` must be equal to (or prefixed by) one of the URIs in `redirectURIs`. You can obtain this from the *Redirect URI* field in the Identity Provider screen
<4> The `grantMethod` {project_name} uses to determine the action when this client requests tokens but has not been granted access by the user.
+
. In {project_name}, paste the value of the *Client ID* into the *Client ID* field.
. In {project_name}, paste the value of the *Client Secret* into the *Client Secret* field.
. Click *Add*.
==== OpenShift 4
.Prerequisites

View File

@ -88,11 +88,6 @@ describe("Identity provider test", () => {
alias: "linkedin-openid-connect",
},
{ testName: "Microsoft", displayName: "Microsoft", alias: "microsoft" },
{
testName: "Openshift-v3",
displayName: "Openshift v3",
alias: "openshift-v3",
},
{
testName: "Openshift-v4",
displayName: "Openshift v4",

View File

@ -297,11 +297,6 @@
"name":"Openshift v4",
"id":"openshift-v4"
},
{
"groupName":"Social",
"name":"Openshift v3",
"id":"openshift-v3"
},
{
"groupName":"Social",
"name":"GitLab",
@ -379,11 +374,6 @@
"name":"Openshift v4",
"id":"openshift-v4"
},
{
"groupName":"Social",
"name":"Openshift v3",
"id":"openshift-v3"
},
{
"groupName":"Social",
"name":"GitLab",
@ -1587,9 +1577,6 @@
"openshift-v4":{
"order":0
},
"openshift-v3":{
"order":0
},
"gitlab":{
"order":0
},

View File

@ -291,7 +291,6 @@
{ "groupName": "Social", "name": "BitBucket", "id": "bitbucket" },
{ "groupName": "Social", "name": "Twitter", "id": "twitter" },
{ "groupName": "Social", "name": "Openshift v4", "id": "openshift-v4" },
{ "groupName": "Social", "name": "Openshift v3", "id": "openshift-v3" },
{ "groupName": "Social", "name": "GitLab", "id": "gitlab" },
{ "groupName": "Social", "name": "PayPal", "id": "paypal" },
{ "groupName": "Social", "name": "StackOverflow", "id": "stackoverflow" }
@ -317,7 +316,6 @@
{ "groupName": "Social", "name": "BitBucket", "id": "bitbucket" },
{ "groupName": "Social", "name": "Twitter", "id": "twitter" },
{ "groupName": "Social", "name": "Openshift v4", "id": "openshift-v4" },
{ "groupName": "Social", "name": "Openshift v3", "id": "openshift-v3" },
{ "groupName": "Social", "name": "GitLab", "id": "gitlab" },
{ "groupName": "Social", "name": "PayPal", "id": "paypal" },
{ "groupName": "Social", "name": "StackOverflow", "id": "stackoverflow" }
@ -956,7 +954,6 @@
"microsoft": { "order": 0 },
"twitter": { "order": 0 },
"openshift-v4": { "order": 0 },
"openshift-v3": { "order": 0 },
"gitlab": { "order": 0 },
"paypal": { "order": 0 },
"stackoverflow": { "order": 0 }

View File

@ -42,7 +42,6 @@ function getIcon(icon: string) {
case "linkedin-openid-connect":
return LinkedinIcon;
case "openshift-v3":
case "openshift-v4":
return OpenshiftIcon;
case "stackoverflow":

View File

@ -36,7 +36,6 @@ import org.keycloak.social.google.GoogleIdentityProviderFactory;
import org.keycloak.social.instagram.InstagramIdentityProviderFactory;
import org.keycloak.social.linkedin.LinkedInOIDCIdentityProviderFactory;
import org.keycloak.social.microsoft.MicrosoftIdentityProviderFactory;
import org.keycloak.social.openshift.OpenshiftV3IdentityProviderFactory;
import org.keycloak.social.openshift.OpenshiftV4IdentityProviderFactory;
import org.keycloak.social.paypal.PayPalIdentityProviderFactory;
import org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory;
@ -74,7 +73,6 @@ public class UsernameTemplateMapper extends AbstractClaimMapper {
InstagramIdentityProviderFactory.PROVIDER_ID,
LinkedInOIDCIdentityProviderFactory.PROVIDER_ID,
MicrosoftIdentityProviderFactory.PROVIDER_ID,
OpenshiftV3IdentityProviderFactory.PROVIDER_ID,
OpenshiftV4IdentityProviderFactory.PROVIDER_ID,
PayPalIdentityProviderFactory.PROVIDER_ID,
StackoverflowIdentityProviderFactory.PROVIDER_ID,

View File

@ -1,91 +0,0 @@
package org.keycloak.social.openshift;
import com.fasterxml.jackson.databind.JsonNode;
import org.keycloak.OAuthErrorException;
import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.IdentityBrokerException;
import org.keycloak.broker.provider.util.SimpleHttp;
import org.keycloak.broker.social.SocialIdentityProvider;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.models.KeycloakSession;
import org.keycloak.services.ErrorResponseException;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.Optional;
/**
* Identity provider for Openshift V3. Check <a href="https://docs.openshift.com/enterprise/3.0/architecture/additional_concepts/authentication.html">official documentation</a> for more details.
*/
public class OpenshiftV3IdentityProvider extends AbstractOAuth2IdentityProvider<OpenshiftV3IdentityProviderConfig> implements SocialIdentityProvider<OpenshiftV3IdentityProviderConfig> {
public static final String BASE_URL = "https://api.preview.openshift.com";
private static final String AUTH_RESOURCE = "/oauth/authorize";
private static final String TOKEN_RESOURCE = "/oauth/token";
private static final String PROFILE_RESOURCE = "/oapi/v1/users/~";
private static final String DEFAULT_SCOPE = "user:info";
public OpenshiftV3IdentityProvider(KeycloakSession session, OpenshiftV3IdentityProviderConfig config) {
super(session, config);
final String baseUrl = Optional.ofNullable(config.getBaseUrl()).orElse(BASE_URL);
config.setAuthorizationUrl(baseUrl + AUTH_RESOURCE);
config.setTokenUrl(baseUrl + TOKEN_RESOURCE);
config.setUserInfoUrl(baseUrl + PROFILE_RESOURCE);
}
@Override
protected String getDefaultScopes() {
return DEFAULT_SCOPE;
}
@Override
protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
try {
final JsonNode profile = fetchProfile(accessToken);
final BrokeredIdentityContext user = extractUserContext(profile);
AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
return user;
} catch (Exception e) {
throw new IdentityBrokerException("Could not obtain user profile from Openshift.", e);
}
}
private BrokeredIdentityContext extractUserContext(JsonNode profile) {
JsonNode metadata = profile.get("metadata");
final BrokeredIdentityContext user = new BrokeredIdentityContext(getJsonProperty(metadata, "uid"), getConfig());
user.setUsername(getJsonProperty(metadata, "name"));
user.setName(getJsonProperty(profile, "fullName"));
user.setIdp(this);
return user;
}
private JsonNode fetchProfile(String accessToken) throws IOException {
return SimpleHttp.doGet(getConfig().getUserInfoUrl(), this.session)
.header("Authorization", "Bearer " + accessToken)
.asJson();
}
@Override
protected boolean supportsExternalExchange() {
return true;
}
@Override
protected String getProfileEndpointForValidation(EventBuilder event) {
return getConfig().getUserInfoUrl();
}
@Override
protected BrokeredIdentityContext extractIdentityFromProfile(EventBuilder event, JsonNode profile) {
final BrokeredIdentityContext user = extractUserContext(profile);
AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
return user;
}
}

View File

@ -1,31 +0,0 @@
package org.keycloak.social.openshift;
import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
import org.keycloak.models.IdentityProviderModel;
public class OpenshiftV3IdentityProviderConfig extends OAuth2IdentityProviderConfig {
private static final String BASE_URL = "baseUrl";
public OpenshiftV3IdentityProviderConfig(IdentityProviderModel identityProviderModel) {
super(identityProviderModel);
}
public OpenshiftV3IdentityProviderConfig() {
}
public String getBaseUrl() {
return getConfig().get(BASE_URL);
}
public void setBaseUrl(String baseUrl) {
getConfig().put(BASE_URL, trimTrailingSlash(baseUrl));
}
private String trimTrailingSlash(String baseUrl) {
if (baseUrl != null && baseUrl.endsWith("/")) {
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
}
return baseUrl;
}
}

View File

@ -1,39 +0,0 @@
package org.keycloak.social.openshift;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.broker.social.SocialIdentityProviderFactory;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.provider.ProviderConfigProperty;
import java.util.List;
public class OpenshiftV3IdentityProviderFactory extends AbstractIdentityProviderFactory<OpenshiftV3IdentityProvider> implements SocialIdentityProviderFactory<OpenshiftV3IdentityProvider> {
public static final String PROVIDER_ID = "openshift-v3";
@Override
public String getName() {
return "Openshift v3";
}
@Override
public OpenshiftV3IdentityProvider create(KeycloakSession keycloakSession, IdentityProviderModel identityProviderModel) {
return new OpenshiftV3IdentityProvider(keycloakSession, new OpenshiftV3IdentityProviderConfig(identityProviderModel));
}
@Override
public OpenshiftV3IdentityProviderConfig createConfig() {
return new OpenshiftV3IdentityProviderConfig();
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return OpenshiftV4IdentityProviderConfig.getConfigProperties();
}
}

View File

@ -23,7 +23,6 @@ org.keycloak.social.linkedin.LinkedInOIDCIdentityProviderFactory
org.keycloak.social.stackoverflow.StackoverflowIdentityProviderFactory
org.keycloak.social.twitter.TwitterIdentityProviderFactory
org.keycloak.social.microsoft.MicrosoftIdentityProviderFactory
org.keycloak.social.openshift.OpenshiftV3IdentityProviderFactory
org.keycloak.social.openshift.OpenshiftV4IdentityProviderFactory
org.keycloak.social.gitlab.GitLabIdentityProviderFactory
org.keycloak.social.bitbucket.BitbucketIdentityProviderFactory

View File

@ -1,33 +0,0 @@
package org.keycloak.social.openshift;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.models.IdentityProviderModel;
public class OpenshiftV3IdentityProviderTest {
@Test
public void shouldConstructProviderUrls() {
final OpenshiftV3IdentityProviderConfig config = new OpenshiftV3IdentityProviderConfig(new IdentityProviderModel());
config.setBaseUrl("http://openshift.io:8443");
final OpenshiftV3IdentityProvider openshiftV3IdentityProvider = new OpenshiftV3IdentityProvider(null, config);
assertConfiguredUrls(openshiftV3IdentityProvider);
}
@Test
public void shouldConstructProviderUrlsForBaseUrlWithTrailingSlash() {
final OpenshiftV3IdentityProviderConfig config = new OpenshiftV3IdentityProviderConfig(new IdentityProviderModel());
config.setBaseUrl("http://openshift.io:8443/");
final OpenshiftV3IdentityProvider openshiftV3IdentityProvider = new OpenshiftV3IdentityProvider(null, config);
assertConfiguredUrls(openshiftV3IdentityProvider);
}
private void assertConfiguredUrls(OpenshiftV3IdentityProvider openshiftV3IdentityProvider) {
Assert.assertEquals("http://openshift.io:8443/oauth/authorize", openshiftV3IdentityProvider.getConfig().getAuthorizationUrl());
Assert.assertEquals("http://openshift.io:8443/oauth/token", openshiftV3IdentityProvider.getConfig().getTokenUrl());
Assert.assertEquals("http://openshift.io:8443/oapi/v1/users/~", openshiftV3IdentityProvider.getConfig().getUserInfoUrl());
}
}

View File

@ -86,7 +86,6 @@ import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.INSTAGRAM;
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_SINGLE_TENANT;
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_KUBE_ADMIN;
import static org.keycloak.testsuite.broker.SocialLoginTest.Provider.PAYPAL;
@ -131,7 +130,6 @@ public class SocialLoginTest extends AbstractKeycloakTest {
MICROSOFT_SINGLE_TENANT("microsoft", "microsoft-single-tenant", MicrosoftLoginPage.class),
PAYPAL("paypal", PayPalLoginPage.class),
STACKOVERFLOW("stackoverflow", StackOverflowLoginPage.class),
OPENSHIFT("openshift-v3", OpenShiftLoginPage.class),
OPENSHIFT4("openshift-v4", OpenShiftLoginPage.class),
OPENSHIFT4_KUBE_ADMIN("openshift-v4", "openshift-v4-admin", OpenShiftLoginPage.class),
GITLAB("gitlab", GitLabLoginPage.class),
@ -246,16 +244,6 @@ public class SocialLoginTest extends AbstractKeycloakTest {
});
}
@Test
@UncaughtServerErrorExpected
public void openshiftLogin() {
setTestProvider(OPENSHIFT);
performLogin();
assertUpdateProfile(true, true, true);
appPage.assertCurrent();
testTokenExchange();
}
@Test
@UncaughtServerErrorExpected
public void openshift4Login() {
@ -460,7 +448,7 @@ public class SocialLoginTest extends AbstractKeycloakTest {
if (provider == STACKOVERFLOW) {
idp.getConfig().put("key", getConfig(provider, "clientKey"));
}
if (provider == OPENSHIFT || provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) {
if (provider == OPENSHIFT4 || provider == OPENSHIFT4_KUBE_ADMIN) {
idp.getConfig().put("baseUrl", getConfig(provider, "baseUrl"));
}
if (provider == MICROSOFT_SINGLE_TENANT) {

View File

@ -45,7 +45,6 @@
<path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/>
</svg>
<#break>
<#case "openshift-v3">
<#case "openshift-v4">
<svg viewBox="116 0 100 100" aria-hidden="true">
<title id="title">OpenShift</title>

View File

@ -108,4 +108,3 @@ kcLogoIdP-paypal=
kcLogoIdP-stackoverflow=
kcLogoIdP-twitter=
kcLogoIdP-openshift-v4=
kcLogoIdP-openshift-v3=

View File

@ -150,7 +150,6 @@ kcLogoIdP-paypal=fa fa-paypal
kcLogoIdP-stackoverflow=fa fa-stack-overflow
kcLogoIdP-twitter=fa fa-twitter
kcLogoIdP-openshift-v4=pf-icon pf-icon-openshift
kcLogoIdP-openshift-v3=pf-icon pf-icon-openshift
## Recovery codes
kcRecoveryCodesWarning=kc-recovery-codes-warning