Skip to content

Commit

Permalink
feat(artifacts/bitbuket): add token auth credentials support (#5604)
Browse files Browse the repository at this point in the history
  • Loading branch information
juanpabloprado committed Jan 12, 2022
1 parent 264af19 commit b83cb75
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 11 deletions.
Expand Up @@ -20,6 +20,7 @@
import com.google.common.base.Strings;
import com.netflix.spinnaker.clouddriver.artifacts.config.ArtifactAccount;
import com.netflix.spinnaker.clouddriver.artifacts.config.BasicAuth;
import com.netflix.spinnaker.clouddriver.artifacts.config.TokenAuth;
import com.netflix.spinnaker.kork.annotations.NonnullByDefault;
import java.util.Optional;
import javax.annotation.ParametersAreNullableByDefault;
Expand All @@ -29,20 +30,35 @@

@NonnullByDefault
@Value
public class BitbucketArtifactAccount implements ArtifactAccount, BasicAuth {
private final String name;
private final Optional<String> username;
private final Optional<String> password;
private final Optional<String> usernamePasswordFile;
public class BitbucketArtifactAccount implements ArtifactAccount, BasicAuth, TokenAuth {
String name;
Optional<String> username;
Optional<String> password;
Optional<String> usernamePasswordFile;
Optional<String> token;
Optional<String> tokenFile;

@Builder
@ConstructorBinding
@ParametersAreNullableByDefault
BitbucketArtifactAccount(
String name, String username, String password, String usernamePasswordFile) {
String name,
String username,
String password,
String usernamePasswordFile,
String token,
String tokenFile) {
this.name = Strings.nullToEmpty(name);
this.username = Optional.ofNullable(Strings.emptyToNull(username));
this.password = Optional.ofNullable(Strings.emptyToNull(password));
this.usernamePasswordFile = Optional.ofNullable(Strings.emptyToNull(usernamePasswordFile));
this.token = Optional.ofNullable(Strings.emptyToNull(token));
this.tokenFile = Optional.ofNullable(Strings.emptyToNull(tokenFile));
}

@ParametersAreNullableByDefault
BitbucketArtifactAccount(
String name, String username, String password, String usernamePasswordFile) {
this(name, username, password, usernamePasswordFile, null, null);
}
}
Expand Up @@ -17,11 +17,15 @@

package com.netflix.spinnaker.clouddriver.artifacts.bitbucket;

import static org.springframework.http.HttpHeaders.AUTHORIZATION;

import com.google.common.collect.ImmutableList;
import com.netflix.spinnaker.clouddriver.artifacts.config.ArtifactCredentials;
import com.netflix.spinnaker.clouddriver.artifacts.config.SimpleHttpArtifactCredentials;
import com.netflix.spinnaker.kork.annotations.NonnullByDefault;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.OkHttpClient;
import java.util.Optional;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

Expand All @@ -38,6 +42,18 @@ public class BitbucketArtifactCredentials
this.name = account.getName();
}

@Override
protected Headers getHeaders(BitbucketArtifactAccount account) {
Headers.Builder headers = new Headers.Builder();
Optional<String> token = account.getTokenAsString();
if (token.isPresent()) {
headers.set(AUTHORIZATION, "Bearer " + token.get());
log.info("Loaded credentials for Bitbucket Artifact Account {}", account.getName());
return headers.build();
}
return super.getHeaders(account);
}

@Override
public String getType() {
return CREDENTIALS_TYPE;
Expand Down
Expand Up @@ -18,31 +18,74 @@

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.MappingBuilder;
import com.netflix.spinnaker.kork.artifacts.model.Artifact;
import com.squareup.okhttp.OkHttpClient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Function;
import org.apache.commons.io.Charsets;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junitpioneer.jupiter.TempDirectory;
import ru.lanwen.wiremock.ext.WiremockResolver;

@ExtendWith({WiremockResolver.class, TempDirectory.class})
class BitbucketArtifactCredentialsTest {
private final ObjectMapper objectMapper = new ObjectMapper();
private final OkHttpClient okHttpClient = new OkHttpClient();

private final String DOWNLOAD_PATH = "/repos/spinnaker/testing/manifest.yml";
private final String FILE_CONTENTS = "file contents";

@Test
void downloadWithToken(@WiremockResolver.Wiremock WireMockServer server) throws IOException {
BitbucketArtifactAccount account =
BitbucketArtifactAccount.builder().name("my-bitbucket-account").token("abc").build();

runTestCase(server, account, m -> m.withHeader(AUTHORIZATION, equalTo("Bearer abc")));
}

@Test
void downloadWithTokenFromFile(
@TempDirectory.TempDir Path tempDir, @WiremockResolver.Wiremock WireMockServer server)
throws IOException {
Path authFile = tempDir.resolve("auth-file");
Files.write(authFile, "zzz".getBytes());

BitbucketArtifactAccount account =
BitbucketArtifactAccount.builder()
.name("my-bitbucket-account")
.tokenFile(authFile.toAbsolutePath().toString())
.build();

runTestCase(server, account, m -> m.withHeader(AUTHORIZATION, equalTo("Bearer zzz")));
}

@Test
void downloadWithTokenFromFileWithReloadHeaders(
@TempDirectory.TempDir Path tempDir, @WiremockResolver.Wiremock WireMockServer server)
throws IOException {
Path authFile = tempDir.resolve("auth-file");
Files.write(authFile, "zzz".getBytes());

BitbucketArtifactAccount account =
BitbucketArtifactAccount.builder()
.name("my-bitbucket-account")
.tokenFile(authFile.toAbsolutePath().toString())
.build();

runTestCase(server, account, m -> m.withHeader(AUTHORIZATION, equalTo("Bearer zzz")));

Files.write(authFile, "aaa".getBytes());

runTestCase(server, account, m -> m.withHeader(AUTHORIZATION, equalTo("Bearer aaa")));
}

@Test
void downloadWithBasicAuth(@WiremockResolver.Wiremock WireMockServer server) throws IOException {
BitbucketArtifactAccount account =
Expand Down Expand Up @@ -76,7 +119,7 @@ void downloadWithNoAuth(@WiremockResolver.Wiremock WireMockServer server) throws
BitbucketArtifactAccount account =
BitbucketArtifactAccount.builder().name("my-bitbucket-account").build();

runTestCase(server, account, m -> m.withHeader("Authorization", absent()));
runTestCase(server, account, m -> m.withHeader(AUTHORIZATION, absent()));
}

private void runTestCase(
Expand All @@ -97,7 +140,7 @@ private void runTestCase(
prepareServer(server, expectedAuth);

assertThat(credentials.download(artifact))
.hasSameContentAs(new ByteArrayInputStream(FILE_CONTENTS.getBytes(Charsets.UTF_8)));
.hasSameContentAs(new ByteArrayInputStream(FILE_CONTENTS.getBytes(StandardCharsets.UTF_8)));
assertThat(server.findUnmatchedRequests().getRequests()).isEmpty();
}

Expand Down

0 comments on commit b83cb75

Please sign in to comment.