-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Simplified form of IAM Roles for ServiceAccounts #9352
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: justinsb The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
f6f0218
to
e23a81b
Compare
So we think this will be the PR that we'll land first between this, #9341 and #9271 Based on this comment: #9271 (comment) the remaining items for this PR are:
I'm sure theres stuff I'm missing but hopefully that makes sense so far. |
e23a81b
to
c15c8d0
Compare
c15c8d0
to
f5149ec
Compare
f5149ec
to
8680bf5
Compare
e4fb028
to
2242ab0
Compare
06b88e8
to
206a40b
Compare
/hold cancel |
} | ||
|
||
if !kubernetesRangesIntersect(versionRange, semver.MustParseRange(">= 1.19.0")) { | ||
// Skip; this is an older manifest |
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 logic needs to be in sync with the iam_builder logic that decides whether to give the privileges to the service account or node
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 this is OK; this is saying "only try to patch the latest versions of the manifests". There is a deeper issue though, which is how to enable this on an existing cluster ... I talk about that in the top level comment.
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.
If the Kubernetes version is 1.11 but the feature flag is on, then iam_builder will withhold the permissions from the node role, yet this won't inject the projected volume. So dns-controller won't have the permissions.
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.
Right - there is "caveat emptor" with feature flags, I see you've got it with your suggested change though so I'm going to incorporate that!
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 can probably be removed now since context.UseServiceAccountIAM()
will be false for the older manifest.
pkg/model/iam/iam_builder.go
Outdated
return | ||
} | ||
|
||
// Legacy IAM permissions for node roles | ||
if b.Cluster.Spec.IAM.Legacy { | ||
if b.Cluster.Spec.IAM.Legacy && b.Role.IsNodeRole() { |
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.
No longer need this change. Legacy now implies all roles are node roles.
pkg/model/iam/pod_roles.go
Outdated
} | ||
|
||
// ServiceAccountForServiceAccountRole returns the kubernetes service account used by pods with the specified role | ||
func ServiceAccountForServiceAccountRole(serviceAccountRole ServiceAccountRole) types.NamespacedName { |
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.
Should this be a receiver?
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.
Done!
pkg/model/iam/pod_roles.go
Outdated
) | ||
|
||
// PodOrNodeRole is used to specify generation of permissions for either a pod or a node | ||
type PodOrNodeRole struct { |
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 was thinking the relevant buildAWSIAMRolePolicy()
logic could possibly be pushed under an interface method. And a ServiceAccount()
method would return the name of any service account.
Basically I'm applying the principle that code that does type assertions (or tests for existence of union fields) suggests that the branches under the test might be better as an interface method. But if it doesn't work, it doesn't work.
Thanks for explaining the interface comment @johngmyers - I implemented that and it seems to work really well. I think we could go even further with this reorganization, but there's likely a lot of moving around of code that would make this PR unreadably large again. Your first comment (about keeping the logic in sync) gets at a deeper point - we don't have a great way to enable IRSA on an existing cluster right now. I suspect it'll actually work out, but it's possible we could hit a circular dependency while trying to publish the jwks document. I think the answer will likely be:
I don't particularly want to tackle that in this PR though - my goal here is to get test coverage on IRSA so we can get the feature enabled in upstream kubernetes (and demonstrate that kops is a good place to build test coverage of new functionality!). |
If the plan is to condition IRSA support on the manifest version, then different service accounts are likely to have different Kubernetes-version cutoffs. Now when we drop support for k8s 1.11 in kops 1.20 a lot of variant manifests will drop away. But there are a few CNIs that vary over 1.16 and spotinst varies over 1.14. |
e4b8af6
to
85529e5
Compare
Merged your suggested change @johngmyers and then passed down I've also been thinking more about your point about functions/templates etc... there's actually a ton of overlap with the idea of operators and their ability to do transforms nicely, but the challenge of the opacity of the resulting manifest. I don't really have a fully formed answer yet, but there's something there I think... |
(Had to add another commit to workaround AWS IAM vs Golang JSON restrictions on the generated IAM policy) |
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 looks like there's only minor stuff left. I think it's really close.
There are some parameters of type iam.Subject
that are named role
; perhaps they should be named subject
.
} | ||
container := &containers[0] | ||
|
||
if context.UseServiceAccountIAM() { |
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.
Cannot be false here.
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.
Thanks - removed!
|
||
// MarshalJSON formats the IAM statement for the AWS IAM restrictions. | ||
// For example, `Resource: []` is not allowed, but golang would force us to use pointers. | ||
func (s *Statement) MarshalJSON() ([]byte, 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 might want unit tests for this.
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.
Good point - we had a unit test and added test cases to cover the new cases (e.g. no Resources).
pkg/model/iam/pod_roles.go
Outdated
) | ||
|
||
// Subject represents an IAM identity, to which permissions are granted. | ||
// It is implemented by NodeRole objects and per-ServiceAccount objects. | ||
type Subject interface { |
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.
Perhaps rename this file subject.go
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.
Good idea - done!
c878d85
to
56526ca
Compare
@justinsb: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
This should be much easier to start and to get under testing; it only works with a load balancer, it sets the apiserver into anonymous-auth allowed, it grants the anonymous auth user permission to read our jwks tokens. But it shouldn't need a second bucket or anything of that nature. Co-authored-by: John Gardiner Myers <[email protected]>
This avoids the hacky search through the list of tasks.
Hat-tip to johngmyers for the idea!
Co-authored-by: John Gardiner Myers <[email protected]>
AWS IAM is very strict and doesn't support `Resource: []` for example. We implement a custom MarshalJSON method to work around that.
56526ca
to
6fa8be2
Compare
/lgtm |
We create a featureflag "PublicJWKS" which runs in a simpler
configuration, where we expose the JWKS directly from the apiserver.
This has some limitations:
But it is a simpler configuration, and likely we can pare down the
code and get this under e2e before tackling some of the more
complicated scenarios.
Edit:
To try this out (but note that this isn't really a production config yet because of anonymous auth):