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

Enable contextual login in OCI HelmRepository #873

Merged
merged 1 commit into from
Aug 26, 2022

Conversation

souleb
Copy link
Member

@souleb souleb commented Aug 24, 2022

If implemented, this pr will enable user to use the auto login feature in order to automatically login to their provider of choice's container registry (i.e. aws, gcr, acr).

This must be tested with the following providers

  • aws. This has been tested on an eks cluster (with IRSA) that was previously using a cronjob to rotate tokens.
  • gcr. This has been tested on gke with a chart in artifact registry.
  • acr. Tested by @darkowlzz successfully.

If people have existing running gke or aks clusters, that would be nice to help test this.

Fix: #867
Fix: #870
Implements: fluxcd/flux2#3025

@souleb souleb marked this pull request as draft August 24, 2022 07:38
@souleb souleb added area/helm Helm related issues and pull requests area/oci OCI related issues and pull requests labels Aug 24, 2022
@hiddeco hiddeco changed the title [HELM OCI] Enable contextual login Enable contextual login OCI HelmRepository Aug 24, 2022
@souleb souleb changed the title Enable contextual login OCI HelmRepository Enable contextual login in OCI HelmRepository Aug 24, 2022
@darkowlzz
Copy link
Contributor

I tested it on azure using the test infrastructure from fluxcd/pkg/oci/tests/integration. It works.

Copy link
Member

@stefanprodan stefanprodan left a comment

Choose a reason for hiding this comment

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

We need to document the contextual login usage. I think the docs can be adapted from https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1beta2/ocirepositories.md#provider

@souleb souleb marked this pull request as ready for review August 25, 2022 11:58
Copy link
Member

@stefanprodan stefanprodan left a comment

Choose a reason for hiding this comment

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

LGTM

Thanks @souleb 🥇

api/v1beta2/helmrepository_types.go Outdated Show resolved Hide resolved
api/v1beta2/helmrepository_types.go Outdated Show resolved Hide resolved
controllers/helmchart_controller.go Show resolved Hide resolved
controllers/helmchart_controller.go Outdated Show resolved Hide resolved
docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
@souleb souleb force-pushed the enable-oidc-auth branch 3 times, most recently from bff9560 to afa6914 Compare August 25, 2022 13:15
@souleb souleb force-pushed the enable-oidc-auth branch 3 times, most recently from fab6e81 to 6afb263 Compare August 25, 2022 13:35
Copy link
Member

@pjbgf pjbgf left a comment

Choose a reason for hiding this comment

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

Tiny nit

docs/spec/v1beta2/helmrepositories.md Outdated Show resolved Hide resolved
@darkowlzz
Copy link
Contributor

darkowlzz commented Aug 25, 2022

While testing events and notifications, I found an issue which I believe didn't get much attention earlier because most of the focus was on getting the status conditions correct.
The line

// Became not ready from ready.
if conditions.IsReady(oldObj) && !conditions.IsReady(obj) {

checks if the object was ready before and became not ready after the reconciliation, and emits a notification based on that. This works for that exact situation, when the object was ready before. But it doesn't work when the object is created for the first time.
Let's change this to notify always when it's not ready but notify once on recovery.
Something around:

-               // Emit events when object's state changes.
+               // Emit event when reconciliation fails or recovers from failure.
                ready := conditions.Get(obj, meta.ReadyCondition)
                // Became ready from not ready.
                if !conditions.IsReady(oldObj) && conditions.IsReady(obj) {
                        r.eventLogf(ctx, obj, corev1.EventTypeNormal, ready.Reason, ready.Message)
                }
-               // Became not ready from ready.
-               if conditions.IsReady(oldObj) && !conditions.IsReady(obj) {
+               // Not ready, failed.
+               if !conditions.IsReady(obj) {

@souleb
Copy link
Member Author

souleb commented Aug 25, 2022

While testing events and notifications, I found an issue which I believe didn't get much attention earlier because most of the focus was on getting the status conditions correct. The line

// Became not ready from ready.
if conditions.IsReady(oldObj) && !conditions.IsReady(obj) {

checks if the object was ready before and became not ready after the reconciliation, and emits a notification based on that. This works for that exact situation, when the object was ready before. But it doesn't work when the object is created for the first time.
Let's change this to notify always when it's not ready but notify once on recovery.
Something around:

-               // Emit events when object's state changes.
+               // Emit event when reconciliation fails or recovers from failure.
                ready := conditions.Get(obj, meta.ReadyCondition)
                // Became ready from not ready.
                if !conditions.IsReady(oldObj) && conditions.IsReady(obj) {
                        r.eventLogf(ctx, obj, corev1.EventTypeNormal, ready.Reason, ready.Message)
                }
-               // Became not ready from ready.
-               if conditions.IsReady(oldObj) && !conditions.IsReady(obj) {
+               // Not ready, failed.
+               if !conditions.IsReady(obj) {

can we do this in another PR? I will make the update.

If implemented, this pr will enable user to use the auto login feature
in order to automatically login to their provider of choice's container
registry (i.e. aws, gcr, acr).

Signed-off-by: Soule BA <[email protected]>
@darkowlzz
Copy link
Contributor

can we do this in another PR? I will make the update.

@souleb okay.

Copy link
Member

@pjbgf pjbgf left a comment

Choose a reason for hiding this comment

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

LGTM

great job @souleb! 🙇

}

return loginOpt, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The code in this function combined with loginWithManager() below, it seems like registry.OIDCAdaptHelper() can just take the result of OCIRepositoryReconciler.oidcAuth(). The arguments of OCIRepositoryReconciler.oidcAuth() can just be the URL and the provider name to not make it source type specific. It should be okay to convert OCIRepositoryReconciler.oidcAuth() into an independent function oidcAuth().

In the future, I think we can make a private package with a lot of the OCI related code here and in OCIRepo reconciler.

Copy link
Member Author

@souleb souleb Aug 25, 2022

Choose a reason for hiding this comment

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

true, it would be better. But as you said OCIRepositoryReconciler.oidcAuth() is a receiver function, so I thought that this would need a specific PR to refactor it.

Copy link
Contributor

Choose a reason for hiding this comment

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

okay to change it separately.

Copy link
Contributor

@darkowlzz darkowlzz left a comment

Choose a reason for hiding this comment

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

LGTM!

@darkowlzz
Copy link
Contributor

darkowlzz commented Aug 26, 2022

Just remembered that when testing with both spec.secretRef and spec.provider set, the provider login option overwrites the secretRef login option. For example, if I create a secret with incorrect credentials and set the provider correctly, the result is a Ready HelmRepository. As per the RFC, https://github.com/fluxcd/flux2/blob/80669d71ef679b2a3018a958e1ac1a30c8a628f5/rfcs/0002-helm-oci/README.md?plain=1#L92-L93

If both spec.secretRef and a non-generic provider are present in the definition,
the controller will use the static credentials from the referenced secret.

it seems to be a different behavior.
But if the referred secret doesn't exist, then the reconciliation fails with secret not found error.

Looking at the code in OCIRepo reconciler, I believe it does the same.

@stefanprodan
Copy link
Member

if I create a secret with incorrect credentials and set the provider correctly, the result is a Ready

Let's fix this for both OCI implementations in a separate PR.

@stefanprodan stefanprodan merged commit 21bbb5c into fluxcd:main Aug 26, 2022
@souleb souleb deleted the enable-oidc-auth branch August 26, 2022 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/helm Helm related issues and pull requests area/oci OCI related issues and pull requests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use OCIRepository in HelmRelease HelmChart does not support auto login on GCR
5 participants