Skip to content

KEDA auth using externally managed TriggerAuthentication resource - #4558

Closed
qswinson wants to merge 1 commit into
knative-extensions:mainfrom
qswinson:keda-auth
Closed

qswinson wants to merge 1 commit into
knative-extensions:mainfrom
qswinson:keda-auth

Conversation

@qswinson

Copy link
Copy Markdown
Contributor

Follow up for #4516 comment

Proposed Changes

New Feature
Add optional KEDA autoscaler configuration to specify externally managed TriggerAuthentication or ClusterTriggerAuthentication resource. These are specified through the config-kafka-autoscaler ConfigMap or annotations on the scaled resource.

The annotation names:

  • autoscaling.eventing.knative.dev/authentication-name: The name of the KEDA resource.
  • autoscaling.eventing.knative.dev/authentication-kind: TriggerAuthentication or ClusterTriggerAuthentication. Only required if the KEDA resource is ClusterTriggerAuthentication.
  • autoscaling.eventing.knative.dev/aws-region: Required if using AWS IAM authentication for MSK. The KEDA Kafka source requires this property to be defined in the trigger.metadata. KEDA does not recognize this property in the authentication resource as it does with properties like sasl.

The primary use case for this feature is to support KEDA autoscaling when using AWS IAM authentication for MSK. This allows a different role to be used for the KEDA operator with a different set of permissions from the KNative Eventing services. By allowing the user to supply an externally managed resource, the complexity of configuring this KEDA authentication is removed from the KNative code and gives more flexibility to the user.

Release Note

Add optional autoscaler configurations to specify an externally managed KEDA TriggerAuthentication or ClusterTriggerAuthentication resource to be used by the KNative managed KEDA ScaledObject resource.

Docs

WIP

@knative-prow knative-prow Bot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. area/control-plane labels Oct 10, 2025
@knative-prow
knative-prow Bot requested review from matzew and pierDipi October 10, 2025 16:26
@codecov

codecov Bot commented Oct 10, 2025 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 70.37037% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 30.70%. Comparing base (06d47e7) to head (23cd4b6).
⚠️ Report is 104 commits behind head on main.

Files with missing lines Patch % Lines
control-plane/pkg/autoscaler/keda/keda.go 64.70% 8 Missing and 4 partials ⚠️
control-plane/pkg/autoscaler/keda/resources.go 66.66% 2 Missing and 1 partial ⚠️
...lane/pkg/reconciler/consumergroup/consumergroup.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4558      +/-   ##
==========================================
+ Coverage   30.10%   30.70%   +0.60%     
==========================================
  Files         294      294              
  Lines       19543    19591      +48     
==========================================
+ Hits         5883     6016     +133     
+ Misses      13207    13117      -90     
- Partials      453      458       +5     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@qswinson

Copy link
Copy Markdown
Contributor Author

/retest

@dprotaso

Copy link
Copy Markdown
Contributor

/assign @matzew @creydr @Cali0707 for review

@matzew

matzew commented Oct 22, 2025

Copy link
Copy Markdown
Contributor

CC @twoGiants

@Cali0707

Copy link
Copy Markdown
Member

The primary use case for this feature is to support KEDA autoscaling when using AWS IAM authentication for MSK. This allows a different role to be used for the KEDA operator with a different set of permissions from the KNative Eventing services. By allowing the user to supply an externally managed resource, the complexity of configuring this KEDA authentication is removed from the KNative code and gives more flexibility to the user.

@qswinson could you clarify this some more? Currently, Knative is managing the rest of the KEDA integration for these resources, so I'm a little hesitant to have this one edge case for the AWS bits around the trigger auth, especially since this would then need to be managed per-trigger by the user

Also re: different set of permissions - doesn't Eventing still need permissions to through AWS IAM to authenticate to these clusters anyway?

I could be missing something here, so please correct me anywhere you see fit.

Also cc @matzew @twoGiants for their thoughts

@twoGiants twoGiants left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi @qswinson!

Great to see you back and thanks again for your new contribution. Keep those contributions coming! 🥇

I have noticed quite big additions in test code and added my comments to it. It would be great if you could address them.

And I think hard coding the awsRegion is not the way to go. I would opt for a generic way of adding trigger metadata key-value pairs. Then its the users responsibility to use awsRegion for the key and us-west-1 for the value. Not sure how though 😆. Maybe something like that autoscaling.eventing.knative.dev/trigger-metadata-awsRegion: "us-west-1". This part autoscaling.eventing.knative.dev/trigger-metadata- is the one that doesn't change and after that the generic one.

And I have one last little request to you. After you finish your re-work I would kindly ask you to fully cleane up the code, proofread it one last time and address all PR review comments before you request the next review. That would be really helpful! Thank you 😃 👍!

Let me know if I can support in any way. You can also find me on the CNCF slack. Happy coding!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see you added quite a few tests here to cover the new logic you introduced in config.go. Thank you for taking care of code coverage 😸 👍. Keep adding tests whenever you add new logic.

Now lets dive a bit deeper. Unfortunately the test code does not have the code quality I'd expect. But we will get there, no worries. I can support you, just let me know if something is not clear.

I have a few questions about the tests you wrote:

  1. Why did you created a this test file here? There was none before because the config is tested implicitly in a different place.
  2. Do you know where config can be tested implicitly or how to figure that out?
  3. When you write unit tests for a class or a function always cover those things: conditions (if), loops (for, while), calculations/operations and polymorphism. Now you added a few new default values and extended the existing condition. It would be enough to write a test for each new condition case and one test for the default values. Why didn't you do that?

)

func TestDefaultConfig(t *testing.T) {
config := defaultConfig()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would avoid package level tests when you can. The rule of thumb is: prefer public api tests over package scoped tests. Add package level tests only if its really needed. Here it isn't.

}

// Helper function to check if a string contains a substring
func contains(s, substr string) bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Small hint, Go standard library contains this function => strings.Contains. Just use that :)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Again a big thanks for keeping the test coverage high! I really appreciate it 😸 👍.

This is also lot of code here and I am afraid it does need a bit of re-work. I have a few similar questions as before, it would really help me understand you thought process better if you address them 😸 :

  1. Why did you create this test file? There was none before which could an indication that it is tested somewhere else.
  2. Why did you create so many test cases in TestGenerateScaleTriggers which tests GenerateScaleTriggers and that has only a few conditions?
  3. Why on the other hand you created so few test cases in TestGenerateTriggerAuthentication which tests GenerateTriggerAuthentication which is huge with a ton of conditions?
  4. Why are you writing so many test cases for SetAutoscalingAnnotations which has barely any logic at all?

// AutoscalingAwsRegion is the annotation that refers to the AWS region of the MSK cluster.
// KEDA requires this to be set when using AWS IAM authentication as an explicit property
// in the trigger.metadata section.
AutoscalingAwsRegion = Autoscaling + "/aws-region"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not sure about this. I would avoid hard coding a provider. Maybe a more generic way to add trigger metadata key-value pairs via ConfigMap is the way to go. Wdys? @Cali0707 @matzew

// DefaultLagThreshold is the default value for AutoscalingLagThreshold.
DefaultLagThreshold = 100
// DefaultAuthenticationName is the default value for AutoscalingAuthenticationName.
DefaultAuthenticationName = ""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Empty values for defaults could also be no defaults then.

AutoscalerAuthentication: map[string]string{
AutoscalingAuthenticationName: DefaultAuthenticationName,
AutoscalingAuthenticationKind: DefaultAuthenticationKind,
AutoscalingAwsRegion: DefaultAwsRegion,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As mentioned above. I would not do this. Probably better a generic way to add trigger metadata key-value pairs.

AutoscalingLagThreshold: DefaultLagThreshold,
},
AutoscalerAuthentication: map[string]string{
AutoscalingAuthenticationName: DefaultAuthenticationName,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Default empty means you don't have to set them at all.

}

if *awsRegion != "" {
triggerMetadata["awsRegion"] = *awsRegion

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same here. Don't think hard coding awsRegion is a good idea. A more generic way is better.

return &i32, nil
}

func GetStringValueFromMap(dict map[string]string, key string, defaultValue string) (*string, error) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This returns either the defaultValue or an empty string or nil. Why empty string or nil? Does it really need the defaultValue if it's an empty string?

Can you elaborate? Thx! 👍

@knative-prow

knative-prow Bot commented Oct 23, 2025

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: qswinson
Once this PR has been reviewed and has the lgtm label, please ask for approval from cali0707. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@qswinson

Copy link
Copy Markdown
Contributor Author

@qswinson could you clarify this some more? Currently, Knative is managing the rest of the KEDA integration for these resources, so I'm a little hesitant to have this one edge case for the AWS bits around the trigger auth, especially since this would then need to be managed per-trigger by the user

This separates the authentication concerns in a platform agnostic manner. Right now KEDA authentication for Kafka must be the same as KNative authentication for Kafka. That makes it difficult to track what api calls are coming from which service regardless of authentication type or Kafka hosting provider. By giving the end user the option to use a separate authentication mechanism for Keda versus KNative, end users who need to track that kind of usage have the tools to do so.
I do think this is a generic solution and not an edge case for AWS. If the ability to define an externally defined TriggerAuthentication is not included, then this code will need to be updated to support creating TriggerAuthentication resources for AWS MSK.

Also re: different set of permissions - doesn't Eventing still need permissions to through AWS IAM to authenticate to these clusters anyway?

The permission issue comes down to IAM role permission policies and trust relationship policies. The role used by the Keda service account must be granted permission to assume every role that is referenced in a TriggerAuthentication resource and every role referenced in a TriggerAuthentication resource must have a trust relationship policy that grants the Keda service account permission to assume it.

If KNative Kafka Controller creates the TriggerAuthentication using the IAM role configured for the broker, then that role has to include the keda service account in its trust relationship. The Keda role must include broker IAM role in its permission policy. This then gives the Keda pod permission to do all IAM permissions granted to the Knative Kafka broker.

The diagram below illustrates how defining an external TriggerAuthentication or ClusterTriggerAuthentication separates the tight coupling of the KNative broker role and the Keda role.
Knative and Keda Auth - Single Account

@github-actions

Copy link
Copy Markdown
Contributor

This Pull Request is stale because it has been open for 90 days with
no activity. It will automatically close after 30 more days of
inactivity. Reopen with /reopen. Mark as fresh by adding the
comment /remove-lifecycle stale.

@github-actions github-actions Bot added lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Feb 13, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

This Pull Request is stale because it has been open for 90 days with
no activity. It will automatically close after 30 more days of
inactivity. Reopen with /reopen. Mark as fresh by adding the
comment /remove-lifecycle stale.

@github-actions github-actions Bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jul 2, 2026
@github-actions github-actions Bot closed this Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/control-plane lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants