Skip to content
This repository was archived by the owner on Nov 5, 2024. It is now read-only.

Support IAM role auth in SQS source#248

Merged
antoineco merged 2 commits into
triggermesh:mainfrom
antoineco:sqs-iamroles
Nov 7, 2021
Merged

Support IAM role auth in SQS source#248
antoineco merged 2 commits into
triggermesh:mainfrom
antoineco:sqs-iamroles

Conversation

@antoineco

@antoineco antoineco commented Nov 5, 2021

Copy link
Copy Markdown
Contributor

Closes #244 (long overdue!)

Adds support for IAM Role authentication to the AWS SQS source.

Other sources will follow once we are confident this is working smoothly.


Demo

Create a SQS source with iamRole selected as the auth method:

apiVersion: sources.triggermesh.io/v1alpha1
kind: AWSSQSSource
metadata:
  name: sample1
spec:
  arn: arn:aws:sqs:eu-central-1:123456789012:foo

  auth:
    iamRole: arn:aws:iam::123456789012:role/foo

  sink:
    ref:
      apiVersion: v1
      kind: Service
      name: event-display
$ kubectl create -f sample1.yaml
awssqssource.sources.triggermesh.io/sample1 created

Notice that a ServiceAccount named after the source gets created, instead of the usual shared ServiceAccount:

$ kubectl get serviceaccount
NAME                     SECRETS   AGE
awssqssource-i-sample1   1         114s

This ServiceAccount is annotated with the configured IAM role:

$ kubectl get serviceaccount awssqssource-i-sample1 -o jsonpath='{.metadata.annotations}'
{"eks.amazonaws.com/role-arn":"arn:aws:iam::123456789012:role/foo"}

The receive adapter was configured to use this ServiceAccount, and not the shared one:

$ kubectl get deployment awssqssource-sample1 -o jsonpath='{.spec.template.spec.serviceAccountName}'
awssqssource-i-sample1

Other SQS sources with standard credentials authentication can still be created alongside the ones with iamRole authentication, and these use the shared ServiceAccount as usual:

$ kubectl create -f sample2.yaml
awssqssource.sources.triggermesh.io/sample2 created
$ kubectl get serviceaccount
NAME                     SECRETS   AGE
awssqssource-adapter     1         9s
awssqssource-i-sample1   1         2m
$ kubectl get deployment awssqssource-sample2 -o jsonpath='{.spec.template.spec.serviceAccountName}'
awssqssource-adapter

@antoineco antoineco marked this pull request as ready for review November 5, 2021 20:40

@odacremolbap odacremolbap left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

extremely clean as always.
+1, although I'm hesitant on if this should be moved from reconciler/testing:

// ServiceAccountOption is a functional option for a ServiceAccount.
type ServiceAccountOption func(*corev1.ServiceAccount)

to somewhere else and be used by sources' reconciler/common and sources API.

@antoineco

Copy link
Copy Markdown
Contributor Author

@odacremolbap yes good idea, this part is a bit of a mess because tests have custom functional options for readability ("make this deployment ready", "enable this auth mode", ...).

I'll move the signature elsewhere and update accordingly.

@antoineco

Copy link
Copy Markdown
Contributor Author

@odacremolbap suggestion addressed in d341018.

@isaac88

isaac88 commented Apr 20, 2022

Copy link
Copy Markdown

@antoineco really great job. It's working like a charm.

@antoineco

Copy link
Copy Markdown
Contributor Author

Hey @isaac88, appreciate the feedback! 🙌

@marcantoine-bibeau

Copy link
Copy Markdown

Hi @antoineco , I'm starting to investigate KNative and Triggermesh, Seems very nice :) I have a question regarding ServiceAccount that prevent me of having all that working.

That PR creates a new ServiceAccount awssqssource-i-sample1 with the annotation eks.amazonaws.com/role-arn":"arn:aws:iam::123456789012:role/foo. Nice but I'm having 1 problem (or it is Function As Designed)

With my current understanding (how I work on my cluster), not only the AWS role needs to be created but the ServiceAccount needs to be added in the OIDC "Trust Relationships" policy to be able to call sts:AssumeRoleWithWebIdentity in order to get proper accesses. (See https://docs.aws.amazon.com/eks/latest/userguide/create-service-account-iam-policy-and-role.html).

Is there a way I do not know to have all that properly configured automatically?
Do I need to configure that somehow by another mean(s)? If so, What is this PR for exactly if the created role is not usable?

Thanks a lot in advance!

@antoineco

antoineco commented Aug 12, 2022

Copy link
Copy Markdown
Contributor Author

@marcantoine-bibeau full disclosure: I no longer work on that project, but I can comment on this specific concern.

It is true that the 1:1 relationship between an IAM role and a Kubernetes service account makes the management of IAM roles in EKS particularly tedious, and you are not the only one to believe some things should be improved: aws/containers-roadmap#1408 (and even this enhancement wouldn't remove the aforementioned restriction).

I'm not aware of any obscure workaround either, unfortunately. Your org needs to have processes and automation in place to be able to deliver IAM roles quickly to the developers that need them (some sort of on-demand credentials provisioning service, based on something like Vault, maybe?). Without such facility, I'm afraid some manual work (update your trusted entities) will be required prior to being able to attach an IAM role to TriggerMesh's event sources.

@marcantoine-bibeau

Copy link
Copy Markdown

@antoineco At least with your answer I understand that I was not missing something ;) I have some workaround with CD in mind until aws/containers-roadmap#1408 is addressed!

Thanks a LOT for your reply, I really appreciate!

@jmcx

jmcx commented Jan 10, 2023

Copy link
Copy Markdown
Contributor

Hi all,

FYI we now have IAM role auth for all AWS targets, as of TriggerMesh 1.23: https://github.com/triggermesh/triggermesh/releases/tag/v1.23.0

Cheers

@mikhno-s

mikhno-s commented Feb 1, 2023

Copy link
Copy Markdown

@jmcx But I already have the service account with an added role that is already in OIDC "Trust Relationships".
And now, after deploying each AWSSQSSource I need to update OIDC "Trust Relationships" policy because pod works under awssqssource-i-{sqs_source_name} Service account that is not in Trust Relationships.

@sebgoa

sebgoa commented Feb 2, 2023

Copy link
Copy Markdown
Member

@mikhno-s Hi, are you saying that you did an upgrade and that it broker your config ? If yes can you tell us from which version to what version ?

@mikhno-s

mikhno-s commented Feb 2, 2023

Copy link
Copy Markdown

I deployed triggermesh 1.23.0 with only one CRD that I need - awssqssources.sources.triggermesh.io

After I added triggermesh-controller service account to OIDC Trust Relationships that allows any pod that use this service account do aws api calls, to sqs api in this case.

Then, I created AWSSQSSource with spec:

apiVersion: sources.triggermesh.io/v1alpha1
kind: AWSSQSSource
metadata:
  name: sqs-guide
  namespace: triggermesh
spec:
spec:
  arn: arn:aws:sqs:us-west-2:0000000000:triggermesh
  auth:
    iamRole: arn:aws:iam::0000000000:role/triggermesh-role
  sink:
...

And then I checked logs of created pod - awssqssource-sqs-guide-... and it was saying that cannot perform assume role, that is obvious because the AWSSQSSource created a new service account awssqssource-i-sqs-guide and run the pod under this account. And error appears because awssqssource-i-sqs-guide account was not added to OIDC Trust Relationships.
After adding it - everything works well.

My Q is - how can I configure under which service accounts these sources will be run? Like I don't mind having all pods run by trigger mesh to be under one service account which can be added to OIDC Trust Relationships.

Because otherwise, I will need to update OIDC Trust Relationships after adding each aws source or target.

@antoineco

Copy link
Copy Markdown
Contributor Author

@mikhno-s indeed, as you discovered users must create one IAM Role and one Trust Relationship per Service Account (hence, per source instance). I agree with you, this is tedious and annoying.

Would it help if the API was updated to allow users to "pin" the Service Account name?

 apiVersion: sources.triggermesh.io/v1alpha1
 kind: AWSSQSSource
 metadata:
   name: sample1
 spec:
   arn: arn:aws:sqs:eu-central-1:123456789012:foo
 
   auth:
-    iamRole: arn:aws:iam::123456789012:role/foo
+    iamRole:
+      arn: arn:aws:iam::123456789012:role/foo
+      serviceAccount: my-manually-created-service-account
 
   sink:
     ref:
       apiVersion: v1
       kind: Service
       name: event-display

Or maybe a less intrusive way to gradually add this feature could be to introduce an annotation instead, as a first iteration:

 apiVersion: sources.triggermesh.io/v1alpha1
 kind: AWSSQSSource
 metadata:
   name: sample1
+  annotations:
+    alpha.triggermesh.io/aws-iam-service-account: my-manually-created-service-account
 spec:
   arn: arn:aws:sqs:eu-central-1:123456789012:foo
 
   auth:
     iamRole: arn:aws:iam::123456789012:role/foo
 
   sink:
     ref:
       apiVersion: v1
       kind: Service
       name: event-display

The downside is that your IAM Role must a wider permission range (read-write to all possible SQS sources).

@mikhno-s

mikhno-s commented Feb 2, 2023

Copy link
Copy Markdown

@antoineco Probably it's better to add an optional spec.iamRole.serviceAccount to allow users to control under which serviceAcc source pods are operating.

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.

Support alternative auth methods such as Kube2IAM and IAM Roles for Service Accounts

7 participants