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

feat(kuma-cp) verify ServiceAccountToken bound to a Pod #2745

Merged
merged 3 commits into from
Sep 13, 2021

Conversation

jakubdyszkiewicz
Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz commented Sep 7, 2021

Summary

When authenticating kuma-dp on Kubernetes, we are carrying ServiceAccountToken and verify it in Kuma CP.
So far, we were only verifying the namespace of this Service Account Token but not the name of the token itself.
That means that any kuma-dp in one namespace could impersonate others in the same namespace.

I think this was done this way because if as a team member you manage Deployment and ServiceAccount objects in one namespace. There is no built-in mechanism in Kubernetes to prevent a user from using another ServiceAccount in a namespace for your Deployment.

However, there are cases where users are not responsible for managing Deployment objects but some high-level provisioner does that for them.

Alternatively, you could have a controller or OPA for Kubernetes that would restrict ServiceAccountToken to given Deployment.

Therefore Kuma should be more strict about verifying the token to not only verify a namespace of a token but check the Pod for the serviceAccountTokenName and also verify a token name.

Issues resolved

No issues.

Documentation

Testing

  • Unit tests
  • E2E tests
  • Manual testing on Universal
  • Manual testing on Kubernetes

Backwards compatibility

  • Add backport-to-stable label if the code is backwards compatible. Otherwise, list breaking changes.

Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
@jakubdyszkiewicz jakubdyszkiewicz requested a review from a team as a code owner September 7, 2021 13:29
@codecov-commenter
Copy link

codecov-commenter commented Sep 7, 2021

Codecov Report

Merging #2745 (ea09e64) into master (858034a) will decrease coverage by 0.00%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2745      +/-   ##
==========================================
- Coverage   51.99%   51.98%   -0.01%     
==========================================
  Files         877      877              
  Lines       51142    51162      +20     
==========================================
+ Hits        26589    26596       +7     
- Misses      22437    22449      +12     
- Partials     2116     2117       +1     
Impacted Files Coverage Δ
pkg/xds/auth/k8s/authenticator.go 0.00% <0.00%> (ø)
test/e2e/hybrid/kuma_hybrid.go 0.00% <0.00%> (ø)
...est/framework/deployments/testserver/deployment.go 0.00% <0.00%> (ø)
...est/framework/deployments/testserver/kubernetes.go 0.00% <0.00%> (ø)
pkg/core/resources/store/customizable_store.go 77.77% <0.00%> (-11.12%) ⬇️
pkg/plugins/resources/memory/store.go 77.71% <0.00%> (-4.35%) ⬇️
api/observability/v1/mads.pb.go 35.56% <0.00%> (+1.03%) ⬆️
pkg/dns/vips_allocator.go 74.00% <0.00%> (+1.33%) ⬆️
pkg/mads/v1/client/client.go 43.75% <0.00%> (+2.50%) ⬆️
pkg/core/resources/manager/cache.go 84.41% <0.00%> (+2.59%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 858034a...ea09e64. Read the comment docs.

@@ -57,6 +58,12 @@ func WithStatefulSet(apply bool) DeploymentOptsFn {
}
}

func WithServiceAccount(sa string) DeploymentOptsFn {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
func WithServiceAccount(sa string) DeploymentOptsFn {
func WithServiceAccount(accountName string) DeploymentOptsFn {

Namespace: namespace,
Name: name,
}, pod); err != nil {
return "", errors.Wrap(err, "could not retrieve Pod to verify identity of a dataplane proxy")
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: might be useful to include the namespaced name in the error

}
return nil
}

func (k *kubeAuthenticator) podServiceAccountName(ctx context.Context, name, namespace string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit:

Suggested change
func (k *kubeAuthenticator) podServiceAccountName(ctx context.Context, name, namespace string) (string, error) {
func (k *kubeAuthenticator) podServiceAccountName(ctx context.Context, podName types.NamespacedName) (string, error) {

}
namespace := userInfo[2]
if namespace != proxyNamespace {
return errors.Errorf("authentication failed: token belongs to a namespace (%q) different from proxyId (%q)", namespace, proxyNamespace)
return errors.Errorf("token belongs to a namespace (%q) different from proxyId (%q)", namespace, proxyNamespace)
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: the parentheses in this error seem a bit out of place since no other error format uses them

_, proxyNamespace, err := util_k8s.CoreNameToK8sName(dataplane.Meta.GetName())
if err != nil {
return err
return errors.Errorf("token must belong to a k8s system account, got %q", tokenReview.Status.User.Username)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return errors.Errorf("token must belong to a k8s system account, got %q", tokenReview.Status.User.Username)
return errors.Errorf("user %q is not a service account", tokenReview.Status.User.Username)

}
serviceAccountName, err := k.podServiceAccountName(ctx, proxyName, proxyNamespace)
if err != nil {
return errors.Wrap(err, "could not retrieve Pods Service Account to verify identity of a dataplane proxy")
Copy link
Contributor

Choose a reason for hiding this comment

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

This error message substantially repeats the one in podServiceAccountName. Maybe trim or or the other?

Same in authZoneIngress.

…dual-satoken

Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
@jakubdyszkiewicz jakubdyszkiewicz merged commit 0b2a7bf into master Sep 13, 2021
@jakubdyszkiewicz jakubdyszkiewicz deleted the chore/verify-individual-satoken branch September 13, 2021 11:10
mergify bot pushed a commit that referenced this pull request Sep 13, 2021
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
(cherry picked from commit 0b2a7bf)
jakubdyszkiewicz pushed a commit that referenced this pull request Sep 13, 2021
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
nikita15p pushed a commit to nikita15p/kuma that referenced this pull request Sep 28, 2021
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
nikita15p pushed a commit to nikita15p/kuma that referenced this pull request Sep 28, 2021
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants