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
39a9043b
Commit
39a9043b
authored
Feb 14, 2016
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #21095 from liggitt/sa-namespace
Auto commit by PR queue bot
parents
4ff418ca
20216fa6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
100 additions
and
8 deletions
+100
-8
types.go
pkg/api/types.go
+2
-0
types.go
pkg/api/v1/types.go
+2
-0
client_config.go
pkg/client/unversioned/clientcmd/client_config.go
+12
-3
tokens_controller.go
pkg/controller/serviceaccount/tokens_controller.go
+8
-1
tokens_controller_test.go
pkg/controller/serviceaccount/tokens_controller_test.go
+56
-4
service_accounts.go
test/e2e/service_accounts.go
+20
-0
No files found.
pkg/api/types.go
View file @
39a9043b
...
@@ -2250,6 +2250,8 @@ const (
...
@@ -2250,6 +2250,8 @@ const (
ServiceAccountKubeconfigKey
=
"kubernetes.kubeconfig"
ServiceAccountKubeconfigKey
=
"kubernetes.kubeconfig"
// ServiceAccountRootCAKey is the key of the optional root certificate authority for SecretTypeServiceAccountToken secrets
// ServiceAccountRootCAKey is the key of the optional root certificate authority for SecretTypeServiceAccountToken secrets
ServiceAccountRootCAKey
=
"ca.crt"
ServiceAccountRootCAKey
=
"ca.crt"
// ServiceAccountNamespaceKey is the key of the optional namespace to use as the default for namespaced API calls
ServiceAccountNamespaceKey
=
"namespace"
// SecretTypeDockercfg contains a dockercfg file that follows the same format rules as ~/.dockercfg
// SecretTypeDockercfg contains a dockercfg file that follows the same format rules as ~/.dockercfg
//
//
...
...
pkg/api/v1/types.go
View file @
39a9043b
...
@@ -2721,6 +2721,8 @@ const (
...
@@ -2721,6 +2721,8 @@ const (
ServiceAccountKubeconfigKey
=
"kubernetes.kubeconfig"
ServiceAccountKubeconfigKey
=
"kubernetes.kubeconfig"
// ServiceAccountRootCAKey is the key of the optional root certificate authority for SecretTypeServiceAccountToken secrets
// ServiceAccountRootCAKey is the key of the optional root certificate authority for SecretTypeServiceAccountToken secrets
ServiceAccountRootCAKey
=
"ca.crt"
ServiceAccountRootCAKey
=
"ca.crt"
// ServiceAccountNamespaceKey is the key of the optional namespace to use as the default for namespaced API calls
ServiceAccountNamespaceKey
=
"namespace"
// SecretTypeDockercfg contains a dockercfg file that follows the same format rules as ~/.dockercfg
// SecretTypeDockercfg contains a dockercfg file that follows the same format rules as ~/.dockercfg
//
//
...
...
pkg/client/unversioned/clientcmd/client_config.go
View file @
39a9043b
...
@@ -19,8 +19,10 @@ package clientcmd
...
@@ -19,8 +19,10 @@ package clientcmd
import
(
import
(
"fmt"
"fmt"
"io"
"io"
"io/ioutil"
"net/url"
"net/url"
"os"
"os"
"strings"
"github.com/golang/glog"
"github.com/golang/glog"
"github.com/imdario/mergo"
"github.com/imdario/mergo"
...
@@ -325,12 +327,19 @@ func (inClusterClientConfig) ClientConfig() (*client.Config, error) {
...
@@ -325,12 +327,19 @@ func (inClusterClientConfig) ClientConfig() (*client.Config, error) {
}
}
func
(
inClusterClientConfig
)
Namespace
()
(
string
,
error
)
{
func
(
inClusterClientConfig
)
Namespace
()
(
string
,
error
)
{
// TODO: generic way to figure out what namespace you are running in?
// This way assumes you've set the POD_NAMESPACE environment variable using the downward API.
// This way assumes you've set the POD_NAMESPACE environment variable
// This check has to be done first for backwards compatibility with the way InClusterConfig was originally set up
// using the downward API.
if
ns
:=
os
.
Getenv
(
"POD_NAMESPACE"
);
ns
!=
""
{
if
ns
:=
os
.
Getenv
(
"POD_NAMESPACE"
);
ns
!=
""
{
return
ns
,
nil
return
ns
,
nil
}
}
// Fall back to the namespace associated with the service account token, if available
if
data
,
err
:=
ioutil
.
ReadFile
(
"/var/run/secrets/kubernetes.io/serviceaccount/namespace"
);
err
==
nil
{
if
ns
:=
strings
.
TrimSpace
(
string
(
data
));
len
(
ns
)
>
0
{
return
ns
,
nil
}
}
return
"default"
,
nil
return
"default"
,
nil
}
}
...
...
pkg/controller/serviceaccount/tokens_controller.go
View file @
39a9043b
...
@@ -325,6 +325,7 @@ func (e *TokensController) createSecret(serviceAccount *api.ServiceAccount) erro
...
@@ -325,6 +325,7 @@ func (e *TokensController) createSecret(serviceAccount *api.ServiceAccount) erro
return
err
return
err
}
}
secret
.
Data
[
api
.
ServiceAccountTokenKey
]
=
[]
byte
(
token
)
secret
.
Data
[
api
.
ServiceAccountTokenKey
]
=
[]
byte
(
token
)
secret
.
Data
[
api
.
ServiceAccountNamespaceKey
]
=
[]
byte
(
serviceAccount
.
Namespace
)
if
e
.
rootCA
!=
nil
&&
len
(
e
.
rootCA
)
>
0
{
if
e
.
rootCA
!=
nil
&&
len
(
e
.
rootCA
)
>
0
{
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
=
e
.
rootCA
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
=
e
.
rootCA
}
}
...
@@ -364,10 +365,12 @@ func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAcco
...
@@ -364,10 +365,12 @@ func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAcco
caData
:=
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
caData
:=
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
needsCA
:=
len
(
e
.
rootCA
)
>
0
&&
bytes
.
Compare
(
caData
,
e
.
rootCA
)
!=
0
needsCA
:=
len
(
e
.
rootCA
)
>
0
&&
bytes
.
Compare
(
caData
,
e
.
rootCA
)
!=
0
needsNamespace
:=
len
(
secret
.
Data
[
api
.
ServiceAccountNamespaceKey
])
==
0
tokenData
:=
secret
.
Data
[
api
.
ServiceAccountTokenKey
]
tokenData
:=
secret
.
Data
[
api
.
ServiceAccountTokenKey
]
needsToken
:=
len
(
tokenData
)
==
0
needsToken
:=
len
(
tokenData
)
==
0
if
!
needsCA
&&
!
needsToken
{
if
!
needsCA
&&
!
needsToken
&&
!
needsNamespace
{
return
nil
return
nil
}
}
...
@@ -375,6 +378,10 @@ func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAcco
...
@@ -375,6 +378,10 @@ func (e *TokensController) generateTokenIfNeeded(serviceAccount *api.ServiceAcco
if
needsCA
{
if
needsCA
{
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
=
e
.
rootCA
secret
.
Data
[
api
.
ServiceAccountRootCAKey
]
=
e
.
rootCA
}
}
// Set the namespace
if
needsNamespace
{
secret
.
Data
[
api
.
ServiceAccountNamespaceKey
]
=
[]
byte
(
secret
.
Namespace
)
}
// Generate the token
// Generate the token
if
needsToken
{
if
needsToken
{
...
...
pkg/controller/serviceaccount/tokens_controller_test.go
View file @
39a9043b
...
@@ -115,8 +115,9 @@ func createdTokenSecret() *api.Secret {
...
@@ -115,8 +115,9 @@ func createdTokenSecret() *api.Secret {
},
},
Type
:
api
.
SecretTypeServiceAccountToken
,
Type
:
api
.
SecretTypeServiceAccountToken
,
Data
:
map
[
string
][]
byte
{
Data
:
map
[
string
][]
byte
{
"token"
:
[]
byte
(
"ABC"
),
"token"
:
[]
byte
(
"ABC"
),
"ca.crt"
:
[]
byte
(
"CA Data"
),
"ca.crt"
:
[]
byte
(
"CA Data"
),
"namespace"
:
[]
byte
(
"default"
),
},
},
}
}
}
}
...
@@ -136,8 +137,9 @@ func serviceAccountTokenSecret() *api.Secret {
...
@@ -136,8 +137,9 @@ func serviceAccountTokenSecret() *api.Secret {
},
},
Type
:
api
.
SecretTypeServiceAccountToken
,
Type
:
api
.
SecretTypeServiceAccountToken
,
Data
:
map
[
string
][]
byte
{
Data
:
map
[
string
][]
byte
{
"token"
:
[]
byte
(
"ABC"
),
"token"
:
[]
byte
(
"ABC"
),
"ca.crt"
:
[]
byte
(
"CA Data"
),
"ca.crt"
:
[]
byte
(
"CA Data"
),
"namespace"
:
[]
byte
(
"default"
),
},
},
}
}
}
}
...
@@ -163,6 +165,20 @@ func serviceAccountTokenSecretWithCAData(data []byte) *api.Secret {
...
@@ -163,6 +165,20 @@ func serviceAccountTokenSecretWithCAData(data []byte) *api.Secret {
return
secret
return
secret
}
}
// serviceAccountTokenSecretWithoutNamespaceData returns an existing ServiceAccountToken secret that lacks namespace data
func
serviceAccountTokenSecretWithoutNamespaceData
()
*
api
.
Secret
{
secret
:=
serviceAccountTokenSecret
()
delete
(
secret
.
Data
,
api
.
ServiceAccountNamespaceKey
)
return
secret
}
// serviceAccountTokenSecretWithNamespaceData returns an existing ServiceAccountToken secret with the specified namespace data
func
serviceAccountTokenSecretWithNamespaceData
(
data
[]
byte
)
*
api
.
Secret
{
secret
:=
serviceAccountTokenSecret
()
secret
.
Data
[
api
.
ServiceAccountNamespaceKey
]
=
data
return
secret
}
func
TestTokenCreation
(
t
*
testing
.
T
)
{
func
TestTokenCreation
(
t
*
testing
.
T
)
{
testcases
:=
map
[
string
]
struct
{
testcases
:=
map
[
string
]
struct
{
ClientObjects
[]
runtime
.
Object
ClientObjects
[]
runtime
.
Object
...
@@ -379,6 +395,24 @@ func TestTokenCreation(t *testing.T) {
...
@@ -379,6 +395,24 @@ func TestTokenCreation(t *testing.T) {
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
},
},
},
},
"added token secret without namespace data"
:
{
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecretWithoutNamespaceData
()},
ExistingServiceAccount
:
serviceAccount
(
tokenSecretReferences
()),
AddedSecret
:
serviceAccountTokenSecretWithoutNamespaceData
(),
ExpectedActions
:
[]
core
.
Action
{
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
},
},
"added token secret with custom namespace data"
:
{
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecretWithNamespaceData
([]
byte
(
"custom"
))},
ExistingServiceAccount
:
serviceAccount
(
tokenSecretReferences
()),
AddedSecret
:
serviceAccountTokenSecretWithNamespaceData
([]
byte
(
"custom"
)),
ExpectedActions
:
[]
core
.
Action
{
// no update is performed... the custom namespace is preserved
},
},
"updated secret without serviceaccount"
:
{
"updated secret without serviceaccount"
:
{
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecret
()},
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecret
()},
...
@@ -422,6 +456,24 @@ func TestTokenCreation(t *testing.T) {
...
@@ -422,6 +456,24 @@ func TestTokenCreation(t *testing.T) {
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
},
},
},
},
"updated token secret without namespace data"
:
{
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecretWithoutNamespaceData
()},
ExistingServiceAccount
:
serviceAccount
(
tokenSecretReferences
()),
UpdatedSecret
:
serviceAccountTokenSecretWithoutNamespaceData
(),
ExpectedActions
:
[]
core
.
Action
{
core
.
NewUpdateAction
(
"secrets"
,
api
.
NamespaceDefault
,
serviceAccountTokenSecret
()),
},
},
"updated token secret with custom namespace data"
:
{
ClientObjects
:
[]
runtime
.
Object
{
serviceAccountTokenSecretWithNamespaceData
([]
byte
(
"custom"
))},
ExistingServiceAccount
:
serviceAccount
(
tokenSecretReferences
()),
UpdatedSecret
:
serviceAccountTokenSecretWithNamespaceData
([]
byte
(
"custom"
)),
ExpectedActions
:
[]
core
.
Action
{
// no update is performed... the custom namespace is preserved
},
},
"deleted secret without serviceaccount"
:
{
"deleted secret without serviceaccount"
:
{
DeletedSecret
:
serviceAccountTokenSecret
(),
DeletedSecret
:
serviceAccountTokenSecret
(),
...
...
test/e2e/service_accounts.go
View file @
39a9043b
...
@@ -24,11 +24,14 @@ import (
...
@@ -24,11 +24,14 @@ import (
apierrors
"k8s.io/kubernetes/pkg/api/errors"
apierrors
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/util/wait"
"k8s.io/kubernetes/pkg/version"
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
"k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
.
"github.com/onsi/ginkgo"
.
"github.com/onsi/ginkgo"
)
)
var
serviceAccountTokenNamespaceVersion
=
version
.
MustParse
(
"v1.2.0"
)
var
_
=
Describe
(
"ServiceAccounts"
,
func
()
{
var
_
=
Describe
(
"ServiceAccounts"
,
func
()
{
f
:=
NewFramework
(
"svcaccounts"
)
f
:=
NewFramework
(
"svcaccounts"
)
...
@@ -94,11 +97,28 @@ var _ = Describe("ServiceAccounts", func() {
...
@@ -94,11 +97,28 @@ var _ = Describe("ServiceAccounts", func() {
},
},
}
}
supportsTokenNamespace
,
_
:=
serverVersionGTE
(
serviceAccountTokenNamespaceVersion
,
f
.
Client
)
if
supportsTokenNamespace
{
pod
.
Spec
.
Containers
=
append
(
pod
.
Spec
.
Containers
,
api
.
Container
{
Name
:
"namespace-test"
,
Image
:
"gcr.io/google_containers/mounttest:0.2"
,
Args
:
[]
string
{
fmt
.
Sprintf
(
"--file_content=%s/%s"
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountNamespaceKey
),
},
})
}
f
.
TestContainerOutput
(
"consume service account token"
,
pod
,
0
,
[]
string
{
f
.
TestContainerOutput
(
"consume service account token"
,
pod
,
0
,
[]
string
{
fmt
.
Sprintf
(
`content of file "%s/%s": %s`
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountTokenKey
,
tokenContent
),
fmt
.
Sprintf
(
`content of file "%s/%s": %s`
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountTokenKey
,
tokenContent
),
})
})
f
.
TestContainerOutput
(
"consume service account root CA"
,
pod
,
1
,
[]
string
{
f
.
TestContainerOutput
(
"consume service account root CA"
,
pod
,
1
,
[]
string
{
fmt
.
Sprintf
(
`content of file "%s/%s": %s`
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountRootCAKey
,
rootCAContent
),
fmt
.
Sprintf
(
`content of file "%s/%s": %s`
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountRootCAKey
,
rootCAContent
),
})
})
if
supportsTokenNamespace
{
f
.
TestContainerOutput
(
"consume service account namespace"
,
pod
,
2
,
[]
string
{
fmt
.
Sprintf
(
`content of file "%s/%s": %s`
,
serviceaccount
.
DefaultAPITokenMountPath
,
api
.
ServiceAccountNamespaceKey
,
f
.
Namespace
.
Name
),
})
}
})
})
})
})
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