Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
0d6e877d
Unverified
Commit
0d6e877d
authored
Dec 02, 2016
by
Jordan Liggitt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add automountServiceAccountToken field to PodSpec and ServiceAccount types
parent
fbc94c08
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
173 additions
and
1 deletion
+173
-1
types.go
pkg/api/types.go
+8
-0
types.go
pkg/api/v1/types.go
+8
-0
admission.go
plugin/pkg/admission/serviceaccount/admission.go
+14
-1
service_accounts.go
test/e2e/service_accounts.go
+143
-0
No files found.
pkg/api/types.go
View file @
0d6e877d
...
@@ -1887,6 +1887,9 @@ type PodSpec struct {
...
@@ -1887,6 +1887,9 @@ type PodSpec struct {
// ServiceAccountName is the name of the ServiceAccount to use to run this pod
// 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
// The pod will be allowed to use secrets referenced by the ServiceAccount
ServiceAccountName
string
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,
// 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
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
...
@@ -2425,6 +2428,11 @@ type ServiceAccount struct {
...
@@ -2425,6 +2428,11 @@ type ServiceAccount struct {
// can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet.
// can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet.
// +optional
// +optional
ImagePullSecrets
[]
LocalObjectReference
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
// ServiceAccountList is a list of ServiceAccount objects
...
...
pkg/api/v1/types.go
View file @
0d6e877d
...
@@ -2160,6 +2160,9 @@ type PodSpec struct {
...
@@ -2160,6 +2160,9 @@ type PodSpec struct {
// +k8s:conversion-gen=false
// +k8s:conversion-gen=false
// +optional
// +optional
DeprecatedServiceAccount
string
`json:"serviceAccount,omitempty" protobuf:"bytes,9,opt,name=serviceAccount"`
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,
// 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
// the scheduler simply schedules this pod onto that node, assuming that it fits resource
...
@@ -2801,6 +2804,11 @@ type ServiceAccount struct {
...
@@ -2801,6 +2804,11 @@ type ServiceAccount struct {
// More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret
// More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret
// +optional
// +optional
ImagePullSecrets
[]
LocalObjectReference
`json:"imagePullSecrets,omitempty" protobuf:"bytes,3,rep,name=imagePullSecrets"`
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
// ServiceAccountList is a list of ServiceAccount objects
...
...
plugin/pkg/admission/serviceaccount/admission.go
View file @
0d6e877d
...
@@ -222,7 +222,7 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
...
@@ -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
err
:=
s
.
mountServiceAccountToken
(
serviceAccount
,
pod
);
err
!=
nil
{
if
_
,
ok
:=
err
.
(
errors
.
APIStatus
);
ok
{
if
_
,
ok
:=
err
.
(
errors
.
APIStatus
);
ok
{
return
err
return
err
...
@@ -239,6 +239,19 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
...
@@ -239,6 +239,19 @@ func (s *serviceAccount) Admit(a admission.Attributes) (err error) {
return
nil
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
// 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
// A global setting of true will override any flag set on the individual service account
func
(
s
*
serviceAccount
)
enforceMountableSecrets
(
serviceAccount
*
api
.
ServiceAccount
)
bool
{
func
(
s
*
serviceAccount
)
enforceMountableSecrets
(
serviceAccount
*
api
.
ServiceAccount
)
bool
{
...
...
test/e2e/service_accounts.go
View file @
0d6e877d
...
@@ -35,6 +35,8 @@ import (
...
@@ -35,6 +35,8 @@ import (
var
serviceAccountTokenNamespaceVersion
=
utilversion
.
MustParseSemantic
(
"v1.2.0"
)
var
serviceAccountTokenNamespaceVersion
=
utilversion
.
MustParseSemantic
(
"v1.2.0"
)
var
serviceAccountTokenAutomountVersion
=
utilversion
.
MustParseSemantic
(
"v1.6.0-alpha.2"
)
var
_
=
framework
.
KubeDescribe
(
"ServiceAccounts"
,
func
()
{
var
_
=
framework
.
KubeDescribe
(
"ServiceAccounts"
,
func
()
{
f
:=
framework
.
NewDefaultFramework
(
"svcaccounts"
)
f
:=
framework
.
NewDefaultFramework
(
"svcaccounts"
)
...
@@ -239,4 +241,145 @@ var _ = framework.KubeDescribe("ServiceAccounts", func() {
...
@@ -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
)
}
}
})
})
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment