che-22776_1
ivinokur 2024-01-28 13:00:19 +02:00
parent aa44cd33c9
commit f5c2a2a742
10 changed files with 75 additions and 37 deletions

View File

@ -65,8 +65,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
public static final String ANNOTATION_SCM_ORGANIZATION = "che.eclipse.org/scm-organization";
public static final String ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID =
"che.eclipse.org/scm-personal-access-token-id";
public static final String ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME =
"che.eclipse.org/scm-personal-access-provider-name";
public static final String ANNOTATION_SCM_PROVIDER_NAME = "che.eclipse.org/scm-provider-name";
public static final String ANNOTATION_SCM_URL = "che.eclipse.org/scm-url";
public static final String TOKEN_DATA_FIELD = "token";
@ -102,9 +101,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
.put(
ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID,
personalAccessToken.getScmTokenId())
.put(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
personalAccessToken.getScmProviderName())
.put(ANNOTATION_SCM_PROVIDER_NAME, personalAccessToken.getScmProviderName())
.build())
.withLabels(SECRET_LABELS)
.build();
@ -172,8 +169,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
private Optional<PersonalAccessToken> doGetPersonalAccessToken(
Subject cheUser, @Nullable String oAuthProviderName, @Nullable String scmServerUrl)
throws ScmConfigurationPersistenceException, ScmUnauthorizedException,
ScmCommunicationException {
throws ScmConfigurationPersistenceException {
try {
for (KubernetesNamespaceMeta namespaceMeta : namespaceFactory.list()) {
List<Secret> secrets =
@ -202,7 +198,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
secretAnnotations.get(ANNOTATION_CHE_USERID),
personalAccessTokenParams.getOrganization(),
scmUsername.get(),
secretAnnotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME),
secretAnnotations.get(ANNOTATION_SCM_PROVIDER_NAME),
personalAccessTokenParams.getScmTokenId(),
personalAccessTokenParams.getToken());
return Optional.of(personalAccessToken);
@ -226,18 +222,29 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
return Optional.empty();
}
private void migrate(Secret secret, String providerName) throws InfrastructureException {
private void migrate(Secret secret, @Nullable String providerName)
throws InfrastructureException {
;
String oldAnnotation =
secret.getMetadata().getAnnotations().get("che.eclipse.org/scm-personal-access-token-name");
if (!isNullOrEmpty(oldAnnotation)) {
if (isNullOrEmpty(providerName)) {
Optional<String> providerNameOptional =
scmPersonalAccessTokenFetcher.getScmProviderName(
this.secret2PersonalAccessTokenParams(secret));
if (providerNameOptional.isPresent()) {
providerName = providerNameOptional.get();
} else
throw new InfrastructureException(
"Unable to migrate secret "
+ secret.getMetadata().getName()
+ " to new format. No provider name found.");
}
secret
.getMetadata()
.getAnnotations()
.remove("che.eclipse.org/scm-personal-access-token-name");
secret
.getMetadata()
.getAnnotations()
.put(ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME, providerName);
secret.getMetadata().getAnnotations().put(ANNOTATION_SCM_PROVIDER_NAME, providerName);
cheServerKubernetesClientFactory
.create()
.secrets()
@ -251,8 +258,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
String configuredScmServerUrl = secretAnnotations.get(ANNOTATION_SCM_URL);
String configuredCheUserId = secretAnnotations.get(ANNOTATION_CHE_USERID);
String configuredOAuthProviderName =
secretAnnotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME);
String configuredOAuthProviderName = secretAnnotations.get(ANNOTATION_SCM_PROVIDER_NAME);
// if any of the required annotations is missing, the secret is not valid
if (isNullOrEmpty(configuredScmServerUrl)
@ -273,8 +279,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
Map<String, String> secretAnnotations = secret.getMetadata().getAnnotations();
String token = new String(Base64.getDecoder().decode(secret.getData().get("token"))).trim();
String configuredOAuthProviderName =
secretAnnotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME);
String configuredOAuthProviderName = secretAnnotations.get(ANNOTATION_SCM_PROVIDER_NAME);
String configuredTokenId = secretAnnotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_TOKEN_ID);
String configuredScmOrganization = secretAnnotations.get(ANNOTATION_SCM_ORGANIZATION);
String configuredScmServerUrl = secretAnnotations.get(ANNOTATION_SCM_URL);
@ -295,8 +300,7 @@ public class KubernetesPersonalAccessTokenManager implements PersonalAccessToken
Map<String, String> secretAnnotations = secret.getMetadata().getAnnotations();
String configuredScmServerUrl = secretAnnotations.get(ANNOTATION_SCM_URL);
String configuredCheUserId = secretAnnotations.get(ANNOTATION_CHE_USERID);
String configuredOAuthProviderName =
secretAnnotations.get(ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME);
String configuredOAuthProviderName = secretAnnotations.get(ANNOTATION_SCM_PROVIDER_NAME);
return (configuredCheUserId.equals(cheUser.getUserId()))
&& (oAuthProviderName == null || oAuthProviderName.equals(configuredOAuthProviderName))

View File

@ -104,7 +104,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user",
@ -181,7 +181,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -192,7 +192,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -203,7 +203,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user2",
@ -249,7 +249,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -294,7 +294,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -339,7 +339,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -350,7 +350,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -396,11 +396,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withNamespace("test")
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1"))
Map.of(ANNOTATION_SCM_PROVIDER_NAME, "github", ANNOTATION_CHE_USERID, "user1"))
.build();
Secret secret1 = new SecretBuilder().withMetadata(meta1).withData(data1).build();
when(secrets.get(any(LabelSelector.class))).thenReturn(Arrays.asList(secret1));
@ -433,7 +429,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -480,7 +476,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",
@ -493,7 +489,7 @@ public class KubernetesPersonalAccessTokenManagerTest {
new ObjectMetaBuilder()
.withAnnotations(
Map.of(
ANNOTATION_SCM_PERSONAL_ACCESS_PROVIDER_NAME,
ANNOTATION_SCM_PROVIDER_NAME,
"github",
ANNOTATION_CHE_USERID,
"user1",

View File

@ -185,7 +185,7 @@ public class EmbeddedOAuthAPI implements OAuthAPI {
return token;
}
Optional<PersonalAccessToken> tokenOptional =
personalAccessTokenManager.get(subject, oauthProvider);
personalAccessTokenManager.get(subject, oauthProvider, null);
if (tokenOptional.isPresent()) {
PersonalAccessToken tokenDto = tokenOptional.get();
return newDto(OAuthToken.class).withToken(tokenDto.getToken());

View File

@ -167,6 +167,11 @@ public class AzureDevOpsPersonalAccessTokenFetcher implements PersonalAccessToke
}
}
@Override
public String getProviderName(PersonalAccessTokenParams params) {
return "azure-devops";
}
private String getLocalAuthenticateUrl() {
return cheApiEndpoint + getAuthenticateUrlPath(scopes);
}

View File

@ -177,4 +177,9 @@ public class BitbucketServerPersonalAccessTokenFetcher implements PersonalAccess
return Optional.empty();
}
}
@Override
public String getProviderName(PersonalAccessTokenParams params) {
return "bitbucket-server";
}
}

View File

@ -168,6 +168,11 @@ public class BitbucketPersonalAccessTokenFetcher implements PersonalAccessTokenF
}
}
@Override
public String getProviderName(PersonalAccessTokenParams params) {
return OAUTH_PROVIDER_NAME;
}
private String getLocalAuthenticateUrl() {
return apiEndpoint
+ "/oauth/authenticate?oauth_provider="

View File

@ -235,6 +235,11 @@ public abstract class AbstractGithubPersonalAccessTokenFetcher
}
}
@Override
public String getProviderName(PersonalAccessTokenParams params) {
return providerName;
}
/**
* Checks if the tokenScopes array contains the requiredScopes.
*

View File

@ -219,6 +219,11 @@ public class GitlabOAuthTokenFetcher implements PersonalAccessTokenFetcher {
}
}
@Override
public String getProviderName(PersonalAccessTokenParams params) {
return OAUTH_PROVIDER_NAME;
}
private String getLocalAuthenticateUrl() {
return apiEndpoint
+ "/oauth/authenticate?oauth_provider="

View File

@ -66,4 +66,6 @@ public interface PersonalAccessTokenFetcher {
* or deny that token is valid.
*/
Optional<Pair<Boolean, String>> isValid(PersonalAccessTokenParams params);
String getProviderName(PersonalAccessTokenParams params);
}

View File

@ -80,7 +80,8 @@ public class ScmPersonalAccessTokenFetcher {
* {@link PersonalAccessTokenFetcher#isValid(PersonalAccessTokenParams)} method. If any of the
* fetchers return an scm username, return it. Otherwise, return null.
*/
public Optional<String> getScmUsername(PersonalAccessTokenParams params) throws UnknownScmProviderException {
public Optional<String> getScmUsername(PersonalAccessTokenParams params)
throws UnknownScmProviderException {
for (PersonalAccessTokenFetcher fetcher : personalAccessTokenFetchers) {
Optional<Pair<Boolean, String>> isValid = fetcher.isValid(params);
if (isValid.isPresent() && isValid.get().first) {
@ -89,4 +90,14 @@ public class ScmPersonalAccessTokenFetcher {
}
return Optional.empty();
}
public Optional<String> getScmProviderName(PersonalAccessTokenParams params) {
for (PersonalAccessTokenFetcher fetcher : personalAccessTokenFetchers) {
Optional<Pair<Boolean, String>> isValid = fetcher.isValid(params);
if (isValid.isPresent() && isValid.get().first) {
return Optional.of(fetcher.getProviderName(params));
}
}
return Optional.empty();
}
}