Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat]: Support for AWS ECR Authentication with Temporary Tokens #2907

Merged
merged 1 commit into from
Jan 26, 2025

Conversation

tamilhce
Copy link
Contributor

What type of PR is this?
feature
Which issue does this PR fix:
#2650

What does this PR do / Why do we need it:
This PR adds support for temporary credentials for upstream registries, specifically focusing on AWS ECR. Since ECR credentials are not permanent and need to be rotated periodically, this enhancement enables Zot to dynamically obtain and refresh valid usernames and passwords when the CredentialHelper is configured for the registry

If an issue # is not available please add repro steps and logs showing the issue:
N/A

Testing done on this change:

During initialization, the logs confirm that ECR credentials have been updated:

{"level":"info","goroutine":1,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:77","time":"2024-10-18T23:15:48.269973286+05:30","message":"Using credentials helper, because CredentialHelper is set to ecr"}
{"level":"info","goroutine":1,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:81","time":"2024-10-18T23:15:48.269998807+05:30","message":"Fetch the credentials using AWS ECR Auth Token."}

During credential expiry, the following log entries are generated:

{"level":"info","url":"accountid.dkr.ecr.us-east-1.amazonaws.com","goroutine":593,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:126","time":"2024-10-19T00:43:06.320476296+05:30","message":"The credentials are close to expiring"}
{"level":"info","url":"accountid.dkr.ecr.us-east-1.amazonaws.com","goroutine":593,"caller":"zotregistry.dev/zot/pkg/extensions/sync/ecr_credential_helper.go:135","time":"2024-10-19T00:43:06.320498388+05:30","message":"Refreshing the ECR credentials"}
{"level":"info","url":"accountid.dkr.ecr.us-east-1.amazonaws.com","goroutine":593,"caller":"zotregistry.dev/zot/pkg/extensions/sync/service.go:162","time":"2024-10-19T00:43:07.009198386+05:30","message":"Refreshing the upstream remote registry credentials"}

These logs verify that the credentials are nearing the expiry window of one hour and have been successfully refreshed.
Automation added to e2e:
Added TestECRCredentialsHelper in sync_internal_test

Will this break upgrades or downgrades?
No

Does this PR introduce any user-facing change?:
No

release-note
With this PR, users can configure AWS ECR as an upstream registry for on-demand or periodic sync by setting CredentialHelper: ecr in the extension sync configuration. This change eliminates the need for users to manually add usernames and passwords in the credentialsFile; instead, credentials will be stored in memory and automatically rotated as they approach expiry. An example configuration is available in examples/config-sync-ecr-credential-helper.json.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@tamilhce
Copy link
Contributor Author

tamilhce commented Jan 23, 2025

I have verified that this PR works as expected in my environment and has been running without issues in our dev/UAT clusters for the past two months.

For reference, related discussions can be found in my personal repo: zot1 PR #13.

Based on the discussion in the linked thread, the PR looks good to @rchincha. @andaaron/ others, please review this as well.

I was on a break due to medical reasons for the last few weeks. Apologies for keeping this thread open for so long. Let's close this ASAP. Let me know if you have any suggestions or comments

@rchincha
Copy link
Contributor

@tamilhce your PR has passed all tests. Pls fix review comments.

In general, everything is under pkg/extensions/sync, so your methods can all be foo..() instead of Foo..() so they are scoped only in that pkg right?

examples/config-sync-ecr-credential-helper.json Outdated Show resolved Hide resolved
pkg/extensions/sync/sync_internal_test.go Outdated Show resolved Hide resolved
pkg/extensions/sync/sync.go Outdated Show resolved Hide resolved
pkg/extensions/sync/service.go Outdated Show resolved Hide resolved
pkg/extensions/sync/service.go Outdated Show resolved Hide resolved
pkg/extensions/sync/service.go Outdated Show resolved Hide resolved
@andaaron
Copy link
Contributor

andaaron commented Jan 24, 2025

We'll also need tests. Is it possible to use localstack to test this functionality? We have examples of using localstack for S3 and DynamoDB (ofc we'd need to check if localstack is available locally and only run those tests if available).

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from b65bac3 to de98cc6 Compare January 24, 2025 11:45
@tamilhce
Copy link
Contributor Author

Thanks, @rchincha and @andaaron, for your valuable comments.
I have addressed all the review comments.

@andaaron, regarding this:

We'll also need tests. Is it possible to use LocalStack to test this functionality? We have examples of using LocalStack for S3 and DynamoDB (of course, we'd need to check if LocalStack is available locally and only run those tests if available).

LocalStack does not support ECR authentication, so it cannot be used to test ECR temporary tokens. However, I can add an example for ECR with LocalStack separately later.

Please review this MR once , and let me know if you have any other suggestions

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from de98cc6 to d13d706 Compare January 24, 2025 19:19
pkg/extensions/sync/service.go Show resolved Hide resolved
pkg/extensions/sync/sync.go Outdated Show resolved Hide resolved
pkg/extensions/sync/ecr_credential_helper.go Outdated Show resolved Hide resolved
@andaaron
Copy link
Contributor

@eusebiu-constantin-petu-dbk , @tamilhce we need to sync about this.
There's another PR rewriting sync to use the regctl library: #2903

I took a brief look at regctl, and it looks like the way they solve the issue is using an external binary: https://github.com/regclient/regclient/blob/main/build/Dockerfile.regsync#L30 and https://github.com/regclient/regclient/blob/d1b36cec797378d9974dcf0b7035be077e56abac/config/credhelper.go

I assume is this the same feature we are discussing in this PR? If it is, can we have our own logic outside of the regctl to handled this? And do we want to have our own logic to handle this outside regctl?

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from d13d706 to 2beb29d Compare January 25, 2025 09:24
@tamilhce
Copy link
Contributor Author

tamilhce commented Jan 25, 2025

@andaaron Regarding this #2907 (comment)
Initially, we discussed about using the external binary amazon-ecr-credential-helper.
As discussed in the initial request, we decided to go with this approach
FYI,
#2650 (comment)
#2650 (comment)

@andaaron
Copy link
Contributor

@andaaron Regarding this #2907 (comment) Initially, we discussed about using the external binary amazon-ecr-credential-helper. As discussed in the initial request, we decided to go with this approach FYI, #2650 (comment) #2650 (comment)

@eusebiu-constantin-petu-dbk ^^, what is your take on this?

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from 2beb29d to 6c63dc5 Compare January 25, 2025 11:12
@tamilhce
Copy link
Contributor Author

took a brief look at regctl, and it looks like the way they solve the issue is using an external binary:

When running Zot as a deployment in a K8s cluster, using an external binary for the credential-helper introduces additional dependencies and complexities:

  • It requires an external binary like amazon-ecr-credential-helper.
  • Zot would need access to the root filesystem as well

Moreover, the external binary periodically updates the credentials regardless of whether the user is actively interacting with the configured upstream registry.

In our implemented approach, we retrieve the ECR authentication token only when it's needed. We avoid unnecessary periodic updates and instead validate the token's expiry whenever an upstream request is made.

If the token has expired, we refresh it (the token is typically valid for 12 hours). For instance, if there are no on-demand sync requests for 48 hours, this approach avoids unnecessary calls to the AWS API to refresh the token.

Additionally, relying on an external binary for ECR/registry authentication can lead to issues if the external system encounters problems, such as expired tokens or connectivity failures. With this approach, we retain control and can independently validate token expiry and refresh it as needed.

since we added the CredentialHelper as an interface, which can easily extend the support other token-based registries like GCR by integrating the necessary SDK. This method is straightforward, minimizes external dependencies, avoids introducing too many components, and provides more control overall.

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from 6c63dc5 to 5078d81 Compare January 25, 2025 11:52
@eusebiu-constantin-petu-dbk
Copy link
Collaborator

@eusebiu-constantin-petu-dbk , @tamilhce we need to sync about this. There's another PR rewriting sync to use the regctl library: #2903

I assume is this the same feature we are discussing in this PR? If it is, can we have our own logic outside of the regctl to handled this? And do we want to have our own logic to handle this outside regctl?

Yes, we can have our own logic, we will do it exactly the same like in this PR.
Credentials are exported vars in the host configuration in regclient, which we have access from sync.
No need to change much in the current PR.

I would say let's merge this one first and I'll rebase.

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch 2 times, most recently from e0e22b0 to a99b0dd Compare January 26, 2025 04:30
@tamilhce
Copy link
Contributor Author

@andaaron All the review comments have been addressed. If everything looks good and there are no further comments, please trigger the remaining test suite and consider approve/merge this MR.

Copy link

codecov bot commented Jan 26, 2025

Codecov Report

Attention: Patch coverage is 41.61850% with 101 lines in your changes missing coverage. Please review.

Project coverage is 91.60%. Comparing base (cf8b20d) to head (c1a9230).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/extensions/sync/ecr_credential_helper.go 50.00% 48 Missing and 5 partials ⚠️
pkg/extensions/sync/service.go 30.64% 42 Missing and 1 partial ⚠️
pkg/extensions/sync/remote.go 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2907      +/-   ##
==========================================
- Coverage   91.90%   91.60%   -0.30%     
==========================================
  Files         170      171       +1     
  Lines       30293    30456     +163     
==========================================
+ Hits        27841    27900      +59     
- Misses       1825     1922      +97     
- Partials      627      634       +7     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@andaaron
Copy link
Contributor

@andaaron All the review comments have been addressed. If everything looks good and there are no further comments, please trigger the remaining test suite and consider approve/merge this MR.

Sign your commit (git commit --amend -S), and you should be good to go.

@tamilhce tamilhce force-pushed the tamilhce/ecr-cred-helper branch from a99b0dd to c1a9230 Compare January 26, 2025 08:59
@tamilhce
Copy link
Contributor Author

@andaaron Done, I have signed the commit now. Could you please review it once.

@andaaron andaaron merged commit d0de12d into project-zot:main Jan 26, 2025
38 of 40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants