Skip to content

Commit

Permalink
Obtain and persist Bitbucket personal access token as k8s secret
Browse files Browse the repository at this point in the history
Signed-off-by: Sergii Kabashniuk <skabashniuk@redhat.com>
  • Loading branch information
skabashnyuk committed Jan 20, 2021
1 parent 2c7b403 commit d20ef75
Show file tree
Hide file tree
Showing 43 changed files with 2,628 additions and 13 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 @@ -111,6 +111,10 @@
<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-bitbucket</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-openshift</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ protected void configure() {
bind(org.eclipse.che.api.user.server.ProfileService.class);
bind(org.eclipse.che.api.user.server.PreferencesService.class);
bind(org.eclipse.che.security.oauth.OAuthAuthenticationService.class);
bind(org.eclipse.che.security.oauth1.OAuthAuthenticationService.class);

install(new DevfileModule());

Expand Down Expand Up @@ -256,6 +257,7 @@ protected void configure() {
install(new FactoryModuleBuilder().build(JwtProxyConfigBuilderFactory.class));
install(new FactoryModuleBuilder().build(PassThroughProxyProvisionerFactory.class));
installDefaultSecureServerExposer(infrastructure);
install(new org.eclipse.che.security.oauth1.BitbucketModule());

if (Boolean.valueOf(System.getenv("CHE_MULTIUSER"))) {
configureMultiUserMode(persistenceProperties, infrastructure);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ che.oauth.openshift.clientsecret=NULL
che.oauth.openshift.oauth_endpoint= NULL
che.oauth.openshift.verify_token_url= NULL

# Configuration of Bitbucket Server OAuth1 client. Used to obtain Personal access tokens.
# Location of the file with Bitbucket Server application consumer key (equivalent to a username).
che.oauth1.bitbucket.consumerkeypath=NULL
# Location of the file with Bitbucket Server application private key
che.oauth1.bitbucket.privatekeypath=NULL
# Bitbucket Server URL. To work correctly with factories the same URL
# has to be part of `che.integration.bitbucket.server_endpoints` too.
che.oauth1.bitbucket.endpoint=NULL


### Internal

# Che extensions can be scheduled executions on a time basis.
Expand Down
5 changes: 0 additions & 5 deletions infrastructures/infrastructure-factory/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,6 @@
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class KeycloakServletModule extends ServletModule {
// not contains /docs/ (for swagger)
+ "(?!.*(/docs/))"
// not ends with '/oauth/callback/' or '/keycloak/settings/' or '/system/state'
+ "(?!.*(/keycloak/settings/?|/oauth/callback/?|/system/state/?)$)"
+ "(?!.*(/keycloak/settings/?|/oauth/callback/?|/oauth/1.0/callback/?|/system/state/?)$)"
// all other
+ ".*";

Expand Down
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,11 @@
<artifactId>che-core-api-auth</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-bitbucket</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-auth-github</artifactId>
Expand Down
65 changes: 65 additions & 0 deletions wsmaster/che-core-api-auth-bitbucket/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2012-2018 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.25.0-SNAPSHOT</version>
</parent>
<artifactId>che-core-api-auth-bitbucket</artifactId>
<packaging>jar</packaging>
<name>Che Core :: API :: Authentication Bitbucket</name>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</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-commons-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2012-2018 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.oauth1;

import com.google.inject.AbstractModule;
import com.google.inject.multibindings.Multibinder;
import org.eclipse.che.inject.DynaModule;

/**
* Setup BitbucketServerOAuthAuthenticator in guice container.
*
* @author Sergii Kabashniuk
*/
@DynaModule
public class BitbucketModule extends AbstractModule {
@Override
protected void configure() {
Multibinder<OAuthAuthenticator> oAuthAuthenticators =
Multibinder.newSetBinder(binder(), OAuthAuthenticator.class);
oAuthAuthenticators.addBinding().toProvider(BitbucketServerOAuthAuthenticatorProvider.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2012-2018 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.oauth1;

import com.google.inject.Singleton;

/**
* OAuth1 authentication for Bitbucket Server account.
*
* @author Igor Vinokur
*/
@Singleton
public class BitbucketServerOAuthAuthenticator extends OAuthAuthenticator {
public static final String AUTHENTICATOR_NAME = "bitbucket-server";

public BitbucketServerOAuthAuthenticator(
String consumerKey, String privateKey, String bitbucketEndpoint, String apiEndpoint) {
super(
consumerKey,
bitbucketEndpoint + "/plugins/servlet/oauth/request-token",
bitbucketEndpoint + "/plugins/servlet/oauth/access-token",
bitbucketEndpoint + "/plugins/servlet/oauth/authorize",
apiEndpoint + "/oauth/1.0/callback",
null,
privateKey);
}

@Override
public final String getOAuthProvider() {
return AUTHENTICATOR_NAME;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) 2012-2018 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.oauth1;

import static com.google.common.base.Strings.isNullOrEmpty;

import com.google.inject.name.Named;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.eclipse.che.commons.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class BitbucketServerOAuthAuthenticatorProvider implements Provider<OAuthAuthenticator> {
private final OAuthAuthenticator authenticator;
private static final Logger LOG =
LoggerFactory.getLogger(BitbucketServerOAuthAuthenticatorProvider.class);

@Inject
public BitbucketServerOAuthAuthenticatorProvider(
@Nullable @Named("che.oauth1.bitbucket.consumerkeypath") String consumerKeyPath,
@Nullable @Named("che.oauth1.bitbucket.privatekeypath") String privateKeyPath,
@Nullable @Named("che.oauth1.bitbucket.endpoint") String bitbucketEndpoint,
@Named("che.api") String apiEndpoint)
throws IOException {

authenticator =
getOAuthAuthenticator(consumerKeyPath, privateKeyPath, bitbucketEndpoint, apiEndpoint);
LOG.debug("{} Bitbucket OAuthAuthenticator is used.", authenticator);
}

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

private static OAuthAuthenticator getOAuthAuthenticator(
String consumerKeyPath, String privateKeyPath, String bitbucketEndpoint, String apiEndpoint)
throws IOException {
if (!isNullOrEmpty(bitbucketEndpoint)
&& !isNullOrEmpty(consumerKeyPath)
&& !isNullOrEmpty(privateKeyPath)) {
String consumerKey = Files.readString(Path.of(consumerKeyPath));
String privateKey = Files.readString(Path.of(privateKeyPath));
if (!isNullOrEmpty(consumerKey) && !isNullOrEmpty(privateKey)) {
return new BitbucketServerOAuthAuthenticator(
consumerKey, privateKey, bitbucketEndpoint, apiEndpoint);
}
}

return new NoopOAuthAuthenticator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2012-2018 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.oauth1;

import java.net.URL;

/**
* Dummy implementation of @{@link OAuthAuthenticator} used in the case if no Bitbucket Server
* integration is configured.
*/
public class NoopOAuthAuthenticator extends OAuthAuthenticator {
protected NoopOAuthAuthenticator() {
super(null, null, null, null, null, null, null);
}

@Override
String getOAuthProvider() {
return "Noop";
}

@Override
String getAuthenticateUrl(URL requestUrl, String requestMethod, String signatureMethod)
throws OAuthAuthenticationException {
throw new RuntimeException("Invalid usage of NoopOAuthAuthenticator");
}

@Override
String callback(URL requestUrl) throws OAuthAuthenticationException {
throw new RuntimeException("Invalid usage of NoopOAuthAuthenticator");
}

@Override
String computeAuthorizationHeader(String userId, String requestMethod, String requestUrl)
throws OAuthAuthenticationException {
throw new RuntimeException("Invalid usage of NoopOAuthAuthenticator");
}
}
Loading

0 comments on commit d20ef75

Please sign in to comment.