mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Merge pull request #60324 from mikedanese/id-test1
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. integration: refactor, cleanup, and add more tests for TokenRequest ref #58790 ```release-note NONE ```
This commit is contained in:
commit
15e34b13c4
@ -25,6 +25,7 @@ import (
|
|||||||
authenticationv1 "k8s.io/api/authentication/v1"
|
authenticationv1 "k8s.io/api/authentication/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||||
@ -63,103 +64,162 @@ func TestServiceAccountTokenCreate(t *testing.T) {
|
|||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
sa := &v1.ServiceAccount{
|
var (
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
sa = &v1.ServiceAccount{
|
||||||
Name: "test",
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: "default",
|
Name: "test-svcacct",
|
||||||
},
|
Namespace: "myns",
|
||||||
}
|
|
||||||
|
|
||||||
tr1 := &authenticationv1.TokenRequest{
|
|
||||||
Spec: authenticationv1.TokenRequestSpec{
|
|
||||||
Audiences: []string{"aud"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = cs.CoreV1().ServiceAccounts(sa.Namespace).Create(sa)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
tr1, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, tr1)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
checkPayload(t, tr1.Status.Token, `"system:serviceaccount:default:test"`, "sub")
|
|
||||||
checkPayload(t, tr1.Status.Token, `["aud"]`, "aud")
|
|
||||||
checkPayload(t, tr1.Status.Token, "null", "kubernetes.io", "pod")
|
|
||||||
checkPayload(t, tr1.Status.Token, "null", "kubernetes.io", "secret")
|
|
||||||
checkPayload(t, tr1.Status.Token, `"default"`, "kubernetes.io", "namespace")
|
|
||||||
checkPayload(t, tr1.Status.Token, `"test"`, "kubernetes.io", "serviceaccount", "name")
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-pod",
|
|
||||||
Namespace: sa.Namespace,
|
|
||||||
},
|
|
||||||
Spec: v1.PodSpec{
|
|
||||||
ServiceAccountName: sa.Name,
|
|
||||||
Containers: []v1.Container{{Name: "test-container", Image: "nginx"}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
_, err = cs.CoreV1().Pods(pod.Namespace).Create(pod)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tr2 := &authenticationv1.TokenRequest{
|
|
||||||
Spec: authenticationv1.TokenRequestSpec{
|
|
||||||
Audiences: []string{"aud"},
|
|
||||||
BoundObjectRef: &authenticationv1.BoundObjectReference{
|
|
||||||
Kind: "Pod",
|
|
||||||
APIVersion: "v1",
|
|
||||||
Name: pod.Name,
|
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
pod = &v1.Pod{
|
||||||
tr2, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, tr2)
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
if err != nil {
|
Name: "test-pod",
|
||||||
t.Fatalf("err: %v", err)
|
Namespace: sa.Namespace,
|
||||||
}
|
|
||||||
|
|
||||||
checkPayload(t, tr2.Status.Token, `"system:serviceaccount:default:test"`, "sub")
|
|
||||||
checkPayload(t, tr2.Status.Token, `["aud"]`, "aud")
|
|
||||||
checkPayload(t, tr2.Status.Token, `"test-pod"`, "kubernetes.io", "pod", "name")
|
|
||||||
checkPayload(t, tr2.Status.Token, "null", "kubernetes.io", "secret")
|
|
||||||
checkPayload(t, tr2.Status.Token, `"default"`, "kubernetes.io", "namespace")
|
|
||||||
checkPayload(t, tr2.Status.Token, `"test"`, "kubernetes.io", "serviceaccount", "name")
|
|
||||||
|
|
||||||
secret := &v1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "test-secret",
|
|
||||||
Namespace: sa.Namespace,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
_, err = cs.CoreV1().Secrets(secret.Namespace).Create(secret)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("err: %v", err)
|
|
||||||
}
|
|
||||||
tr3 := &authenticationv1.TokenRequest{
|
|
||||||
Spec: authenticationv1.TokenRequestSpec{
|
|
||||||
Audiences: []string{"aud"},
|
|
||||||
BoundObjectRef: &authenticationv1.BoundObjectReference{
|
|
||||||
Kind: "Secret",
|
|
||||||
APIVersion: "v1",
|
|
||||||
Name: secret.Name,
|
|
||||||
},
|
},
|
||||||
},
|
Spec: v1.PodSpec{
|
||||||
}
|
ServiceAccountName: sa.Name,
|
||||||
tr3, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, tr3)
|
Containers: []v1.Container{{Name: "test-container", Image: "nginx"}},
|
||||||
if err != nil {
|
},
|
||||||
t.Fatalf("err: %v", err)
|
}
|
||||||
}
|
secret = &v1.Secret{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-secret",
|
||||||
|
Namespace: sa.Namespace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
checkPayload(t, tr2.Status.Token, `"system:serviceaccount:default:test"`, "sub")
|
one = int64(1)
|
||||||
checkPayload(t, tr2.Status.Token, `["aud"]`, "aud")
|
wrongUID = types.UID("wrong")
|
||||||
checkPayload(t, tr2.Status.Token, `"test-pod"`, "kubernetes.io", "pod", "name")
|
noUID = types.UID("")
|
||||||
checkPayload(t, tr2.Status.Token, `null`, "kubernetes.io", "secret")
|
)
|
||||||
checkPayload(t, tr2.Status.Token, `"default"`, "kubernetes.io", "namespace")
|
|
||||||
checkPayload(t, tr2.Status.Token, `"test"`, "kubernetes.io", "serviceaccount", "name")
|
t.Run("bound to service account", func(t *testing.T) {
|
||||||
|
treq := &authenticationv1.TokenRequest{
|
||||||
|
Spec: authenticationv1.TokenRequestSpec{
|
||||||
|
Audiences: []string{"api"},
|
||||||
|
ExpirationSeconds: &one,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token for nonexistant svcacct but got: %#v", resp)
|
||||||
|
}
|
||||||
|
sa, del := createDeleteSvcAcct(t, cs, sa)
|
||||||
|
defer del()
|
||||||
|
|
||||||
|
treq, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPayload(t, treq.Status.Token, `"system:serviceaccount:myns:test-svcacct"`, "sub")
|
||||||
|
checkPayload(t, treq.Status.Token, `["api"]`, "aud")
|
||||||
|
checkPayload(t, treq.Status.Token, "null", "kubernetes.io", "pod")
|
||||||
|
checkPayload(t, treq.Status.Token, "null", "kubernetes.io", "secret")
|
||||||
|
checkPayload(t, treq.Status.Token, `"myns"`, "kubernetes.io", "namespace")
|
||||||
|
checkPayload(t, treq.Status.Token, `"test-svcacct"`, "kubernetes.io", "serviceaccount", "name")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bound to service account and pod", func(t *testing.T) {
|
||||||
|
treq := &authenticationv1.TokenRequest{
|
||||||
|
Spec: authenticationv1.TokenRequestSpec{
|
||||||
|
Audiences: []string{"api"},
|
||||||
|
ExpirationSeconds: &one,
|
||||||
|
BoundObjectRef: &authenticationv1.BoundObjectReference{
|
||||||
|
Kind: "Pod",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Name: pod.Name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token for nonexistant svcacct but got: %#v", resp)
|
||||||
|
}
|
||||||
|
sa, del := createDeleteSvcAcct(t, cs, sa)
|
||||||
|
defer del()
|
||||||
|
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token bound to nonexistant pod but got: %#v", resp)
|
||||||
|
}
|
||||||
|
pod, del := createDeletePod(t, cs, pod)
|
||||||
|
defer del()
|
||||||
|
|
||||||
|
// right uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = pod.UID
|
||||||
|
if _, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
// wrong uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = wrongUID
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token bound to pod with wrong uid but got: %#v", resp)
|
||||||
|
}
|
||||||
|
// no uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = noUID
|
||||||
|
treq, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPayload(t, treq.Status.Token, `"system:serviceaccount:myns:test-svcacct"`, "sub")
|
||||||
|
checkPayload(t, treq.Status.Token, `["api"]`, "aud")
|
||||||
|
checkPayload(t, treq.Status.Token, `"test-pod"`, "kubernetes.io", "pod", "name")
|
||||||
|
checkPayload(t, treq.Status.Token, "null", "kubernetes.io", "secret")
|
||||||
|
checkPayload(t, treq.Status.Token, `"myns"`, "kubernetes.io", "namespace")
|
||||||
|
checkPayload(t, treq.Status.Token, `"test-svcacct"`, "kubernetes.io", "serviceaccount", "name")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bound to service account and secret", func(t *testing.T) {
|
||||||
|
treq := &authenticationv1.TokenRequest{
|
||||||
|
Spec: authenticationv1.TokenRequestSpec{
|
||||||
|
Audiences: []string{"api"},
|
||||||
|
ExpirationSeconds: &one,
|
||||||
|
BoundObjectRef: &authenticationv1.BoundObjectReference{
|
||||||
|
Kind: "Secret",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Name: secret.Name,
|
||||||
|
UID: secret.UID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token for nonexistant svcacct but got: %#v", resp)
|
||||||
|
}
|
||||||
|
sa, del := createDeleteSvcAcct(t, cs, sa)
|
||||||
|
defer del()
|
||||||
|
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token bound to nonexistant secret but got: %#v", resp)
|
||||||
|
}
|
||||||
|
secret, del := createDeleteSecret(t, cs, secret)
|
||||||
|
defer del()
|
||||||
|
|
||||||
|
// right uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = secret.UID
|
||||||
|
if _, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
// wrong uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = wrongUID
|
||||||
|
if resp, err := cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq); err == nil {
|
||||||
|
t.Fatalf("expected err creating token bound to secret with wrong uid but got: %#v", resp)
|
||||||
|
}
|
||||||
|
// no uid
|
||||||
|
treq.Spec.BoundObjectRef.UID = noUID
|
||||||
|
treq, err = cs.CoreV1().ServiceAccounts(sa.Namespace).CreateToken(sa.Name, treq)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPayload(t, treq.Status.Token, `"system:serviceaccount:myns:test-svcacct"`, "sub")
|
||||||
|
checkPayload(t, treq.Status.Token, `["api"]`, "aud")
|
||||||
|
checkPayload(t, treq.Status.Token, `null`, "kubernetes.io", "pod")
|
||||||
|
checkPayload(t, treq.Status.Token, `"test-secret"`, "kubernetes.io", "secret", "name")
|
||||||
|
checkPayload(t, treq.Status.Token, `"myns"`, "kubernetes.io", "namespace")
|
||||||
|
checkPayload(t, treq.Status.Token, `"test-svcacct"`, "kubernetes.io", "serviceaccount", "name")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPayload(t *testing.T, tok string, want string, parts ...string) {
|
func checkPayload(t *testing.T, tok string, want string, parts ...string) {
|
||||||
@ -199,3 +259,45 @@ func getPayload(t *testing.T, b string) string {
|
|||||||
}
|
}
|
||||||
return string(payload)
|
return string(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createDeleteSvcAcct(t *testing.T, cs clientset.Interface, sa *v1.ServiceAccount) (*v1.ServiceAccount, func()) {
|
||||||
|
t.Helper()
|
||||||
|
sa, err := cs.CoreV1().ServiceAccounts(sa.Namespace).Create(sa)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
return sa, func() {
|
||||||
|
t.Helper()
|
||||||
|
if err := cs.CoreV1().ServiceAccounts(sa.Namespace).Delete(sa.Name, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDeletePod(t *testing.T, cs clientset.Interface, pod *v1.Pod) (*v1.Pod, func()) {
|
||||||
|
t.Helper()
|
||||||
|
pod, err := cs.CoreV1().Pods(pod.Namespace).Create(pod)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
return pod, func() {
|
||||||
|
t.Helper()
|
||||||
|
if err := cs.CoreV1().Pods(pod.Namespace).Delete(pod.Name, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDeleteSecret(t *testing.T, cs clientset.Interface, sec *v1.Secret) (*v1.Secret, func()) {
|
||||||
|
t.Helper()
|
||||||
|
sec, err := cs.CoreV1().Secrets(sec.Namespace).Create(sec)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
return sec, func() {
|
||||||
|
t.Helper()
|
||||||
|
if err := cs.CoreV1().Secrets(sec.Namespace).Delete(sec.Name, nil); err != nil {
|
||||||
|
t.Fatalf("err: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user