mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +00:00
Add ServiceAccountToken SecretType
This commit is contained in:
parent
86800eafa7
commit
6e1e7dbb24
@ -284,6 +284,7 @@ _kubectl_describe()
|
|||||||
must_have_one_noun+=("pod")
|
must_have_one_noun+=("pod")
|
||||||
must_have_one_noun+=("replicationcontroller")
|
must_have_one_noun+=("replicationcontroller")
|
||||||
must_have_one_noun+=("resourcequota")
|
must_have_one_noun+=("resourcequota")
|
||||||
|
must_have_one_noun+=("secret")
|
||||||
must_have_one_noun+=("service")
|
must_have_one_noun+=("service")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1802,7 +1802,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||||||
type SecretType string
|
type SecretType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||||
|
SecretTypeOpaque SecretType = "Opaque"
|
||||||
|
|
||||||
|
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||||
|
//
|
||||||
|
// Required fields:
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||||
|
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||||
|
|
||||||
|
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||||
|
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||||
|
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountTokenKey = "token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretList struct {
|
type SecretList struct {
|
||||||
|
@ -1705,7 +1705,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||||||
type SecretType string
|
type SecretType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||||
|
SecretTypeOpaque SecretType = "Opaque"
|
||||||
|
|
||||||
|
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||||
|
//
|
||||||
|
// Required fields:
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||||
|
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||||
|
|
||||||
|
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||||
|
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||||
|
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountTokenKey = "token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretList struct {
|
type SecretList struct {
|
||||||
|
@ -1614,7 +1614,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||||||
type SecretType string
|
type SecretType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||||
|
SecretTypeOpaque SecretType = "Opaque"
|
||||||
|
|
||||||
|
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||||
|
//
|
||||||
|
// Required fields:
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||||
|
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||||
|
|
||||||
|
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||||
|
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||||
|
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountTokenKey = "token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretList struct {
|
type SecretList struct {
|
||||||
|
@ -1689,7 +1689,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||||||
type SecretType string
|
type SecretType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||||
|
SecretTypeOpaque SecretType = "Opaque"
|
||||||
|
|
||||||
|
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||||
|
//
|
||||||
|
// Required fields:
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||||
|
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||||
|
|
||||||
|
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||||
|
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||||
|
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountTokenKey = "token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretList struct {
|
type SecretList struct {
|
||||||
|
@ -1705,7 +1705,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||||||
type SecretType string
|
type SecretType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SecretTypeOpaque SecretType = "Opaque" // Default; arbitrary user-defined data
|
// SecretTypeOpaque is the default; arbitrary user-defined data
|
||||||
|
SecretTypeOpaque SecretType = "Opaque"
|
||||||
|
|
||||||
|
// SecretTypeServiceAccountToken contains a token that identifies a service account to the API
|
||||||
|
//
|
||||||
|
// Required fields:
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.name"] - the name of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Annotations["kubernetes.io/service-account.uid"] - the UID of the ServiceAccount the token identifies
|
||||||
|
// - Secret.Data["token"] - a token that identifies the service account to the API
|
||||||
|
SecretTypeServiceAccountToken SecretType = "kubernetes.io/service-account-token"
|
||||||
|
|
||||||
|
// ServiceAccountNameKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountNameKey = "kubernetes.io/service-account.name"
|
||||||
|
// ServiceAccountUIDKey is the key of the required annotation for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountUIDKey = "kubernetes.io/service-account.uid"
|
||||||
|
// ServiceAccountTokenKey is the key of the required data for SecretTypeServiceAccountToken secrets
|
||||||
|
ServiceAccountTokenKey = "token"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretList struct {
|
type SecretList struct {
|
||||||
|
@ -1244,6 +1244,12 @@ func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch secret.Type {
|
switch secret.Type {
|
||||||
|
case api.SecretTypeServiceAccountToken:
|
||||||
|
// Only require Annotations[kubernetes.io/service-account.name]
|
||||||
|
// Additional fields (like Annotations[kubernetes.io/service-account.uid] and Data[token]) might be contributed later by a controller loop
|
||||||
|
if value := secret.Annotations[api.ServiceAccountNameKey]; len(value) == 0 {
|
||||||
|
allErrs = append(allErrs, errs.NewFieldRequired(fmt.Sprintf("metadata.annotations[%s]", api.ServiceAccountNameKey)))
|
||||||
|
}
|
||||||
case api.SecretTypeOpaque, "":
|
case api.SecretTypeOpaque, "":
|
||||||
// no-op
|
// no-op
|
||||||
default:
|
default:
|
||||||
|
@ -2961,6 +2961,7 @@ func TestValidateNamespaceUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateSecret(t *testing.T) {
|
func TestValidateSecret(t *testing.T) {
|
||||||
|
// Opaque secret validation
|
||||||
validSecret := func() api.Secret {
|
validSecret := func() api.Secret {
|
||||||
return api.Secret{
|
return api.Secret{
|
||||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||||
@ -2988,6 +2989,32 @@ func TestValidateSecret(t *testing.T) {
|
|||||||
}
|
}
|
||||||
invalidKey.Data["a..b"] = []byte("whoops")
|
invalidKey.Data["a..b"] = []byte("whoops")
|
||||||
|
|
||||||
|
// kubernetes.io/service-account-token secret validation
|
||||||
|
validServiceAccountTokenSecret := func() api.Secret {
|
||||||
|
return api.Secret{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "bar",
|
||||||
|
Annotations: map[string]string{
|
||||||
|
api.ServiceAccountNameKey: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Type: api.SecretTypeServiceAccountToken,
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"data-1": []byte("bar"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
emptyTokenAnnotation = validServiceAccountTokenSecret()
|
||||||
|
missingTokenAnnotation = validServiceAccountTokenSecret()
|
||||||
|
missingTokenAnnotations = validServiceAccountTokenSecret()
|
||||||
|
)
|
||||||
|
emptyTokenAnnotation.Annotations[api.ServiceAccountNameKey] = ""
|
||||||
|
delete(missingTokenAnnotation.Annotations, api.ServiceAccountNameKey)
|
||||||
|
missingTokenAnnotations.Annotations = nil
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
secret api.Secret
|
secret api.Secret
|
||||||
valid bool
|
valid bool
|
||||||
@ -2999,6 +3026,11 @@ func TestValidateSecret(t *testing.T) {
|
|||||||
"invalid namespace": {invalidNs, false},
|
"invalid namespace": {invalidNs, false},
|
||||||
"over max size": {overMaxSize, false},
|
"over max size": {overMaxSize, false},
|
||||||
"invalid key": {invalidKey, false},
|
"invalid key": {invalidKey, false},
|
||||||
|
|
||||||
|
"valid service-account-token secret": {validServiceAccountTokenSecret(), true},
|
||||||
|
"empty service-account-token annotation": {emptyTokenAnnotation, false},
|
||||||
|
"missing service-account-token annotation": {missingTokenAnnotation, false},
|
||||||
|
"missing service-account-token annotations": {missingTokenAnnotations, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
|
@ -64,6 +64,7 @@ func describerMap(c *client.Client) map[string]Describer {
|
|||||||
m := map[string]Describer{
|
m := map[string]Describer{
|
||||||
"Pod": &PodDescriber{c},
|
"Pod": &PodDescriber{c},
|
||||||
"ReplicationController": &ReplicationControllerDescriber{c},
|
"ReplicationController": &ReplicationControllerDescriber{c},
|
||||||
|
"Secret": &SecretDescriber{c},
|
||||||
"Service": &ServiceDescriber{c},
|
"Service": &ServiceDescriber{c},
|
||||||
"Minion": &NodeDescriber{c},
|
"Minion": &NodeDescriber{c},
|
||||||
"Node": &NodeDescriber{c},
|
"Node": &NodeDescriber{c},
|
||||||
@ -421,6 +422,44 @@ func describeReplicationController(controller *api.ReplicationController, events
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SecretDescriber generates information about a secret
|
||||||
|
type SecretDescriber struct {
|
||||||
|
client.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *SecretDescriber) Describe(namespace, name string) (string, error) {
|
||||||
|
c := d.Secrets(namespace)
|
||||||
|
|
||||||
|
secret, err := c.Get(name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return describeSecret(secret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func describeSecret(secret *api.Secret) (string, error) {
|
||||||
|
return tabbedString(func(out io.Writer) error {
|
||||||
|
fmt.Fprintf(out, "Name:\t%s\n", secret.Name)
|
||||||
|
fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(secret.Labels))
|
||||||
|
fmt.Fprintf(out, "Annotations:\t%s\n", formatLabels(secret.Annotations))
|
||||||
|
|
||||||
|
fmt.Fprintf(out, "\nType:\t%s\n", secret.Type)
|
||||||
|
|
||||||
|
fmt.Fprintf(out, "\nData\n====\n")
|
||||||
|
for k, v := range secret.Data {
|
||||||
|
switch {
|
||||||
|
case k == api.ServiceAccountTokenKey && secret.Type == api.SecretTypeServiceAccountToken:
|
||||||
|
fmt.Fprintf(out, "%s:\t%s\n", k, string(v))
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(out, "%s:\t%d bytes\n", k, len(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceDescriber generates information about a service.
|
// ServiceDescriber generates information about a service.
|
||||||
type ServiceDescriber struct {
|
type ServiceDescriber struct {
|
||||||
client.Interface
|
client.Interface
|
||||||
|
Loading…
Reference in New Issue
Block a user