-
Notifications
You must be signed in to change notification settings - Fork 137
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
Add support for EKS Pod Identity #416
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #416 +/- ##
==========================================
+ Coverage 49.67% 52.62% +2.94%
==========================================
Files 9 11 +2
Lines 781 952 +171
==========================================
+ Hits 388 501 +113
- Misses 383 436 +53
- Partials 10 15 +5 ☔ View full report in Codecov by Sentry. |
auth/auth.go
Outdated
return nil, err | ||
} | ||
credProvider := NewIRSACredentialProvider(p.stsClient, *roleArn, p.region) | ||
config, err = credProvider.GetAWSConfig(fetcher) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config, err = credProvider.GetAWSConfig(fetcher)
if err != nil {
return nil, err
}
is common to both blocks of the if
statement, it can be extracted out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made change in commit c3ca813
auth/auth.go
Outdated
} | ||
} | ||
|
||
func (p *PodIdentityCredentialProvider) GetAWSConfig(fetcher *authTokenFetcher) (*aws.Config, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we move the two credential providers to their own files in a subfolder?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean creating a separate folder/package similar to auth
? I didn't do it because moving credential providers
to a new folder would also require moving authTokenFetcher at the same time (otherwise it causes circular dependency since credential provider
and auth
try to import each other). auth
is pretty much empty after moving out those 2 big pieces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the change in commit 703570b
auth/auth.go
Outdated
return podIdentityAgentEndpointIPv4 | ||
}() | ||
|
||
var podIdentityAgentEndpoint = defaultPodIdentityAgentEndpoint |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is defaultPodIdentityAgentEndpoint used anywhere else? If not you can remove the extra assignment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaultPodIdentityAgentEndpoint
is used in tests. The endpoint is overridden in test, so assign it back to default state after test completion.
auth/auth.go
Outdated
return nil, roleErr | ||
} | ||
credProvider := NewIRSACredentialProvider(p.stsClient, *roleArn, p.region) | ||
config, err = credProvider.GetAWSConfig(fetcher) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you missed config, err = credProvider.GetAWSConfig(fetcher)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for missing this. corrected in commit 703570b
auth/auth.go
Outdated
config, err = credProvider.GetAWSConfig(fetcher) | ||
|
||
} else { | ||
roleArn, roleErr := p.getRoleARN() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check should be the responsibility of the IRSA credential provider, let's move it to that provider's implementation in its constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the move in commit 703570b
@@ -0,0 +1,279 @@ | |||
package credential_provider |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also split this test file into two test files for both implementations of the credential providers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the change in commit 539f715
server/server.go
Outdated
} | ||
|
||
if usePodIdentity { | ||
klog.Infof("Using Pod Identity for authentication in namespace: %s, service account: %s", nameSpace, svcAcct) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These can be logged from here for better encapsulation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made the change in commit 539f715
@@ -53,6 +53,10 @@ spec: | |||
env: | |||
- name: AWS_USE_FIPS_ENDPOINT | |||
value: {{ .Values.useFipsEndpoint | quote }} | |||
- name: POD_IP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for good measure, let's leave a comment above this explaining that this is needed for the pod identity agent to choose between IPV4/IPV6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added in commit 539f715
examples/ExampleDeployment-IRSA.yaml
Outdated
spec: | ||
selector: | ||
app: nginx | ||
app: nginx-irsas |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like an extra trailing 's'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in commit 4d4df72. Thank you for catching!
func NewAuth( | ||
ctx context.Context, | ||
region, nameSpace, svcAcc string, | ||
region, nameSpace, svcAcc, podName string, | ||
usePodIdentity bool, | ||
k8sClient k8sv1.CoreV1Interface, | ||
) (auth *Auth, e error) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do not use sess nor stsClient when usePodIdentity
is true. Can move the sts.new(sess)
call up here and condition it all on !usePodIdentity
(setting stsClient to nil otherwise)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change made in commit 4d4df72
README.md
Outdated
@@ -8,14 +8,14 @@ AWS offers two services to manage secrets and parameters conveniently in your co | |||
## Installation | |||
|
|||
### Requirements | |||
* Amazon Elastic Kubernetes Service (EKS) 1.17+ running an EC2 node group (Fargate node groups are not supported **[^1]**) | |||
* Amazon Elastic Kubernetes Service (EKS) 1.24+ running an EC2 node group (Fargate node groups are not supported **[^1]**) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am guessing this is being driven by Pod Identity only being supported on 1.24. I know 1.17 is no longer supported but this does not match what is required by the helm chart and if we change that it could break users running ancient installations out there who need to reload this driver for some reason.
Instead, we could just leave this at 1.17 and mention somewhere below that using Pod Identity requires EKS 1.24.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change made in commit 4d4df72
- name: POD_IP # This is needed to choose between IPv4 and IPv6 Pod Identity Agent endpoint | ||
valueFrom: | ||
fieldRef: | ||
fieldPath: status.podIP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all inside an {{- if .Values.useFipsEndpoint }}
condition so when using the helm chart install option it will never be set unless the administrator turns on FIPS. We could move the "if FIPS" condition to be just around the FIP env variable, but it would be better to just not need to pass in the address in configuration and dynamically determine the address. See comments below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed setting POD_IP env variable in daemonset template and installers in commit 4d4df72
var defaultPodIdentityAgentEndpoint = func() string { | ||
isIPv6, err := isIPv6() | ||
if err != nil { | ||
klog.Warningf("Error determining IP version: %v. Defaulting to IPv4 endpoint", err) | ||
return podIdentityAgentEndpointIPv4 | ||
} | ||
|
||
if isIPv6 { | ||
klog.Infof("Using Pod Identity Agent IPv6 endpoint") | ||
return podIdentityAgentEndpointIPv6 | ||
} | ||
klog.Infof("Using Pod Identity Agent IPv4 endpoint") | ||
return podIdentityAgentEndpointIPv4 | ||
}() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking up the address type is cumbersome and even if we get it right, there are a lot of ways the network could get mis-configured. A more reliable approach is to just try both addresses in quick succession. Try IPV4 with a 100ms timeout, and if that fails log the error as a warning and then try IPV6 with the same timeout and only fail if both tries fail.
This adds a slight penalty for IPV6 only configurations so we would also want to give the option to turn off IPV4. To make this general we would probably let the user turn off either (maybe something like preferedAddressType = IPV4/IPV6).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
introduce a new optional parameter preferredAddressType
in commit 4d4df72.
Implemented behavior:
- if
preferredAddressType
is set to ipv4, only try ipv4 - if
preferredAddressType
is set to ipv6, only try ipv6 - if
preferredAddressType
is not set or is set with value other than ipv4/ipv6, try ipv4 first with 100ms timeout and then try ipv6. if both tries fail, error out.
}, | ||
} | ||
|
||
// Use the K8s API to fetch the token from the OIDC provider. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case there likely will not be an OIDC provider.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated in commit 4d4df72
if preferredAddressType != "" { | ||
klog.Warningf("Unknown preferred address type: %s, falling back to auto selection", preferredAddressType) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Directly failing on bad configuration is the best option. It makes problems easier to find and it is difficult to add in later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made change in commit c88e0f6
switch p.preferredEndpoint { | ||
case preferenceIPv4: | ||
klog.Infof("Using preferred Pod Identity Agent IPv4 endpoint") | ||
config, err := p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv4) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get AWS config from pod identity agent IPv4 endpoint: %+v", err) | ||
} | ||
return config, nil | ||
case preferenceIPv6: | ||
klog.Infof("Using preferred Pod Identity Agent IPv6 endpoint") | ||
config, err := p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv6) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get AWS config from pod identity agent IPv6 endpoint: %+v", err) | ||
} | ||
return config, nil | ||
default: | ||
klog.Infof("Using auto Pod Identity Agent endpoint selection") | ||
config, err := p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv4) | ||
if err != nil { | ||
klog.Warningf("IPv4 endpoint attempt failed: %+v. Trying IPv6 endpoint", err) | ||
config, err = p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv6) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get AWS config from pod identity agent: %+v", err) | ||
} | ||
} | ||
return config, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a little more natural to solve things in general by avoiding handling each case separately. For example:
if( p.preferredEndpoint == preferenceIPv4 || p.preferredEndpoint == preferenceAuto ) {
config, err := p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv4)
if err != nil {
klog.Warningf("IPv4 endpoint attempt failed: %+v.", err)
} else {
return config, nil;
}
}
if( p.preferredEndpoint == preferenceIPv6 || p.preferredEndpoint == preferenceAuto ) {
config, err := p.getAWSConfigFromPodIdentityAgent(token, podIdentityAgentEndpointIPv6)
if err != nil {
klog.Warningf("IPv6 endpoint attempt failed: %+v.", err)
}
}
if err != nil {
return nil, fmt.Errorf("failed to get AWS config from pod identity agent: %+v", err);
}
return config, nil;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made change in commit c88e0f6. This does look a lot cleaner. Thank you!
Issue #, if available: Closes #300
Description of changes:
Introduce an optional parameter usePodIdentity to support EKS Pod Identity
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.