mirror of https://github.com/k3s-io/k3s
Add ServiceAccountToken SecretType
parent
86800eafa7
commit
6e1e7dbb24
|
@ -284,6 +284,7 @@ _kubectl_describe()
|
|||
must_have_one_noun+=("pod")
|
||||
must_have_one_noun+=("replicationcontroller")
|
||||
must_have_one_noun+=("resourcequota")
|
||||
must_have_one_noun+=("secret")
|
||||
must_have_one_noun+=("service")
|
||||
}
|
||||
|
||||
|
|
|
@ -1802,7 +1802,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||
type SecretType string
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1705,7 +1705,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||
type SecretType string
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1614,7 +1614,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||
type SecretType string
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1689,7 +1689,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||
type SecretType string
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1705,7 +1705,23 @@ const MaxSecretSize = 1 * 1024 * 1024
|
|||
type SecretType string
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1244,6 +1244,12 @@ func ValidateSecret(secret *api.Secret) errs.ValidationErrorList {
|
|||
}
|
||||
|
||||
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, "":
|
||||
// no-op
|
||||
default:
|
||||
|
|
|
@ -2961,6 +2961,7 @@ func TestValidateNamespaceUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidateSecret(t *testing.T) {
|
||||
// Opaque secret validation
|
||||
validSecret := func() api.Secret {
|
||||
return api.Secret{
|
||||
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "bar"},
|
||||
|
@ -2988,6 +2989,32 @@ func TestValidateSecret(t *testing.T) {
|
|||
}
|
||||
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 {
|
||||
secret api.Secret
|
||||
valid bool
|
||||
|
@ -2999,6 +3026,11 @@ func TestValidateSecret(t *testing.T) {
|
|||
"invalid namespace": {invalidNs, false},
|
||||
"over max size": {overMaxSize, 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 {
|
||||
|
|
|
@ -64,6 +64,7 @@ func describerMap(c *client.Client) map[string]Describer {
|
|||
m := map[string]Describer{
|
||||
"Pod": &PodDescriber{c},
|
||||
"ReplicationController": &ReplicationControllerDescriber{c},
|
||||
"Secret": &SecretDescriber{c},
|
||||
"Service": &ServiceDescriber{c},
|
||||
"Minion": &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.
|
||||
type ServiceDescriber struct {
|
||||
client.Interface
|
||||
|
|
Loading…
Reference in New Issue