-
Notifications
You must be signed in to change notification settings - Fork 549
Add AWS Elastic Container Service authentication support #876
Conversation
Codecov Report
@@ 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 |
It would be great to see this in the docker client |
There was a problem hiding this 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. |
There was a problem hiding this comment.
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"?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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())); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need spy()
here. See https://gist.github.com/davidxia/ad4b35ae0777c30726afabe0a77490c0
Any news on this MR? any time frame for its availability? |
Hey team. Let merge this PR? |
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. |
@davidxia I fixed your remarks on https://github.com/toelen/docker-client/tree/feat/ecr-auth |
Sorry for the late reply.
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. |
There was a problem hiding this comment.
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.") |
There was a problem hiding this comment.
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"), |
There was a problem hiding this comment.
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"), |
There was a problem hiding this comment.
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"), |
There was a problem hiding this comment.
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"); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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; |
There was a problem hiding this comment.
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?
@toelen Sorry, I didn't see your comment here.
Can you update this PR with those changes? |
return authorizationData; | ||
} | ||
|
||
void refresh() throws IOException { |
There was a problem hiding this comment.
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() { |
There was a problem hiding this comment.
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()); |
There was a problem hiding this comment.
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?
Can We get this merge please , We also eagerly waiting for this support |
@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. |
No description provided.