mirror of https://github.com/k3s-io/k3s
Merge pull request #37953 from liggitt/automount
Automatic merge from submit-queue (batch tested with PRs 37137, 41506, 41239, 41511, 37953) Add field to control service account token automounting Fixes https://github.com/kubernetes/kubernetes/issues/16779 * adds an `automountServiceAccountToken *bool` field to `ServiceAccount` and `PodSpec` * if set in both the service account and pod, the pod wins * if unset in both the service account and pod, we automount for backwards compatibility ```release-note An `automountServiceAccountToken *bool` field was added to ServiceAccount and PodSpec objects. If set to `false` on a pod spec, no service account token is automounted in the pod. If set to `false` on a service account, no service account token is automounted for that service account unless explicitly overridden in the pod spec. ```pull/6/head
commit
97212f5b3a
|
@ -37886,6 +37886,10 @@
|
|||
"description": "If specified, the pod's scheduling constraints",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.Affinity"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"containers": {
|
||||
"description": "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers",
|
||||
"type": "array",
|
||||
|
@ -38767,6 +38771,10 @@
|
|||
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources",
|
||||
"type": "string"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"description": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"imagePullSecrets": {
|
||||
"description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret",
|
||||
"type": "array",
|
||||
|
|
|
@ -1322,6 +1322,10 @@
|
|||
"type": "string",
|
||||
"description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead."
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean",
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted."
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string",
|
||||
"description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements."
|
||||
|
|
|
@ -1327,6 +1327,10 @@
|
|||
"type": "string",
|
||||
"description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead."
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean",
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted."
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string",
|
||||
"description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements."
|
||||
|
|
|
@ -6729,6 +6729,10 @@
|
|||
"type": "string",
|
||||
"description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead."
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean",
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted."
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string",
|
||||
"description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements."
|
||||
|
|
|
@ -18265,6 +18265,10 @@
|
|||
"type": "string",
|
||||
"description": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead."
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean",
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted."
|
||||
},
|
||||
"nodeName": {
|
||||
"type": "string",
|
||||
"description": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements."
|
||||
|
@ -20078,6 +20082,10 @@
|
|||
"$ref": "v1.LocalObjectReference"
|
||||
},
|
||||
"description": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"type": "boolean",
|
||||
"description": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4556,6 +4556,13 @@ The StatefulSet guarantees that a given network identity will always map to the
|
|||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">automountServiceAccountToken</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">nodeName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
|
@ -5081,7 +5088,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-06 11:50:05 UTC
|
||||
Last updated 2017-02-14 05:29:50 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -4543,6 +4543,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">automountServiceAccountToken</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">nodeName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
|
@ -5013,7 +5020,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-06 11:50:30 UTC
|
||||
Last updated 2017-02-14 05:30:28 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -4080,6 +4080,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">automountServiceAccountToken</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">nodeName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
|
@ -7304,7 +7311,7 @@ Both these may change in the future. Incoming requests are matched against the h
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-06 11:50:48 UTC
|
||||
Last updated 2017-02-14 05:30:44 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -2887,6 +2887,13 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_localobjectreference">v1.LocalObjectReference</a> array</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">automountServiceAccountToken</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -4790,6 +4797,13 @@ The resulting set of endpoints can be viewed as:<br>
|
|||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">automountServiceAccountToken</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">nodeName</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
|
@ -9261,7 +9275,7 @@ Examples:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2017-02-06 11:49:57 UTC
|
||||
Last updated 2017-02-14 05:29:43 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -12490,6 +12490,10 @@
|
|||
"description": "If specified, the pod's scheduling constraints",
|
||||
"$ref": "#/definitions/io.k8s.kubernetes.pkg.api.v1.Affinity"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"description": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"containers": {
|
||||
"description": "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers",
|
||||
"type": "array",
|
||||
|
|
|
@ -1887,6 +1887,9 @@ type PodSpec struct {
|
|||
// ServiceAccountName is the name of the ServiceAccount to use to run this pod
|
||||
// The pod will be allowed to use secrets referenced by the ServiceAccount
|
||||
ServiceAccountName string
|
||||
// AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
|
||||
// +optional
|
||||
AutomountServiceAccountToken *bool
|
||||
|
||||
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
|
||||
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
|
||||
|
@ -2425,6 +2428,11 @@ type ServiceAccount struct {
|
|||
// can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet.
|
||||
// +optional
|
||||
ImagePullSecrets []LocalObjectReference
|
||||
|
||||
// AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted.
|
||||
// Can be overridden at the pod level.
|
||||
// +optional
|
||||
AutomountServiceAccountToken *bool
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2569,6 +2569,10 @@ message PodSpec {
|
|||
// +optional
|
||||
optional string serviceAccount = 9;
|
||||
|
||||
// AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
|
||||
// +optional
|
||||
optional bool automountServiceAccountToken = 21;
|
||||
|
||||
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
|
||||
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
|
||||
// requirements.
|
||||
|
@ -3307,6 +3311,11 @@ message ServiceAccount {
|
|||
// More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret
|
||||
// +optional
|
||||
repeated LocalObjectReference imagePullSecrets = 3;
|
||||
|
||||
// AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted.
|
||||
// Can be overridden at the pod level.
|
||||
// +optional
|
||||
optional bool automountServiceAccountToken = 4;
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2160,6 +2160,9 @@ type PodSpec struct {
|
|||
// +k8s:conversion-gen=false
|
||||
// +optional
|
||||
DeprecatedServiceAccount string `json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
|
||||
// AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.
|
||||
// +optional
|
||||
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty" protobuf:"varint,21,opt,name=automountServiceAccountToken"`
|
||||
|
||||
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
|
||||
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
|
||||
|
@ -2801,6 +2804,11 @@ type ServiceAccount struct {
|
|||
// More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret
|
||||
// +optional
|
||||
ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty" protobuf:"bytes,3,rep,name=imagePullSecrets"`
|
||||
|
||||
// AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted.
|
||||
// Can be overridden at the pod level.
|
||||
// +optional
|
||||
AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty" protobuf:"varint,4,opt,name=automountServiceAccountToken"`
|
||||
}
|
||||
|
||||
// ServiceAccountList is a list of ServiceAccount objects
|
||||
|
|
|
@ -1301,6 +1301,7 @@ var map_PodSpec = map[string]string{
|
|||
"nodeSelector": "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: http://kubernetes.io/docs/user-guide/node-selection/README",
|
||||
"serviceAccountName": "ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: http://releases.k8s.io/HEAD/docs/design/service_accounts.md",
|
||||
"serviceAccount": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.",
|
||||
"automountServiceAccountToken": "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.",
|
||||
"nodeName": "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.",
|
||||
"hostNetwork": "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified. Default to false.",
|
||||
"hostPID": "Use the host's pid namespace. Optional: Default to false.",
|
||||
|
@ -1681,10 +1682,11 @@ func (Service) SwaggerDoc() map[string]string {
|
|||
}
|
||||
|
||||
var map_ServiceAccount = map[string]string{
|
||||
"": "ServiceAccount binds together: * a name, understood by users, and perhaps by peripheral systems, for an identity * a principal that can be authenticated and authorized * a set of secrets",
|
||||
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
"secrets": "Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. More info: http://kubernetes.io/docs/user-guide/secrets",
|
||||
"imagePullSecrets": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret",
|
||||
"": "ServiceAccount binds together: * a name, understood by users, and perhaps by peripheral systems, for an identity * a principal that can be authenticated and authorized * a set of secrets",
|
||||
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
|
||||
"secrets": "Secrets is the list of secrets allowed to be used by pods running using this ServiceAccount. More info: http://kubernetes.io/docs/user-guide/secrets",
|
||||
"imagePullSecrets": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret",
|
||||
"automountServiceAccountToken": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.",
|
||||
}
|
||||
|
||||
func (ServiceAccount) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -3086,6 +3086,7 @@ func autoConvert_v1_PodSpec_To_api_PodSpec(in *PodSpec, out *api.PodSpec, s conv
|
|||
out.NodeSelector = *(*map[string]string)(unsafe.Pointer(&in.NodeSelector))
|
||||
out.ServiceAccountName = in.ServiceAccountName
|
||||
// INFO: in.DeprecatedServiceAccount opted out of conversion generation
|
||||
out.AutomountServiceAccountToken = (*bool)(unsafe.Pointer(in.AutomountServiceAccountToken))
|
||||
out.NodeName = in.NodeName
|
||||
// INFO: in.HostNetwork opted out of conversion generation
|
||||
// INFO: in.HostPID opted out of conversion generation
|
||||
|
@ -3127,6 +3128,7 @@ func autoConvert_api_PodSpec_To_v1_PodSpec(in *api.PodSpec, out *PodSpec, s conv
|
|||
out.DNSPolicy = DNSPolicy(in.DNSPolicy)
|
||||
out.NodeSelector = *(*map[string]string)(unsafe.Pointer(&in.NodeSelector))
|
||||
out.ServiceAccountName = in.ServiceAccountName
|
||||
out.AutomountServiceAccountToken = (*bool)(unsafe.Pointer(in.AutomountServiceAccountToken))
|
||||
out.NodeName = in.NodeName
|
||||
if in.SecurityContext != nil {
|
||||
in, out := &in.SecurityContext, &out.SecurityContext
|
||||
|
@ -3992,6 +3994,7 @@ func autoConvert_v1_ServiceAccount_To_api_ServiceAccount(in *ServiceAccount, out
|
|||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Secrets = *(*[]api.ObjectReference)(unsafe.Pointer(&in.Secrets))
|
||||
out.ImagePullSecrets = *(*[]api.LocalObjectReference)(unsafe.Pointer(&in.ImagePullSecrets))
|
||||
out.AutomountServiceAccountToken = (*bool)(unsafe.Pointer(in.AutomountServiceAccountToken))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -4003,6 +4006,7 @@ func autoConvert_api_ServiceAccount_To_v1_ServiceAccount(in *api.ServiceAccount,
|
|||
out.ObjectMeta = in.ObjectMeta
|
||||
out.Secrets = *(*[]ObjectReference)(unsafe.Pointer(&in.Secrets))
|
||||
out.ImagePullSecrets = *(*[]LocalObjectReference)(unsafe.Pointer(&in.ImagePullSecrets))
|
||||
out.AutomountServiceAccountToken = (*bool)(unsafe.Pointer(in.AutomountServiceAccountToken))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -2303,6 +2303,11 @@ func DeepCopy_v1_PodSpec(in interface{}, out interface{}, c *conversion.Cloner)
|
|||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.AutomountServiceAccountToken != nil {
|
||||
in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.SecurityContext != nil {
|
||||
in, out := &in.SecurityContext, &out.SecurityContext
|
||||
*out = new(PodSecurityContext)
|
||||
|
@ -2948,6 +2953,11 @@ func DeepCopy_v1_ServiceAccount(in interface{}, out interface{}, c *conversion.C
|
|||
*out = make([]LocalObjectReference, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AutomountServiceAccountToken != nil {
|
||||
in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2347,6 +2347,11 @@ func DeepCopy_api_PodSpec(in interface{}, out interface{}, c *conversion.Cloner)
|
|||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.AutomountServiceAccountToken != nil {
|
||||
in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
if in.SecurityContext != nil {
|
||||
in, out := &in.SecurityContext, &out.SecurityContext
|
||||
*out = new(PodSecurityContext)
|
||||
|
@ -2980,6 +2985,11 @@ func DeepCopy_api_ServiceAccount(in interface{}, out interface{}, c *conversion.
|
|||
*out = make([]LocalObjectReference, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AutomountServiceAccountToken != nil {
|
||||
in, out := &in.AutomountServiceAccountToken, &out.AutomountServiceAccountToken
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1679,7 +1679,7 @@ func (x codecSelfer1234) decSliceStatefulSet(v *[]StatefulSet, d *codec1978.Deco
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 824)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 832)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
|
|
@ -2481,7 +2481,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) {
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 848)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 856)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
|
|
@ -4534,7 +4534,7 @@ func (x codecSelfer1234) decSliceJob(v *[]Job, d *codec1978.Decoder) {
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 848)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 856)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
@ -4772,7 +4772,7 @@ func (x codecSelfer1234) decSliceCronJob(v *[]CronJob, d *codec1978.Decoder) {
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 1096)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 1104)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
|
|
@ -18858,7 +18858,7 @@ func (x codecSelfer1234) decSliceDeployment(v *[]Deployment, d *codec1978.Decode
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 888)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 896)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
@ -18977,7 +18977,7 @@ func (x codecSelfer1234) decSliceDaemonSet(v *[]DaemonSet, d *codec1978.Decoder)
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 784)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 792)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
@ -19691,7 +19691,7 @@ func (x codecSelfer1234) decSliceReplicaSet(v *[]ReplicaSet, d *codec1978.Decode
|
|||
|
||||
yyrg1 := len(yyv1) > 0
|
||||
yyv21 := yyv1
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 824)
|
||||
yyrl1, yyrt1 = z.DecInferLen(yyl1, z.DecBasicHandle().MaxInitLen, 832)
|
||||
if yyrt1 {
|
||||
if yyrl1 <= cap(yyv1) {
|
||||
yyv1 = yyv1[:yyrl1]
|
||||
|
|
|
@ -6383,6 +6383,13 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
Format: "",
|
||||
},
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "AutomountServiceAccountToken indicates whether a service account token should be automatically mounted.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"nodeName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.",
|
||||
|
@ -8285,6 +8292,13 @@ func GetOpenAPIDefinitions(ref openapi.ReferenceCallback) map[string]openapi.Ope
|
|||
},
|
||||
},
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.",
|
||||
Type: []string{"boolean"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -222,7 +222,7 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if s.MountServiceAccountToken {
|
||||
if s.MountServiceAccountToken && shouldAutomount(serviceAccount, pod) {
|
||||
if err := s.mountServiceAccountToken(serviceAccount, pod); err != nil {
|
||||
if _, ok := err.(errors.APIStatus); ok {
|
||||
return err
|
||||
|
@ -239,6 +239,19 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func shouldAutomount(sa *api.ServiceAccount, pod *api.Pod) bool {
|
||||
// Pod's preference wins
|
||||
if pod.Spec.AutomountServiceAccountToken != nil {
|
||||
return *pod.Spec.AutomountServiceAccountToken
|
||||
}
|
||||
// Then service account's
|
||||
if sa.AutomountServiceAccountToken != nil {
|
||||
return *sa.AutomountServiceAccountToken
|
||||
}
|
||||
// Default to true for backwards compatibility
|
||||
return true
|
||||
}
|
||||
|
||||
// enforceMountableSecrets indicates whether mountable secrets should be enforced for a particular service account
|
||||
// A global setting of true will override any flag set on the individual service account
|
||||
func (s *serviceAccount) enforceMountableSecrets(serviceAccount *api.ServiceAccount) bool {
|
||||
|
|
|
@ -35,6 +35,8 @@ import (
|
|||
|
||||
var serviceAccountTokenNamespaceVersion = utilversion.MustParseSemantic("v1.2.0")
|
||||
|
||||
var serviceAccountTokenAutomountVersion = utilversion.MustParseSemantic("v1.6.0-alpha.2")
|
||||
|
||||
var _ = framework.KubeDescribe("ServiceAccounts", func() {
|
||||
f := framework.NewDefaultFramework("svcaccounts")
|
||||
|
||||
|
@ -239,4 +241,145 @@ var _ = framework.KubeDescribe("ServiceAccounts", func() {
|
|||
})
|
||||
}
|
||||
})
|
||||
|
||||
It("should allow opting out of API token automount [Conformance]", func() {
|
||||
framework.SkipUnlessServerVersionGTE(serviceAccountTokenAutomountVersion, f.ClientSet.Discovery())
|
||||
|
||||
var err error
|
||||
trueValue := true
|
||||
falseValue := false
|
||||
mountSA := &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: "mount"}, AutomountServiceAccountToken: &trueValue}
|
||||
nomountSA := &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: "nomount"}, AutomountServiceAccountToken: &falseValue}
|
||||
mountSA, err = f.ClientSet.Core().ServiceAccounts(f.Namespace.Name).Create(mountSA)
|
||||
framework.ExpectNoError(err)
|
||||
nomountSA, err = f.ClientSet.Core().ServiceAccounts(f.Namespace.Name).Create(nomountSA)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
// Standard get, update retry loop
|
||||
framework.ExpectNoError(wait.Poll(time.Millisecond*500, framework.ServiceAccountProvisionTimeout, func() (bool, error) {
|
||||
By("getting the auto-created API token")
|
||||
sa, err := f.ClientSet.Core().ServiceAccounts(f.Namespace.Name).Get(mountSA.Name, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
framework.Logf("mount service account was not found")
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
framework.Logf("error getting mount service account: %v", err)
|
||||
return false, err
|
||||
}
|
||||
if len(sa.Secrets) == 0 {
|
||||
framework.Logf("mount service account has no secret references")
|
||||
return false, nil
|
||||
}
|
||||
for _, secretRef := range sa.Secrets {
|
||||
secret, err := f.ClientSet.Core().Secrets(f.Namespace.Name).Get(secretRef.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
framework.Logf("Error getting secret %s: %v", secretRef.Name, err)
|
||||
continue
|
||||
}
|
||||
if secret.Type == v1.SecretTypeServiceAccountToken {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
framework.Logf("default service account has no secret references to valid service account tokens")
|
||||
return false, nil
|
||||
}))
|
||||
|
||||
testcases := []struct {
|
||||
PodName string
|
||||
ServiceAccountName string
|
||||
AutomountPodSpec *bool
|
||||
ExpectTokenVolume bool
|
||||
}{
|
||||
{
|
||||
PodName: "pod-service-account-defaultsa",
|
||||
ServiceAccountName: "default",
|
||||
AutomountPodSpec: nil,
|
||||
ExpectTokenVolume: true, // default is true
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-mountsa",
|
||||
ServiceAccountName: mountSA.Name,
|
||||
AutomountPodSpec: nil,
|
||||
ExpectTokenVolume: true,
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-nomountsa",
|
||||
ServiceAccountName: nomountSA.Name,
|
||||
AutomountPodSpec: nil,
|
||||
ExpectTokenVolume: false,
|
||||
},
|
||||
|
||||
// Make sure pod spec trumps when opting in
|
||||
{
|
||||
PodName: "pod-service-account-defaultsa-mountspec",
|
||||
ServiceAccountName: "default",
|
||||
AutomountPodSpec: &trueValue,
|
||||
ExpectTokenVolume: true,
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-mountsa-mountspec",
|
||||
ServiceAccountName: mountSA.Name,
|
||||
AutomountPodSpec: &trueValue,
|
||||
ExpectTokenVolume: true,
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-nomountsa-mountspec",
|
||||
ServiceAccountName: nomountSA.Name,
|
||||
AutomountPodSpec: &trueValue,
|
||||
ExpectTokenVolume: true, // pod spec trumps
|
||||
},
|
||||
|
||||
// Make sure pod spec trumps when opting out
|
||||
{
|
||||
PodName: "pod-service-account-defaultsa-nomountspec",
|
||||
ServiceAccountName: "default",
|
||||
AutomountPodSpec: &falseValue,
|
||||
ExpectTokenVolume: false, // pod spec trumps
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-mountsa-nomountspec",
|
||||
ServiceAccountName: mountSA.Name,
|
||||
AutomountPodSpec: &falseValue,
|
||||
ExpectTokenVolume: false, // pod spec trumps
|
||||
},
|
||||
{
|
||||
PodName: "pod-service-account-nomountsa-nomountspec",
|
||||
ServiceAccountName: nomountSA.Name,
|
||||
AutomountPodSpec: &falseValue,
|
||||
ExpectTokenVolume: false, // pod spec trumps
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: tc.PodName},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{{Name: "token-test", Image: "gcr.io/google_containers/mounttest:0.7"}},
|
||||
RestartPolicy: v1.RestartPolicyNever,
|
||||
ServiceAccountName: tc.ServiceAccountName,
|
||||
AutomountServiceAccountToken: tc.AutomountPodSpec,
|
||||
},
|
||||
}
|
||||
createdPod, err := f.ClientSet.Core().Pods(f.Namespace.Name).Create(pod)
|
||||
framework.ExpectNoError(err)
|
||||
framework.Logf("created pod %s", tc.PodName)
|
||||
|
||||
hasServiceAccountTokenVolume := false
|
||||
for _, c := range createdPod.Spec.Containers {
|
||||
for _, vm := range c.VolumeMounts {
|
||||
if vm.MountPath == serviceaccount.DefaultAPITokenMountPath {
|
||||
hasServiceAccountTokenVolume = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasServiceAccountTokenVolume != tc.ExpectTokenVolume {
|
||||
framework.Failf("%s: expected volume=%v, got %v (%#v)", tc.PodName, tc.ExpectTokenVolume, hasServiceAccountTokenVolume, createdPod)
|
||||
} else {
|
||||
framework.Logf("pod %s service account token volume mount: %v", tc.PodName, hasServiceAccountTokenVolume)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue