Skip to content

Commit

Permalink
feat: Allow to configure 2 github providers simultaneously (#598)
Browse files Browse the repository at this point in the history
* feat: Support enabling Github enterprise and SaaS simultaneously on Dev Spaces

Signed-off-by: Anatolii Bazko <[email protected]>
  • Loading branch information
tolusha authored Nov 7, 2023
1 parent 2c19833 commit 72f191b
Show file tree
Hide file tree
Showing 44 changed files with 1,529 additions and 879 deletions.
4 changes: 4 additions & 0 deletions assembly/assembly-wsmaster-war/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-bitbucket</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-github</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-gitlab</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
import org.eclipse.che.api.factory.server.git.ssh.GitSshFactoryParametersResolver;
import org.eclipse.che.api.factory.server.git.ssh.GitSshScmFileResolver;
import org.eclipse.che.api.factory.server.github.GithubFactoryParametersResolver;
import org.eclipse.che.api.factory.server.github.GithubFactoryParametersResolverSecond;
import org.eclipse.che.api.factory.server.github.GithubScmFileResolver;
import org.eclipse.che.api.factory.server.github.GithubScmFileResolverSecond;
import org.eclipse.che.api.factory.server.gitlab.GitlabFactoryParametersResolver;
import org.eclipse.che.api.factory.server.gitlab.GitlabScmFileResolver;
import org.eclipse.che.api.metrics.WsMasterMetricsModule;
Expand Down Expand Up @@ -104,7 +106,6 @@
import org.eclipse.che.security.PBKDF2PasswordEncryptor;
import org.eclipse.che.security.PasswordEncryptor;
import org.eclipse.che.security.oauth.EmbeddedOAuthAPI;
import org.eclipse.che.security.oauth.GitLabModule;
import org.eclipse.che.security.oauth.OAuthAPI;
import org.eclipse.che.security.oauth.OpenShiftOAuthModule;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientConfigFactory;
Expand Down Expand Up @@ -169,6 +170,9 @@ protected void configure() {
Multibinder<FactoryParametersResolver> factoryParametersResolverMultibinder =
Multibinder.newSetBinder(binder(), FactoryParametersResolver.class);
factoryParametersResolverMultibinder.addBinding().to(GithubFactoryParametersResolver.class);
factoryParametersResolverMultibinder
.addBinding()
.to(GithubFactoryParametersResolverSecond.class);
factoryParametersResolverMultibinder
.addBinding()
.to(BitbucketServerAuthorizingFactoryParametersResolver.class);
Expand All @@ -185,6 +189,7 @@ protected void configure() {
Multibinder<ScmFileResolver> scmFileResolverResolverMultibinder =
Multibinder.newSetBinder(binder(), ScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GithubScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GithubScmFileResolverSecond.class);
scmFileResolverResolverMultibinder.addBinding().to(BitbucketScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(GitlabScmFileResolver.class);
scmFileResolverResolverMultibinder.addBinding().to(BitbucketServerScmFileResolver.class);
Expand Down Expand Up @@ -296,8 +301,9 @@ protected void configure() {
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
installDefaultSecureServerExposer(infrastructure);
install(new org.eclipse.che.security.BitbucketModule());
install(new GitLabModule());
install(new org.eclipse.che.security.oauth.GitLabModule());
install(new org.eclipse.che.security.oauth.AzureDevOpsModule());
install(new org.eclipse.che.security.oauth.GithubModule());

configureMultiUserMode(persistenceProperties, infrastructure);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,22 +145,42 @@ che.oauth.azure.devops.redirecturis=https://${CHE_HOST}/api/oauth/callback
# Location of the file with GitHub client id.
che.oauth2.github.clientid_filepath=NULL

# Configuration of the GitHub OAuth2 client. Used to obtain personal access tokens.
# Location of the file with GitHub client id (The second GitHub instance).
che.oauth2.github.clientid_filepath_2=NULL

# Location of the file with GitHub client secret.
che.oauth2.github.clientsecret_filepath=NULL

# Location of the file with GitHub client secret (The second GitHub instance).
che.oauth2.github.clientsecret_filepath_2=NULL

# GitHub OAuth authorization URI.
che.oauth.github.authuri= https://github.com/login/oauth/authorize

# GitHub OAuth authorization URI (The second GitHub instance).
che.oauth.github.authuri_2= https://github.com/login/oauth/authorize

# GitHub OAuth token URI.
che.oauth.github.tokenuri= https://github.com/login/oauth/access_token

# GitHub OAuth token URI (The second GitHub instance).
che.oauth.github.tokenuri_2= https://github.com/login/oauth/access_token

# GitHub server address.
# Prerequisite: OAuth 2 integration is configured on the GitHub server.
che.integration.github.oauth_endpoint=NULL

# GitHub server address.
# Prerequisite: OAuth 2 integration is configured on the GitHub server (The second GitHub instance).
che.integration.github.oauth_endpoint_2=NULL

# GitHub server disable subdomain isolation flag.
che.integration.github.disable_subdomain_isolation=false

# GitHub server disable subdomain isolation flag (The second GitHub instance).
che.integration.github.disable_subdomain_isolation_2=false

# GitHub OAuth redirect URIs.
# Separate multiple values with comma, for example: URI,URI,URI.
che.oauth.github.redirecturis= http://localhost:${CHE_PORT}/api/oauth/callback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-github</artifactId>
<artifactId>che-core-api-auth-github-common</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public OpenShiftGitHubOAuthAuthenticator(
@Nullable @Named("che.oauth.github.tokenuri") String tokenUri)
throws IOException {

super("NULL", "NULL", redirectUris, null, authUri, tokenUri);
super("NULL", "NULL", redirectUris, null, authUri, tokenUri, "github");

if (!isNullOrEmpty(authUri)
&& !isNullOrEmpty(tokenUri)
Expand Down
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,11 @@
<artifactId>che-core-api-auth-github</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-github-common</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-gitlab</artifactId>
Expand Down Expand Up @@ -769,6 +774,11 @@
<artifactId>che-core-api-factory-github</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-factory-github-common</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-factory-gitlab</artifactId>
Expand Down
70 changes: 70 additions & 0 deletions wsmaster/che-core-api-auth-github-common/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2023 Red Hat, Inc.
This program and the accompanying materials are made
available under the terms of the Eclipse Public License 2.0
which is available at https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
Red Hat, Inc. - initial API and implementation
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>che-master-parent</artifactId>
<groupId>org.eclipse.che.core</groupId>
<version>7.77.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-auth-github-common</artifactId>
<packaging>jar</packaging>
<name>Che Core :: API :: Authentication Github Common</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client</artifactId>
</dependency>
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-shared</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-lang</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-standalone</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.security.oauth;

import static com.google.common.base.Strings.isNullOrEmpty;
import static org.eclipse.che.commons.lang.StringUtils.trimEnd;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import javax.inject.Provider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Provides implementation of GitHub {@link OAuthAuthenticator} based on available configuration.
*
* @author Pavol Baran
*/
public abstract class AbstractGitHubOAuthAuthenticatorProvider
implements Provider<OAuthAuthenticator> {
private static final Logger LOG =
LoggerFactory.getLogger(AbstractGitHubOAuthAuthenticatorProvider.class);
private final String providerName;
private final OAuthAuthenticator authenticator;

public AbstractGitHubOAuthAuthenticatorProvider(
String gitHubClientIdPath,
String gitHubClientSecretPath,
String[] redirectUris,
String oauthEndpoint,
String authUri,
String tokenUri,
String providerName)
throws IOException {
this.providerName = providerName;
authenticator =
getOAuthAuthenticator(
gitHubClientIdPath,
gitHubClientSecretPath,
redirectUris,
oauthEndpoint,
authUri,
tokenUri);
LOG.debug("{} GitHub OAuth Authenticator is used.", authenticator);
}

@Override
public OAuthAuthenticator get() {
return authenticator;
}

private OAuthAuthenticator getOAuthAuthenticator(
String clientIdPath,
String clientSecretPath,
String[] redirectUris,
String oauthEndpoint,
String authUri,
String tokenUri)
throws IOException {

String trimmedOauthEndpoint = isNullOrEmpty(oauthEndpoint) ? null : trimEnd(oauthEndpoint, '/');
authUri =
isNullOrEmpty(trimmedOauthEndpoint)
? authUri
: trimmedOauthEndpoint + "/login/oauth/authorize";
tokenUri =
isNullOrEmpty(trimmedOauthEndpoint)
? tokenUri
: trimmedOauthEndpoint + "/login/oauth/access_token";
if (!isNullOrEmpty(clientIdPath)
&& !isNullOrEmpty(clientSecretPath)
&& !isNullOrEmpty(authUri)
&& !isNullOrEmpty(tokenUri)
&& Objects.nonNull(redirectUris)
&& redirectUris.length != 0) {
final String clientId = Files.readString(Path.of(clientIdPath)).trim();
final String clientSecret = Files.readString(Path.of(clientSecretPath)).trim();
if (!isNullOrEmpty(clientId) && !isNullOrEmpty(clientSecret)) {
return new GitHubOAuthAuthenticator(
clientId,
clientSecret,
redirectUris,
trimmedOauthEndpoint,
authUri,
tokenUri,
providerName);
}
}
return new NoopOAuthAuthenticator();
}

static class NoopOAuthAuthenticator extends OAuthAuthenticator {
@Override
public String getOAuthProvider() {
return "Noop";
}

@Override
public String getEndpointUrl() {
return "Noop";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,28 @@
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import javax.inject.Singleton;
import org.eclipse.che.api.auth.shared.dto.OAuthToken;

/** OAuth authentication for github account. */
@Singleton
public class GitHubOAuthAuthenticator extends OAuthAuthenticator {
private final String clientId;
private final String clientSecret;
private final String githubApiUrl;
private final String providerUrl;
private final String providerName;

public GitHubOAuthAuthenticator(
String clientId,
String clientSecret,
String[] redirectUris,
String authEndpoint,
String authUri,
String tokenUri)
String tokenUri,
String providerName)
throws IOException {
this.clientId = clientId;
this.clientSecret = clientSecret;
this.providerName = providerName;
providerUrl = isNullOrEmpty(authEndpoint) ? "https://github.com" : trimEnd(authEndpoint, '/');
githubApiUrl =
providerUrl.equals("https://github.com")
Expand All @@ -52,7 +53,7 @@ public GitHubOAuthAuthenticator(

@Override
public final String getOAuthProvider() {
return "github";
return providerName;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2021 Red Hat, Inc.
* Copyright (c) 2012-2023 Red Hat, Inc.
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
Expand Down
Loading

0 comments on commit 72f191b

Please sign in to comment.