Merge pull request #71007 from mikedanese/allowdefault

TokenRequestProjections should allow API server to default empty audience
pull/58/head
k8s-ci-robot 2018-11-14 11:38:16 -08:00 committed by GitHub
commit 5a84dffc75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 131 additions and 3 deletions

View File

@ -11,15 +11,22 @@ go_test(
srcs = ["projected_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/authentication/v1:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/volume:go_default_library",
"//pkg/volume/emptydir:go_default_library",
"//pkg/volume/testing:go_default_library",
"//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/authentication/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library",
],
)

View File

@ -326,11 +326,14 @@ func (s *projectedVolumeMounter) collectData() (map[string]volumeutil.FileProjec
continue
}
tp := source.ServiceAccountToken
var auds []string
if len(tp.Audience) != 0 {
auds = []string{tp.Audience}
}
tr, err := s.plugin.getServiceAccountToken(s.pod.Namespace, s.pod.Spec.ServiceAccountName, &authenticationv1.TokenRequest{
Spec: authenticationv1.TokenRequestSpec{
Audiences: []string{
tp.Audience,
},
Audiences: auds,
ExpirationSeconds: tp.ExpirationSeconds,
BoundObjectRef: &authenticationv1.BoundObjectReference{
APIVersion: "v1",

View File

@ -25,11 +25,18 @@ import (
"strings"
"testing"
authenticationv1 "k8s.io/api/authentication/v1"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/diff"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
clitesting "k8s.io/client-go/testing"
pkgauthenticationv1 "k8s.io/kubernetes/pkg/apis/authentication/v1"
pkgcorev1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/emptydir"
volumetest "k8s.io/kubernetes/pkg/volume/testing"
@ -699,6 +706,113 @@ func TestCollectDataWithDownwardAPI(t *testing.T) {
}
}
func TestCollectDataWithServiceAccountToken(t *testing.T) {
scheme := runtime.NewScheme()
utilruntime.Must(pkgauthenticationv1.RegisterDefaults(scheme))
utilruntime.Must(pkgcorev1.RegisterDefaults(scheme))
minute := int64(60)
cases := []struct {
name string
svcacct string
audience string
expiration *int64
path string
payload map[string]util.FileProjection
}{
{
name: "test good service account",
audience: "https://example.com",
path: "token",
expiration: &minute,
payload: map[string]util.FileProjection{
"token": {Data: []byte("test_projected_namespace:foo:60:[https://example.com]"), Mode: 0600},
},
},
{
name: "test good service account other path",
audience: "https://example.com",
path: "other-token",
expiration: &minute,
payload: map[string]util.FileProjection{
"other-token": {Data: []byte("test_projected_namespace:foo:60:[https://example.com]"), Mode: 0600},
},
},
{
name: "test good service account defaults audience",
path: "token",
expiration: &minute,
payload: map[string]util.FileProjection{
"token": {Data: []byte("test_projected_namespace:foo:60:[https://api]"), Mode: 0600},
},
},
{
name: "test good service account defaults expiration",
audience: "https://example.com",
path: "token",
payload: map[string]util.FileProjection{
"token": {Data: []byte("test_projected_namespace:foo:3600:[https://example.com]"), Mode: 0600},
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
testNamespace := "test_projected_namespace"
source := makeProjection(tc.name, 0600, "serviceAccountToken")
source.Sources[0].ServiceAccountToken.Audience = tc.audience
source.Sources[0].ServiceAccountToken.ExpirationSeconds = tc.expiration
source.Sources[0].ServiceAccountToken.Path = tc.path
testPodUID := types.UID("test_pod_uid")
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID},
Spec: v1.PodSpec{ServiceAccountName: "foo"},
}
scheme.Default(pod)
client := &fake.Clientset{}
client.AddReactor("create", "serviceaccounts", clitesting.ReactionFunc(func(action clitesting.Action) (bool, runtime.Object, error) {
tr := action.(clitesting.CreateAction).GetObject().(*authenticationv1.TokenRequest)
scheme.Default(tr)
if len(tr.Spec.Audiences) == 0 {
tr.Spec.Audiences = []string{"https://api"}
}
tr.Status.Token = fmt.Sprintf("%v:%v:%d:%v", action.GetNamespace(), "foo", *tr.Spec.ExpirationSeconds, tr.Spec.Audiences)
return true, tr, nil
}))
_, host := newTestHost(t, client)
var myVolumeMounter = projectedVolumeMounter{
projectedVolume: &projectedVolume{
sources: source.Sources,
podUID: pod.UID,
plugin: &projectedPlugin{
host: host,
getServiceAccountToken: host.GetServiceAccountTokenFunc(),
},
},
source: *source,
pod: pod,
}
actualPayload, err := myVolumeMounter.collectData()
if err != nil {
t.Fatalf("unexpected failure making payload: %v", err)
}
if e, a := tc.payload, actualPayload; !reflect.DeepEqual(e, a) {
t.Errorf("expected and actual payload do not match:\n%s", diff.ObjectReflectDiff(e, a))
}
})
}
}
func newTestHost(t *testing.T, clientset clientset.Interface) (string, volume.VolumeHost) {
tempDir, err := ioutil.TempDir("/tmp", "projected_volume_test.")
if err != nil {
@ -1113,6 +1227,10 @@ func makeProjection(name string, defaultMode int32, kind string) *v1.ProjectedVo
item = v1.VolumeProjection{
DownwardAPI: &v1.DownwardAPIProjection{},
}
case "serviceAccountToken":
item = v1.VolumeProjection{
ServiceAccountToken: &v1.ServiceAccountTokenProjection{},
}
}
return &v1.ProjectedVolumeSource{