Skip to content
This repository has been archived by the owner on Mar 21, 2022. It is now read-only.

Add AWS Elastic Container Service authentication support #876

Closed
wants to merge 4 commits into from

Conversation

toelen
Copy link

@toelen toelen commented Aug 29, 2017

No description provided.

@codecov-io
Copy link

codecov-io commented Aug 29, 2017

Codecov Report

Merging #876 into master will decrease coverage by 0.32%.
The diff coverage is 66.66%.

@@             Coverage Diff              @@
##             master     #876      +/-   ##
============================================
- Coverage     66.39%   66.06%   -0.33%     
- Complexity      742      778      +36     
============================================
  Files           166      171       +5     
  Lines          3139     3300     +161     
  Branches        357      376      +19     
============================================
+ Hits           2084     2180      +96     
- Misses          898      952      +54     
- Partials        157      168      +11     

@ben-gineer
Copy link

It would be great to see this in the docker client

Copy link
Contributor

@davidxia davidxia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@toelen Thanks so much for this PR.

In general, I'm not sure if we want to add more vendor specific libraries to this repo or if we want to pull out this support to separate libraries that can be plugged in.

See spotify/dockerfile-maven#54.

@mattnworb thoughts?

private static final Logger log = LoggerFactory.getLogger(ContainerRegistryAuthSupplier.class);

/**
* Constructs a ContainerRegistryAuthSupplier using the Application Default Credentials.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it accurate to use "Application Default Credentials" here or should we simply call it "default AWS credentials"?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, AWS Default Credential Provider Chain is probably the most correct.

return RegistryConfigs.empty();
}

final Map<String, RegistryAuth> configs = new HashMap<String, RegistryAuth>(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You can omit the explicit type args here in new HashMap<>.

ecrClient, clock, minimumExpirationSecs, credentials));

private static Matcher<RegistryAuth> matchesAccessToken(final AuthorizationData accessToken) {
String decoded = new String(Base64.decode(accessToken.getAuthorizationToken()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: You can also add final here.

private final DateTime expiration = new DateTime(2017, 5, 23, 16, 25);
private final String tokenValue = new String(encode("test-username:test-password".getBytes()));

private AmazonECR ecrClient = mock(AmazonECR.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can also be final.


@Before
public void before() {
GetAuthorizationTokenResult res = new GetAuthorizationTokenResult()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can be final.


// Don't refresh if expiration time hasn't been provided.
if (expirationTime == null) {
return true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to test this? Will accessToken.getExpiresAt() ever be null?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private final Clock clock = mock(Clock.class);
private final int minimumExpirationSecs = 30;
private final EcrCredentials credentials = spy(new EcrCredentials(ecrClient, authData1));
private final ContainerRegistryAuthSupplier supplier = spy(new ContainerRegistryAuthSupplier(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhermosi
Copy link

mhermosi commented Jan 9, 2018

Any news on this MR? any time frame for its availability?

@smuryginim
Copy link

Hey team. Let merge this PR?

@davidxia
Copy link
Contributor

davidxia commented Mar 1, 2018

This PR doesn't seem ready yet to merge. I at least still had some comments and unresolved questions above. Original author hasn't responded yet.

@toelen
Copy link
Author

toelen commented Mar 2, 2018

@mattnworb
Copy link
Member

Sorry for the late reply.

In general, I'm not sure if we want to add more vendor specific libraries to this repo or if we want to pull out this support to separate libraries that can be plugged in.

See spotify/dockerfile-maven#54.

@mattnworb thoughts?

I think the best thing would be to structure these things as different modules, meaning change docker-client to be a multi-module maven build with a "core" module that contains all the existing code minus the GCR part, which can go in a separate module, and then ECR or other RegistryAuthSuppliers can all go in different modules. But I am indifferent about if that is a prerequisite for merging this change or not.

private static final Logger log = LoggerFactory.getLogger(ContainerRegistryAuthSupplier.class);

/**
* Constructs a ContainerRegistryAuthSupplier using the Application Default Credentials.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, AWS Default Credential Provider Chain is probably the most correct.

public RegistryAuth authFor(final String imageName) throws DockerException {
final String[] imageParts = imageName.split("/", 2);

if ((imageParts.length < 2) || !imageParts[0].contains(".dkr.ecr.")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about just doing a regex on the ECR repo format? Something along the lines of ^\d+\.dkr\.ecr\.[a-z-0-9]+\.amazonaws\.com\/

expiration.minusSeconds(minimumExpirationSecs + 1).getMillis());

assertThat(
supplier.authFor("1234567890.dkr.ecr.eu-west-1.amazonaws.com/foobar/barfoo:latest"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of these image names seem to be the wrong format, to me. Shouldn't it be 1234567890.dkr.ecr.eu-west-1.amazonaws.com/foobar:latest?

doReturn(true).when(supplier).needsRefresh(Matchers.any(AuthorizationData.class));

assertThat(
supplier.authFor("1234567890.dkr.ecr.eu-west-1.amazonaws.com/foobar/barfoo:latest"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same image name format comment as above

doReturn(true).when(supplier).needsRefresh(Matchers.any(AuthorizationData.class));

assertThat(
supplier.authFor("1234567890.dkr.ecr.eu-west-1.amazonaws.com/foobar/barfoo:latest"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same image name format comment as above

exception.expect(DockerException.class);
exception.expectCause(is(ex));

supplier.authFor("1234567890.dkr.ecr.eu-west-1.amazonaws.com/example/foobar:1.2.3");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same image name format comment as above


// Don't refresh if expiration time hasn't been provided.
if (expirationTime == null) {
return true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sigpwned
Copy link

sigpwned commented Apr 21, 2018

Oops! I just submitted a different pull request #1013 for ECR authentication. I missed this in my search. I was searching for ECR and ECS. Hopefully now this comment will flag for future searchers.

It looks like this review may have stalled out. If I can do some work to push it through, or if my other pull request looks OK, it would be great to get ECR support into this project soon. Very happy to help do that — just LMK how!

ContainerRegistryAuthSupplier(final AmazonECR ecr, final Clock clock,
final long minimumExpiryMillis, final EcrCredentials credentials) {
Preconditions.checkArgument(ecr != null, "ecr");
this.ecr = ecr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to pass ecr here? I see it's used as a sync object below, but can't you just lock on something else?

@davidxia
Copy link
Contributor

@toelen Sorry, I didn't see your comment here.

@davidxia I fixed your remarks on https://github.com/toelen/docker-client/tree/feat/ecr-auth

Can you update this PR with those changes?

return authorizationData;
}

void refresh() throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the IOException here.

this.authorizationData = authorizationData;
}

public AuthorizationData getAuthorizationData() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be package-private.


void refresh() throws IOException {
GetAuthorizationTokenResult authorizationToken = ecr
.getAuthorizationToken(new GetAuthorizationTokenRequest());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javadocs for GetAuthorizationTokenRequest() say

A list of AWS account IDs that are associated with the registries for which to get authorization tokens. If you do not specify a registry, the default registry is assumed.

Will the user ever need to use registries other than the default?

@cenacsf
Copy link

cenacsf commented Jul 17, 2018

Can We get this merge please , We also eagerly waiting for this support

@davidxia
Copy link
Contributor

@cenacsf There's this and #1013. The last update was my comment here #1013 (comment). It seems like both of these PRs have stalled. If someone's willing to drive #1013 (comment) to completion, I'm happy to review and merge.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants