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

Get credentials from GCP/Azure when needed #194

Merged
merged 1 commit into from
Jan 20, 2022

Conversation

somtochiama
Copy link
Member

@somtochiama somtochiama commented Nov 5, 2021

Closes #180
Closes #179

This pull request adds two flags (gcp-autologin-for-gcr and azure-autologin-for-acr) for autologin on GCP and Azure to their container registries.

This has been tested on GKE clusters with workload identities enabled and default service account.
This has been tested on an AKS w Managed Identities.

Further refactoring could be done to move implementation details of various cloud providers into a dedicated package.

Signed-off-by: Somtochi Onyekwere somtochionyekwere@gmail.com

@relu
Copy link
Member

relu commented Nov 8, 2021

This is a note for later but I think it would be better to get these implementations out of the controller, maybe moved to internal.

@somtochiama somtochiama changed the title Get credentials from GCP when needed Get credentials from GCP/Azure when needed Nov 9, 2021
@somtochiama somtochiama marked this pull request as ready for review November 10, 2021 16:40
@somtochiama somtochiama requested review from relu and hiddeco November 22, 2021 09:06
@squaremo squaremo self-requested a review November 22, 2021 10:44
Copy link
Member

@relu relu left a comment

Choose a reason for hiding this comment

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

Looking good, @somtochiama 👍
Added some comments regarding a few minor improvements.

Comment on lines 45 to 54
req, err := http.NewRequest("POST", exchangeUrl, strings.NewReader(parameters.Encode()))
if err != nil {
return "", fmt.Errorf("error constructing exchange request: %w", err)
}

req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(parameters.Encode())))

client := &http.Client{}
resp, err := client.Do(req)
Copy link
Member

Choose a reason for hiding this comment

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

There's a helper method that can be used for form POSTing in http. Here's the short variant of all of this 😄

Suggested change
req, err := http.NewRequest("POST", exchangeUrl, strings.NewReader(parameters.Encode()))
if err != nil {
return "", fmt.Errorf("error constructing exchange request: %w", err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(parameters.Encode())))
client := &http.Client{}
resp, err := client.Do(req)
resp, err := http.PostForm(exchangeUrl, parameters)

}

type Exchanger struct {
scheme string
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't seem like something that would ever be changed or overridden, should be safe to hardcode this as https in the resulting URL.

var authConfig authn.AuthConfig
gcpDefaultTokenURL := "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"

request, err := http.NewRequest("GET", gcpDefaultTokenURL, nil)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe use the const here

Suggested change
request, err := http.NewRequest("GET", gcpDefaultTokenURL, nil)
request, err := http.NewRequest(http.MethodGet, gcpDefaultTokenURL, nil)

controllers/imagerepository_controller.go Show resolved Hide resolved
Copy link
Member

@relu relu left a comment

Choose a reason for hiding this comment

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

Left just a few more comments.

return "", fmt.Errorf("failed to send token exchnage request: %w", err)
}

if resp.StatusCode != 200 {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if resp.StatusCode != 200 {
if resp.StatusCode != http.StatusOK {

}

if resp.StatusCode != 200 {
responseBytes, err := ioutil.ReadAll(resp.Body)
Copy link
Member

Choose a reason for hiding this comment

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

Might be a good idea to not use ioutil.ReadAll here, we don't know how large the response body can be and this can cause memory issues. See my comment below.

Do we know what type of responses we get? If it's JSON maybe we can extract only the relevant bits for the error message. If not, maybe try to only read at a maximum just a few bytes worth of data.

Comment on lines 55 to 61
responseBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %w", err)
}

var tokenResp tokenResponse
err = json.Unmarshal(responseBytes, &tokenResp)
Copy link
Member

Choose a reason for hiding this comment

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

ioutil.ReadAll loads everything into memory and it should be avoided whenever possible. Using the json Decoder would be more efficient.

Suggested change
responseBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %w", err)
}
var tokenResp tokenResponse
err = json.Unmarshal(responseBytes, &tokenResp)
var tokenResp tokenResponse
decoder := json.NewDecoder(resp.Body)
if err := decoder.Decode(&tokenResp); err != nil {
return "", err
}

}

func (e *Exchanger) ExchangeACRAccessToken(armToken string) (string, error) {
exchangeUrl := fmt.Sprintf("%s://%s/oauth2/exchange", "https", e.acrFQDN)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
exchangeUrl := fmt.Sprintf("%s://%s/oauth2/exchange", "https", e.acrFQDN)
exchangeUrl := fmt.Sprintf("https://%s/oauth2/exchange", e.acrFQDN)

@kingdonb
Copy link
Member

I've done some testing against the image somma/image-reflector-controller:test-autologin-c34c7cf34b1 on both Azure and GKE, and the feature was working all around for me.

$ flux get image policy -A
NAMESPACE       NAME    READY   MESSAGE                                                                                         LATEST IMAGE                                         
podinfo-staging podinfo True    Latest image tag for 'acrkingdontest.azurecr.io/stefanprodan/podinfo' resolved to: 5.0.0        acrkingdontest.azurecr.io/stefanprodan/podinfo:5.0.0

and on GCP:

$ flux get image policy -A
NAMESPACE               NAME    READY   MESSAGE                                                                 LATEST IMAGE                    
podinfo-production      podinfo True    Latest image tag for 'gcr.io/dx-kingdon/podinfo' resolved to: 5.0.0     gcr.io/dx-kingdon/podinfo:5.0.0

The testing involved was to follow basically the first half of the Image Update guide: create an ImageRepo and ImagePolicy, pointed at the private repository. Remove the flag to confirm that access does not happen without the newly added feature. When the flag is present, there should be no secretRef or other access management required, it should "just work."

I created the Azure cluster in an existing Resource Group through the portal with a "System-Managed Identity" and associated the cluster with a Container Registry on the same RG. I used Azure CNI and Calico policy enforcement, which probably doesn't matter, (but just to be complete) with Kubernetes 1.21 under the hood. The image repo created was definitely private. I used the Quickstart guide from Azure docs to "build and push" some example Podinfo images FROM stefanprodan/podinfo:5.0.0.

https://docs.microsoft.com/en-us/azure/container-registry/container-registry-quickstart-task-cli

The Dockerfiles for example are in here: https://github.com/kingdonb/bootstrap-repo/tree/main/apps/base/podinfo - they are very sparse. I just needed two images so I could confirm they were both discovered successfully when the ImageRepo is reconciled.

I did the same test on GCR basically, creating a GKE cluster with Workload Identity enabled, then building the same images from the tutorial for Google Cloud Build. This testing method made it possible for me to avoid using my local network or any local build nodes 👍 I placed the images in a new repository in the same project-id that my cluster was created in. I assume this is using the new "Artifact Registry" protocol but I haven't looked deeply into it yet. (Maybe separate validation is still needed for that.) I just used the most obvious docs and searched for anything that I didn't know, I'm only marginally familiar with both cloud vendors.

https://cloud.google.com/build/docs/building/build-containers

The Workload Identity automatically authorized the project repository in the same workspace (project) and as I was able to push images with the gcloud client, that were then discovered without issue by the image-reflector-controller, with a set of manifests in and centered around this one: https://github.com/kingdonb/bootstrap-repo/blob/main/apps/production/podinfo/imagerepo.yaml

After confirming these both worked successfully with the flags:

https://github.com/kingdonb/bootstrap-repo/blob/75fc7f8822f1850d4046700ce4281c39ac5e4bfd/clusters/gke-geekingdon/flux-system/kustomization.yaml#L16
and
https://github.com/kingdonb/bootstrap-repo/blob/75fc7f8822f1850d4046700ce4281c39ac5e4bfd/clusters/aks-kuberkingdon/flux-system/kustomization.yaml#L16

I'm happy to report the feature works without issue on both of these! Removing the flag made for an authentication error that looked reasonable, (I didn't capture it.) I'll be repeating the testing later today, in case there are any questions or issues in the critical path that other reviewers wanted to make sure are properly addressed. Please let me know.

internal/azure/exchanger.go Outdated Show resolved Hide resolved
Copy link
Member

@relu relu left a comment

Choose a reason for hiding this comment

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

Great, thank you @somtochiama! 💯

@relu
Copy link
Member

relu commented Nov 23, 2021

Could you please also resolve the conflicts?

@kingdonb
Copy link
Member

I have some surprising results after testing further on GKE,

I created a new cluster and enabled Workload Identity, but the reflector controller can no longer reach the auth, or something else has gone wrong:

{"level":"error","ts":"2021-11-23T20:02:18.456Z","logger":"controller-runtime.manager.controller.imagepolicy","msg":"Reconciler error","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImagePolicy","name":"podinfo","namespace":"podinfo-production","error":"version list argument cannot be empty"}
{"level":"info","ts":"2021-11-23T20:02:21.686Z","logger":"controller-runtime.manager.controller.imagerepository","msg":"Logging in to GCP GCR for gcr.io/dx-kingdon/podinfo","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImageRepository","name":"podinfo","namespace":"podinfo-production"}
{"level":"error","ts":"2021-11-23T20:02:21.878Z","logger":"controller-runtime.manager.controller.imagerepository","msg":"Reconciler error","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImageRepository","name":"podinfo","namespace":"podinfo-production","error":"GET https://gcr.io/v2/dx-kingdon/podinfo/tags/list?n=1000: DENIED: Failed to read tags for host 'gcr.io', repository '/v2/dx-kingdon/podinfo/tags/list?n=1000'"}
{"level":"info","ts":"2021-11-23T20:03:59.667Z","logger":"controller-runtime.manager.controller.imagerepository","msg":"Logging in to GCP GCR for gcr.io/dx-kingdon/podinfo","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImageRepository","name":"podinfo","namespace":"podinfo-production"}
{"level":"error","ts":"2021-11-23T20:03:59.693Z","logger":"controller-runtime.manager.controller.imagepolicy","msg":"Reconciler error","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImagePolicy","name":"podinfo","namespace":"podinfo-production","error":"version list argument cannot be empty"}
{"level":"error","ts":"2021-11-23T20:03:59.875Z","logger":"controller-runtime.manager.controller.imagerepository","msg":"Reconciler error","reconciler group":"image.toolkit.fluxcd.io","reconciler kind":"ImageRepository","name":"podinfo","namespace":"podinfo-production","error":"GET https://gcr.io/v2/dx-kingdon/podinfo/tags/list?n=1000: DENIED: Failed to read tags for host 'gcr.io', repository '/v2/dx-kingdon/podinfo/tags/list?n=1000'"}

This while the images can be deployed in the cluster, so apparently the project association is correct, something else has gone wrong.

I suspect this is probably a configuration error, although I'm not sure what can have gone wrong, I have the flag enabled and my image is at:

images: # []
- name: ghcr.io/fluxcd/image-reflector-controller
  newName: docker.io/somma/image-reflector-controller
  newTag: test-autologin-c34c7cf34b1

but the registry cannot be scanned for ImageRepository resources. Is there somewhere else to check for debugging errors?

@kingdonb
Copy link
Member

@somtochiama sent me some docs about Workload Identity that I hadn't seen before. It looks like my previous test was not using workload identity, but the default service account instead. I will go back and repeat it after I work out my Workload Identity issues to confirm. Anyway just to add to this report, my configuration issue is definitely a configuration issue.

@somtochiama
Copy link
Member Author

somtochiama commented Jan 11, 2022

I am adding some notes here for testing this on GCP. I will write more detailed documentation next and make a commit.

  1. Enable Workload Identiy on the cluster (Docs: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#enable_on_cluster. If you have an existing cluster, don't forget to migrate applications to workload identity. See https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#migrate_applications_to
  2. Create a GCP service account that has access to GCR
  3. Bind the GCP service account to the image-reflector-controller service account (Docs)
  4. Customize the flux manifest so that it uses the image from this pull request and also annotates the image-reflector-controller service account with the iam.gke.io/gcp-service-account label

Example of gotk-patches.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: image-reflector-controller
  namespace: flux-system
spec:
  template:
    spec:
      containers:
      - name: manager
        image: somma/image-reflector-controller:test-autologin-d5255a590
        args:
          - --events-addr=http://notification-controller.flux-system.svc.cluster.local/
          - --watch-all-namespaces
          - --log-level=info
          - --log-encoding=json
          - --enable-leader-election
          - --gcp-autologin-for-gcr
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: image-reflector-controller
  namespace: flux-system
  annotations:
    iam.gke.io/gcp-service-account: "service-account-name@project-id.iam.gserviceaccount.com"

@stefanprodan
Copy link
Member

The bootstrap docs along with #193 should be placed in https://fluxcd.io/docs/guides/image-update/#imagerepository-cloud-providers-authentication

Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

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

Solid work @somtochiama, thank you. I've made a few suggestions and raised some questions -- nothing drastic, so I've approved this PR.

(The first commit seems to have a duplicate sign-off -- something to amend if you end up doing further work here.)

controllers/imagerepository_controller.go Show resolved Hide resolved
}, nil
}

// List from https://github.com/kubernetes/kubernetes/blob/master/pkg/credentialprovider/azure/azure_credentials.go
Copy link
Member

Choose a reason for hiding this comment

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

Probably better to link to the code at a specific revision, or (more readably) a release tag, otherwise it can change out from under you.

.github/workflows/scan.yml Show resolved Hide resolved
ClientCert = "certFile"
ClientKey = "keyFile"
CACert = "caFile"
azureCloudConfigJsonFile = "/etc/kubernetes/azure.json"
Copy link
Member

Choose a reason for hiding this comment

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

This const isn't mentioned in the rest of the diff -- perhaps it's a holdover from the "mount the file from the host" code?

if err != nil {
return authConfig, err
}

Copy link
Member

Choose a reason for hiding this comment

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

Provided Do didn't return an error, you should Close() the response body, and probably read it to the end too (see the comment in https://pkg.go.dev/net/http#Client.Do). You can do io.Copy(io.Discard, response.Body) (or perhaps better, io.Copy(io.Discard, &io.LimitedReader{R: response.Body, N: maxResponseLength}) for some maxResponseLength).

Copy link
Member

Choose a reason for hiding this comment

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

You should really do this in all cases other than getting an error back from Do. As it stands, the body will only be read to the end and closed if the status was OK and a JSON value could be decoded; but, it's entirely possible, e.g., that a 40x status would have body content.
It's a pain I know, because you are forced to either repeat code or defer (and throw away errors) -- since no (other) I/O happens after the request, I think using defer is fine.


// getAzureLoginAuth returns authentication for ACR. The details needed for authentication
// are gotten from environment variable so there is not need to mount a host path.
func getAzureLoginAuth(ref name.Reference) (authn.AuthConfig, error) {
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be wise to pass the context from Reconcile through to this func, for it to use in requests (and likewise for the GCR -- and ECR, for that matter). What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think so too.


For [<abbr title="Elastic Kubernetes Service">EKS</abbr>][EKS] and [<abbr title="Elastic Container Registry">ECR</abbr>][ECR],
the flag is `--aws-autologin-for-ecr`.
For [<abbr title="Googke Kubernetes Enginer">GKE</abbr>][GKE] and [<abbr title="Google Container Registry">GCR</abbr>][GCR],
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
For [<abbr title="Googke Kubernetes Enginer">GKE</abbr>][GKE] and [<abbr title="Google Container Registry">GCR</abbr>][GCR],
For [<abbr title="Google Kubernetes Engine">GKE</abbr>][GKE] and [<abbr title="Google Container Registry">GCR</abbr>][GCR],

<3 for using <abbr> consistently!

the flag is `--aws-autologin-for-ecr`.
For [<abbr title="Googke Kubernetes Enginer">GKE</abbr>][GKE] and [<abbr title="Google Container Registry">GCR</abbr>][GCR],
the flag is `--gcp-autologin-for-gcr`.
For [<abbr title="Azure Kubernetes Service">AKS</abbr>][AKS] and [<abbr title="Azure Container Registry">EKS</abbr>][ACR],
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
For [<abbr title="Azure Kubernetes Service">AKS</abbr>][AKS] and [<abbr title="Azure Container Registry">EKS</abbr>][ACR],
For [<abbr title="Azure Kubernetes Service">AKS</abbr>][AKS] and [<abbr title="Azure Container Registry">ACR</abbr>][ACR],

Copy link
Member

Choose a reason for hiding this comment

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

So .. many .. TLAs ... 😄
(to be clear, I'm commenting on Tech, not on the docs here)

internal/azure/exchanger.go Show resolved Hide resolved
go.mod Outdated Show resolved Hide resolved
@somtochiama somtochiama requested a review from squaremo January 13, 2022 09:26
@kingdonb
Copy link
Member

It's noted elsewhere, but following up that I have tested GKE Workload Identity to connect with gcr.io registries successfully

However I was not able to get artifact registry working through workload identity, even after separately granting the role for role/artifactregistry.reader I still get this error:

podinfo-artifact-registry	False	GET https://us-central1-docker.pkg.dev/v2/token?scope=repository%3Adx-kingdon%2Fgeekingdon-images%2Fpodinfo%3Apull&service=us-central1-docker.pkg.dev: DENIED: Permission "artifactregistry.repositories.downloadArtifacts" denied on resource "projects/dx-kingdon/locations/us-central1/repositories/geekingdon-images" (or it may not exist)	                         	False

I guess the culprit is here: https://github.com/fluxcd/image-reflector-controller/pull/194/files#diff-922fcbfbe2565443329918a2b0d49b2b03588007ec6464a20d3feb824f3f80a2R735-R737

it needs to match pkg.dev as well (and possibly others), else artifact registry won't be considered as the same as container registry. I'm giving it a shot and testing it on my own, I think I have everything I need to compile a version of image-reflector-controller 👍

@kingdonb
Copy link
Member

kingdonb commented Jan 14, 2022

Yey, that worked:

$ flux get image repository
NAME                     	READY	MESSAGE                      	LAST SCAN                	SUSPENDED
podinfo                  	True 	successful scan, found 2 tags	2022-01-14T10:58:16-05:00	False
podinfo-artifact-registry	True 	successful scan, found 2 tags	2022-01-14T10:58:16-05:00	False

Some research indicates artifact registry OCI addresses for GCP will always be of the form *-docker.pkg.dev

Here is the commit that enables artifact registry, if you'd like to pull it into your branch:

kingdonb/image-reflector-controller:2eb0be8

The page that clued me into the structure is here, https://cloud.google.com/artifact-registry/docs/access-control – it would be good to have a more canonical source than that, as there may still be other addresses that can host Artifact Registry and they will not work without further changes. Hopefully this address format is invariant and we can count on it everywhere 🤷

I tested this version and it works with both gcr.io and *-docker.pkg.dev so covers both the old GCR (deprecated) and the new "Artifact Registry" successor, which I haven't heard much about (but couldn't avoid tripping over in the GCP New User onboarding workflows. It's pretty clear they don't want you to use gcr.io anymore.)

@kingdonb
Copy link
Member

kingdonb commented Jan 14, 2022

The other thing I might want to add to the docs:

gcloud projects add-iam-policy-binding <PROJECT> --member "serviceAccount:<GCP-SA-NAME>@<PROJECT>.iam.gserviceaccount.com" --role roles/artifactregistry.reader
gcloud projects add-iam-policy-binding <PROJECT> --member "serviceAccount:<GCP-SA-NAME>@<PROJECT>.iam.gserviceaccount.com" --role roles/containerregistry.ServiceAgent

It was not very difficult to discover these roles, but we can help the users by spelling it out.

I'm not sure I have selected the minimal roles either. There is no containerregistry.reader to go with artifactregistry.reader, only containerregistry.ServiceAgent, and after applying both of the roles I found (and possibly some others, who knows exactly what I did here, I'm not 100%), I wind up with this set of bindings which seems like it might likely be in excess of what I needed:

Updated IAM policy for project [dx-kingdon].
bindings:
- members:
  - serviceAccount:kingdon-test-gcr-sa@dx-kingdon.iam.gserviceaccount.com
  role: roles/artifactregistry.reader
- members:
  - serviceAccount:service-1041773995540@gcp-sa-artifactregistry.iam.gserviceaccount.com
  role: roles/artifactregistry.serviceAgent
- members:
  - serviceAccount:1041773995540@cloudbuild.gserviceaccount.com
  role: roles/cloudbuild.builds.builder
- members:
  - serviceAccount:service-1041773995540@gcp-sa-cloudbuild.iam.gserviceaccount.com
  role: roles/cloudbuild.serviceAgent
- members:
  - serviceAccount:service-1041773995540@compute-system.iam.gserviceaccount.com
  role: roles/compute.serviceAgent
- members:
  - serviceAccount:service-1041773995540@container-engine-robot.iam.gserviceaccount.com
  role: roles/container.serviceAgent
- members:
  - serviceAccount:kingdon-test-gcr-sa@dx-kingdon.iam.gserviceaccount.com
  - serviceAccount:service-1041773995540@containerregistry.iam.gserviceaccount.com
  role: roles/containerregistry.ServiceAgent
- members:
  - serviceAccount:1041773995540-compute@developer.gserviceaccount.com
  - serviceAccount:1041773995540@cloudservices.gserviceaccount.com
  role: roles/editor
- members:
  - user:kingdon@weave.works
  role: roles/owner
- members:
  - serviceAccount:service-1041773995540@gcp-sa-pubsub.iam.gserviceaccount.com
  role: roles/pubsub.serviceAgent
etag: BwXVjQ36L8E=
version: 1

Someone who knows GCP well enough to say how to select the minimal roles should review that information for correctness.

(Perhaps the nasty mess of roles required just to get "container registry / reader" access is part of the motivation to deprecate gcr.io - I'm not sure if I'm the one that added cloud build role or if it came with containerregistry.ServiceAgent but push access is something that we definitely don't need here, and it's obvious how to set that up for artifact registry, but not so clear at least as a beginner, with all the different role primitives associated with the gcr agent role.)

@kingdonb
Copy link
Member

This was the doc from GCP re: Workload Identity that gave the most clarity about what roles were available and what role primitives composed them: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles

@stefanprodan
Copy link
Member

@somtochiama can you please rebase and run make fmt.

Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>

Signed-off-by: Somtochi Onyekwere <somtochionyekwere@gmail.com>
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 @somtochiama 🏅

@stefanprodan stefanprodan added the enhancement New feature or request label Jan 20, 2022
@stefanprodan stefanprodan merged commit 4ca33b4 into fluxcd:main Jan 20, 2022
Copy link
Member

@squaremo squaremo left a comment

Choose a reason for hiding this comment

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

Thanks for following through on my comments -- one adjustment, then I think this is good to go.

if err != nil {
return authConfig, err
}

Copy link
Member

Choose a reason for hiding this comment

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

You should really do this in all cases other than getting an error back from Do. As it stands, the body will only be read to the end and closed if the status was OK and a JSON value could be decoded; but, it's entirely possible, e.g., that a 40x status would have body content.
It's a pain I know, because you are forced to either repeat code or defer (and throw away errors) -- since no (other) I/O happens after the request, I think using defer is fine.

@stefanprodan
Copy link
Member

@somtochiama can you please open a new PR to address @squaremo comment, sorry I missed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Azure/ACR "autologin" GKE/GCR "autologin"
6 participants