Skip to content

Commit

Permalink
Address edoardo and tiago's feedback + dedup audiences
Browse files Browse the repository at this point in the history
  • Loading branch information
hugoShaka authored and github-actions committed Dec 5, 2024
1 parent 98c0c76 commit c04a083
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 7 deletions.
18 changes: 12 additions & 6 deletions lib/kubernetestoken/token_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package kubernetestoken
import (
"context"
"encoding/json"
"github.com/gravitational/teleport/api/utils"
"slices"
"strings"
"sync"
Expand Down Expand Up @@ -110,8 +111,8 @@ func (v *TokenReviewValidator) getClient(_ context.Context) (kubernetes.Interfac
return nil, nil, trace.WrapWithMessage(err, "failed to initialize in-cluster Kubernetes client")
}

// We do a self-review to recover the default cluster audience
audiences, err := getTokenAudiences(config.BearerToken)
// We extract the audiences from our own token. This allows us to detect the default Kubernetes audiences.
audiences, err := unsafeGetTokenAudiences(config.BearerToken)
if err != nil {
return nil, nil, trace.Wrap(err, "doing a self-review")
}
Expand All @@ -121,8 +122,11 @@ func (v *TokenReviewValidator) getClient(_ context.Context) (kubernetes.Interfac
return client, audiences, nil
}

// getTokenAudiences extracts the audience from
func getTokenAudiences(token string) ([]string, error) {
// unsafeGetTokenAudiences extracts the audience from the mounted token.
// THIS FUNCTION DOES NOT VALIDATE THE TOKEN SIGNATURE.
// Bound tokens always have audiences and the list will not be empty.
// Legacy tokens don't have audiences, the result will be an empty list and no error.
func unsafeGetTokenAudiences(token string) ([]string, error) {
jwt, err := josejwt.ParseSigned(token)
if err != nil {
return nil, trace.Wrap(err)
Expand Down Expand Up @@ -157,8 +161,10 @@ func (v *TokenReviewValidator) Validate(ctx context.Context, token, clusterName
// We do this only if the Kubernetes cluster supports audiences.
// Earlier Kube versions don't have audience
// support, in this case, we just do a regular token review.
if audiences != nil {
review.Spec.Audiences = append([]string{clusterName}, audiences...)
if len(audiences) > 0 {
// We deduplicate because the Teleport cluster name could be one of the default audiences
// And I really don't want to discover if sending the same audience multiple times is valid for Kubernetes.
review.Spec.Audiences = utils.Deduplicate(append([]string{clusterName}, audiences...))
}

options := metav1.CreateOptions{}
Expand Down
2 changes: 1 addition & 1 deletion lib/kubernetestoken/token_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func TestGetTokenAudiences(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := getTokenAudiences(tt.token)
result, err := unsafeGetTokenAudiences(tt.token)
tt.expectErr(t, err)
assert.Equal(t, tt.expectedAudiences, result)
})
Expand Down

0 comments on commit c04a083

Please sign in to comment.