interesting changes to add tokenreviews endpoint to implement webhook

This commit is contained in:
deads2k 2016-07-19 14:47:53 -04:00
parent eb79e2c859
commit 60dd4a5d26
29 changed files with 491 additions and 30 deletions

View File

@ -33,7 +33,7 @@ import (
var ( var (
test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata") test = flag.BoolP("test", "t", false, "set this flag to generate the client code for the testdata")
inputVersions = flag.StringSlice("input", []string{"api/", "extensions/", "autoscaling/", "batch/", "rbac/", "certificates/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,autoscaling/,batch/,rbac/\"") inputVersions = flag.StringSlice("input", []string{"api/", "extensions/", "autoscaling/", "authentication/", "batch/", "rbac/", "certificates/"}, "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\". Default to \"api/,extensions/,autoscaling/,batch/,rbac/\"")
includedTypesOverrides = flag.StringSlice("included-types-overrides", []string{}, "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient=true in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient=true will be used for other group versions.") includedTypesOverrides = flag.StringSlice("included-types-overrides", []string{}, "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient=true in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient=true will be used for other group versions.")
basePath = flag.String("input-base", "k8s.io/kubernetes/pkg/apis", "base path to look for the api group. Default to \"k8s.io/kubernetes/pkg/apis\"") basePath = flag.String("input-base", "k8s.io/kubernetes/pkg/apis", "base path to look for the api group. Default to \"k8s.io/kubernetes/pkg/apis\"")
clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.") clientsetName = flag.StringP("clientset-name", "n", "internalclientset", "the name of the generated clientset package.")

View File

@ -72,6 +72,7 @@ func New() *Generator {
`k8s.io/kubernetes/pkg/apis/batch/v1`, `k8s.io/kubernetes/pkg/apis/batch/v1`,
`k8s.io/kubernetes/pkg/apis/batch/v2alpha1`, `k8s.io/kubernetes/pkg/apis/batch/v2alpha1`,
`k8s.io/kubernetes/pkg/apis/apps/v1alpha1`, `k8s.io/kubernetes/pkg/apis/apps/v1alpha1`,
`k8s.io/kubernetes/pkg/apis/authentication/v1beta1`,
`k8s.io/kubernetes/pkg/apis/rbac/v1alpha1`, `k8s.io/kubernetes/pkg/apis/rbac/v1alpha1`,
`k8s.io/kubernetes/federation/apis/federation/v1beta1`, `k8s.io/kubernetes/federation/apis/federation/v1beta1`,
`k8s.io/kubernetes/pkg/apis/certificates/v1alpha1`, `k8s.io/kubernetes/pkg/apis/certificates/v1alpha1`,

View File

@ -2323,6 +2323,10 @@ __EOF__
# Post-condition: node is schedulable # Post-condition: node is schedulable
kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>' kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>'
# check webhook token authentication endpoint, kubectl doesn't actually display the returned object so this isn't super useful
# but it proves that works
kubectl create -f test/fixtures/pkg/kubectl/cmd/create/tokenreview.json --validate=false
##################### #####################
# Retrieve multiple # # Retrieve multiple #

View File

@ -60,7 +60,7 @@ KUBE_GOVERALLS_BIN=${KUBE_GOVERALLS_BIN:-}
# "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3" # "v1,compute/v1alpha1,experimental/v1alpha2;v1,compute/v2,experimental/v1alpha3"
# FIXME: due to current implementation of a test client (see: pkg/api/testapi/testapi.go) # FIXME: due to current implementation of a test client (see: pkg/api/testapi/testapi.go)
# ONLY the last version is tested in each group. # ONLY the last version is tested in each group.
KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,autoscaling/v1,batch/v1,batch/v2alpha1,extensions/v1beta1,apps/v1alpha1,federation/v1beta1,policy/v1alpha1,rbac.authorization.k8s.io/v1alpha1,certificates/v1alpha1"} KUBE_TEST_API_VERSIONS=${KUBE_TEST_API_VERSIONS:-"v1,autoscaling/v1,authentication.k8s.io/v1beta1,batch/v1,batch/v2alpha1,extensions/v1beta1,apps/v1alpha1,federation/v1beta1,policy/v1alpha1,rbac.authorization.k8s.io/v1alpha1,certificates/v1alpha1"}
# once we have multiple group supports # once we have multiple group supports
# Create a junit-style XML test report in this directory if set. # Create a junit-style XML test report in this directory if set.
KUBE_JUNIT_REPORT_DIR=${KUBE_JUNIT_REPORT_DIR:-} KUBE_JUNIT_REPORT_DIR=${KUBE_JUNIT_REPORT_DIR:-}

View File

@ -57,7 +57,7 @@ EOF
mv "$TMPFILE" "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go" mv "$TMPFILE" "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"
} }
GROUP_VERSIONS=(unversioned v1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac/v1alpha1 certificates/v1alpha1) GROUP_VERSIONS=(unversioned v1 authentication/v1beta1 authorization/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac/v1alpha1 certificates/v1alpha1)
# To avoid compile errors, remove the currently existing files. # To avoid compile errors, remove the currently existing files.
for group_version in "${GROUP_VERSIONS[@]}"; do for group_version in "${GROUP_VERSIONS[@]}"; do
rm -f "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go" rm -f "pkg/$(kube::util::group-version-to-pkg-path "${group_version}")/types_swagger_doc_generated.go"

View File

@ -74,7 +74,7 @@ APISERVER_PID=$!
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: " kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver: "
SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/" SWAGGER_API_PATH="http://127.0.0.1:${API_PORT}/swaggerapi/"
DEFAULT_GROUP_VERSIONS="v1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac.authorization.k8s.io/v1alpha1 certificates/v1alpha1" DEFAULT_GROUP_VERSIONS="v1 authentication.k8s.io/v1beta1 autoscaling/v1 batch/v1 batch/v2alpha1 extensions/v1beta1 apps/v1alpha1 policy/v1alpha1 rbac.authorization.k8s.io/v1alpha1 certificates/v1alpha1"
VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS} VERSIONS=${VERSIONS:-$DEFAULT_GROUP_VERSIONS}
kube::log::status "Updating " ${SWAGGER_ROOT_DIR} kube::log::status "Updating " ${SWAGGER_ROOT_DIR}

View File

@ -42,6 +42,7 @@ import (
_ "k8s.io/kubernetes/federation/apis/federation/install" _ "k8s.io/kubernetes/federation/apis/federation/install"
_ "k8s.io/kubernetes/pkg/api/install" _ "k8s.io/kubernetes/pkg/api/install"
_ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/apps/install"
_ "k8s.io/kubernetes/pkg/apis/authentication/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install" _ "k8s.io/kubernetes/pkg/apis/batch/install"
_ "k8s.io/kubernetes/pkg/apis/certificates/install" _ "k8s.io/kubernetes/pkg/apis/certificates/install"

View File

@ -16,5 +16,4 @@ limitations under the License.
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +groupName=authentication.k8s.io // +groupName=authentication.k8s.io
package authentication // import "k8s.io/kubernetes/pkg/apis/authentication" package authentication // import "k8s.io/kubernetes/pkg/apis/authentication"

View File

@ -17,12 +17,20 @@ limitations under the License.
package authentication package authentication
import ( import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
) )
// +genclient=true
// +nonNamespaced=true
// +noMethods=true
// TokenReview attempts to authenticate a token to a known user. // TokenReview attempts to authenticate a token to a known user.
type TokenReview struct { type TokenReview struct {
unversioned.TypeMeta unversioned.TypeMeta
// ObjectMeta fulfills the meta.ObjectMetaAccessor interface so that the stock
// REST handler paths work
api.ObjectMeta
// Spec holds information about the request being evaluated // Spec holds information about the request being evaluated
Spec TokenReviewSpec Spec TokenReviewSpec
@ -38,11 +46,14 @@ type TokenReviewSpec struct {
} }
// TokenReviewStatus is the result of the token authentication request. // TokenReviewStatus is the result of the token authentication request.
// This type mirrors the authentication.Token interface
type TokenReviewStatus struct { type TokenReviewStatus struct {
// Authenticated indicates that the token was associated with a known user. // Authenticated indicates that the token was associated with a known user.
Authenticated bool Authenticated bool
// User is the UserInfo associated with the provided token. // User is the UserInfo associated with the provided token.
User UserInfo User UserInfo
// Error indicates that the token couldn't be checked
Error string
} }
// UserInfo holds the information about the user needed to implement the // UserInfo holds the information about the user needed to implement the
@ -57,5 +68,8 @@ type UserInfo struct {
// The names of groups this user is a part of. // The names of groups this user is a part of.
Groups []string Groups []string
// Any additional information provided by the authenticator. // Any additional information provided by the authenticator.
Extra map[string][]string Extra map[string]ExtraValue
} }
// ExtraValue masks the value so protobuf can generate
type ExtraValue []string

View File

@ -16,5 +16,5 @@ limitations under the License.
// +k8s:deepcopy-gen=package,register // +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/authentication // +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/authentication
// +groupName=authentication.k8s.io
package v1beta1 // import "k8s.io/kubernetes/pkg/apis/authentication/v1beta1" package v1beta1 // import "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"

View File

@ -18,46 +18,58 @@ package v1beta1
import ( import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/api/v1"
) )
// +genclient=true
// +nonNamespaced=true
// +noMethods=true
// TokenReview attempts to authenticate a token to a known user. // TokenReview attempts to authenticate a token to a known user.
// Note: TokenReview requests may be cached by the webhook token authenticator // Note: TokenReview requests may be cached by the webhook token authenticator
// plugin in the kube-apiserver. // plugin in the kube-apiserver.
type TokenReview struct { type TokenReview struct {
unversioned.TypeMeta `json:",inline"` unversioned.TypeMeta `json:",inline"`
v1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Spec holds information about the request being evaluated // Spec holds information about the request being evaluated
Spec TokenReviewSpec `json:"spec"` Spec TokenReviewSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// Status is filled in by the server and indicates whether the request can be authenticated. // Status is filled in by the server and indicates whether the request can be authenticated.
Status TokenReviewStatus `json:"status,omitempty"` Status TokenReviewStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
} }
// TokenReviewSpec is a description of the token authentication request. // TokenReviewSpec is a description of the token authentication request.
type TokenReviewSpec struct { type TokenReviewSpec struct {
// Token is the opaque bearer token. // Token is the opaque bearer token.
Token string `json:"token,omitempty"` Token string `json:"token,omitempty" protobuf:"bytes,1,opt,name=token"`
} }
// TokenReviewStatus is the result of the token authentication request. // TokenReviewStatus is the result of the token authentication request.
type TokenReviewStatus struct { type TokenReviewStatus struct {
// Authenticated indicates that the token was associated with a known user. // Authenticated indicates that the token was associated with a known user.
Authenticated bool `json:"authenticated,omitempty"` Authenticated bool `json:"authenticated,omitempty" protobuf:"varint,1,opt,name=authenticated"`
// User is the UserInfo associated with the provided token. // User is the UserInfo associated with the provided token.
User UserInfo `json:"user,omitempty"` User UserInfo `json:"user,omitempty" protobuf:"bytes,2,opt,name=user"`
// Error indicates that the token couldn't be checked
Error string `json:"error,omitempty" protobuf:"bytes,3,opt,name=error"`
} }
// UserInfo holds the information about the user needed to implement the // UserInfo holds the information about the user needed to implement the
// user.Info interface. // user.Info interface.
type UserInfo struct { type UserInfo struct {
// The name that uniquely identifies this user among all active users. // The name that uniquely identifies this user among all active users.
Username string `json:"username,omitempty"` Username string `json:"username,omitempty" protobuf:"bytes,1,opt,name=username"`
// A unique value that identifies this user across time. If this user is // A unique value that identifies this user across time. If this user is
// deleted and another user by the same name is added, they will have // deleted and another user by the same name is added, they will have
// different UIDs. // different UIDs.
UID string `json:"uid,omitempty"` UID string `json:"uid,omitempty" protobuf:"bytes,2,opt,name=uid"`
// The names of groups this user is a part of. // The names of groups this user is a part of.
Groups []string `json:"groups,omitempty"` Groups []string `json:"groups,omitempty" protobuf:"bytes,3,rep,name=groups"`
// Any additional information provided by the authenticator. // Any additional information provided by the authenticator.
Extra map[string][]string `json:"extra,omitempty"` Extra map[string]ExtraValue `json:"extra,omitempty" protobuf:"bytes,4,rep,name=extra"`
} }
// ExtraValue masks the value so protobuf can generate
// +protobuf.nullable=true
type ExtraValue []string

View File

@ -0,0 +1,28 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
import (
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/client/testing/core"
)
func (c *FakeTokenReviews) Create(tokenReview *authenticationapi.TokenReview) (result *authenticationapi.TokenReview, err error) {
obj, err := c.Fake.Invokes(core.NewRootCreateAction(authenticationapi.SchemeGroupVersion.WithResource("tokenreviews"), tokenReview), &authenticationapi.TokenReview{})
return obj.(*authenticationapi.TokenReview), err
}

View File

@ -0,0 +1,35 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
)
type TokenReviewExpansion interface {
Create(tokenReview *authenticationapi.TokenReview) (result *authenticationapi.TokenReview, err error)
}
func (c *tokenReviews) Create(tokenReview *authenticationapi.TokenReview) (result *authenticationapi.TokenReview, err error) {
result = &authenticationapi.TokenReview{}
err = c.client.Post().
Resource("tokenreviews").
Body(tokenReview).
Do().
Into(result)
return
}

View File

@ -0,0 +1,77 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/client/restclient"
)
type AuthenticationInterface interface {
TokenReviewsInterface
}
// AuthenticationClient is used to interact with Kubernetes authentication features.
type AuthenticationClient struct {
*restclient.RESTClient
}
func (c *AuthenticationClient) TokenReviews() TokenReviewInterface {
return newTokenReviews(c)
}
func NewAuthentication(c *restclient.Config) (*AuthenticationClient, error) {
config := *c
if err := setAuthenticationDefaults(&config); err != nil {
return nil, err
}
client, err := restclient.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &AuthenticationClient{client}, nil
}
func NewAuthenticationOrDie(c *restclient.Config) *AuthenticationClient {
client, err := NewAuthentication(c)
if err != nil {
panic(err)
}
return client
}
func setAuthenticationDefaults(config *restclient.Config) error {
// if authentication group is not registered, return an error
g, err := registered.Group(authentication.GroupName)
if err != nil {
return err
}
config.APIPath = defaultAPIPath
if config.UserAgent == "" {
config.UserAgent = restclient.DefaultKubernetesUserAgent()
}
// TODO: Unconditionally set the config.Version, until we fix the config.
//if config.Version == "" {
copyGroupVersion := g.GroupVersion
config.GroupVersion = &copyGroupVersion
//}
config.NegotiatedSerializer = api.Codecs
return nil
}

View File

@ -46,6 +46,7 @@ type Interface interface {
ConfigMapsNamespacer ConfigMapsNamespacer
Apps() AppsInterface Apps() AppsInterface
Autoscaling() AutoscalingInterface Autoscaling() AutoscalingInterface
Authentication() AuthenticationInterface
Batch() BatchInterface Batch() BatchInterface
Extensions() ExtensionsInterface Extensions() ExtensionsInterface
Rbac() RbacInterface Rbac() RbacInterface
@ -120,6 +121,7 @@ func (c *Client) ConfigMaps(namespace string) ConfigMapsInterface {
type Client struct { type Client struct {
*restclient.RESTClient *restclient.RESTClient
*AutoscalingClient *AutoscalingClient
*AuthenticationClient
*BatchClient *BatchClient
*ExtensionsClient *ExtensionsClient
*AppsClient *AppsClient
@ -155,6 +157,10 @@ func (c *Client) Autoscaling() AutoscalingInterface {
return c.AutoscalingClient return c.AutoscalingClient
} }
func (c *Client) Authentication() AuthenticationInterface {
return c.AuthenticationClient
}
func (c *Client) Batch() BatchInterface { func (c *Client) Batch() BatchInterface {
return c.BatchClient return c.BatchClient
} }

View File

@ -23,6 +23,7 @@ import (
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
"k8s.io/kubernetes/pkg/apis/certificates" "k8s.io/kubernetes/pkg/apis/certificates"
@ -71,6 +72,15 @@ func New(c *restclient.Config) (*Client, error) {
} }
} }
var authenticationClient *AuthenticationClient
if registered.IsRegistered(authentication.GroupName) {
authenticationConfig := *c
authenticationClient, err = NewAuthentication(&authenticationConfig)
if err != nil {
return nil, err
}
}
var batchClient *BatchClient var batchClient *BatchClient
if registered.IsRegistered(batch.GroupName) { if registered.IsRegistered(batch.GroupName) {
batchConfig := *c batchConfig := *c
@ -123,7 +133,18 @@ func New(c *restclient.Config) (*Client, error) {
} }
} }
return &Client{RESTClient: client, AutoscalingClient: autoscalingClient, BatchClient: batchClient, CertificatesClient: certsClient, ExtensionsClient: extensionsClient, DiscoveryClient: discoveryClient, AppsClient: appsClient, PolicyClient: policyClient, RbacClient: rbacClient}, nil return &Client{
RESTClient: client,
AppsClient: appsClient,
AuthenticationClient: authenticationClient,
AutoscalingClient: autoscalingClient,
BatchClient: batchClient,
CertificatesClient: certsClient,
DiscoveryClient: discoveryClient,
ExtensionsClient: extensionsClient,
PolicyClient: policyClient,
RbacClient: rbacClient,
}, nil
} }
// MatchesServerVersion queries the server to compares the build version // MatchesServerVersion queries the server to compares the build version

View File

@ -23,7 +23,7 @@ import (
_ "k8s.io/kubernetes/pkg/api/install" _ "k8s.io/kubernetes/pkg/api/install"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
_ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/apps/install"
_ "k8s.io/kubernetes/pkg/apis/authentication.k8s.io/install" _ "k8s.io/kubernetes/pkg/apis/authentication/install"
_ "k8s.io/kubernetes/pkg/apis/authorization/install" _ "k8s.io/kubernetes/pkg/apis/authorization/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install" _ "k8s.io/kubernetes/pkg/apis/batch/install"

View File

@ -0,0 +1,35 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testclient
import (
"k8s.io/kubernetes/pkg/apis/authentication"
)
// FakeTokenReviews implements ClusterRoleInterface
type FakeTokenReviews struct {
Fake *FakeAuthentication
}
func (c *FakeTokenReviews) Create(review *authentication.TokenReview) (*authentication.TokenReview, error) {
obj, err := c.Fake.Invokes(NewRootCreateAction("tokenreviews", review), review)
if obj == nil {
return nil, err
}
return obj.(*authentication.TokenReview), err
}

View File

@ -313,6 +313,10 @@ func (c *Fake) Rbac() client.RbacInterface {
return &FakeRbac{Fake: c} return &FakeRbac{Fake: c}
} }
func (c *Fake) Authentication() client.AuthenticationInterface {
return &FakeAuthentication{Fake: c}
}
// SwaggerSchema returns an empty swagger.ApiDeclaration for testing // SwaggerSchema returns an empty swagger.ApiDeclaration for testing
func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) {
action := ActionImpl{} action := ActionImpl{}
@ -353,6 +357,18 @@ func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.Hori
return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace} return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace}
} }
func NewSimpleFakeAuthentication(objects ...runtime.Object) *FakeAuthentication {
return &FakeAuthentication{Fake: NewSimpleFake(objects...)}
}
type FakeAuthentication struct {
*Fake
}
func (c *FakeAuthentication) TokenReviews() client.TokenReviewInterface {
return &FakeTokenReviews{Fake: c}
}
// NewSimpleFakeBatch returns a client that will respond with the provided objects // NewSimpleFakeBatch returns a client that will respond with the provided objects
func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch { func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch {
return &FakeBatch{Fake: NewSimpleFake(objects...)} return &FakeBatch{Fake: NewSimpleFake(objects...)}

View File

@ -0,0 +1,49 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
"k8s.io/kubernetes/pkg/apis/authentication"
)
// TokenReviews has methods to work with TokenReview resources in a namespace
type TokenReviewsInterface interface {
TokenReviews() TokenReviewInterface
}
// TokenReviewInterface has methods to work with TokenReview resources.
type TokenReviewInterface interface {
Create(tokenReview *authentication.TokenReview) (*authentication.TokenReview, error)
}
// tokenReviews implements TokenReviewsNamespacer interface
type tokenReviews struct {
client *AuthenticationClient
}
// newTokenReviews returns a tokenReviews
func newTokenReviews(c *AuthenticationClient) *tokenReviews {
return &tokenReviews{
client: c,
}
}
func (c *tokenReviews) Create(obj *authentication.TokenReview) (result *authentication.TokenReview, err error) {
result = &authentication.TokenReview{}
err = c.client.Post().Resource("tokenreviews").Body(obj).Do().Into(result)
return
}

View File

@ -503,10 +503,11 @@ func monitorFor(p *Propagator, clientPool dynamic.ClientPool, resource unversion
} }
var ignoredResources = map[unversioned.GroupVersionResource]struct{}{ var ignoredResources = map[unversioned.GroupVersionResource]struct{}{
unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {}, unversioned.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "replicationcontrollers"}: {},
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {}, unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "bindings"}: {},
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {}, unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "componentstatuses"}: {},
unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {}, unversioned.GroupVersionResource{Group: "", Version: "v1", Resource: "events"}: {},
unversioned.GroupVersionResource{Group: "authentication.k8s.io", Version: "v1beta1", Resource: "tokenreviews"}: {},
} }
func NewGarbageCollector(clientPool dynamic.ClientPool, resources []unversioned.GroupVersionResource) (*GarbageCollector, error) { func NewGarbageCollector(clientPool dynamic.ClientPool, resources []unversioned.GroupVersionResource) (*GarbageCollector, error) {

View File

@ -23,6 +23,7 @@ import (
_ "k8s.io/kubernetes/pkg/api/install" _ "k8s.io/kubernetes/pkg/api/install"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
_ "k8s.io/kubernetes/pkg/apis/apps/install" _ "k8s.io/kubernetes/pkg/apis/apps/install"
_ "k8s.io/kubernetes/pkg/apis/authentication/install"
_ "k8s.io/kubernetes/pkg/apis/authorization/install" _ "k8s.io/kubernetes/pkg/apis/authorization/install"
_ "k8s.io/kubernetes/pkg/apis/autoscaling/install" _ "k8s.io/kubernetes/pkg/apis/autoscaling/install"
_ "k8s.io/kubernetes/pkg/apis/batch/install" _ "k8s.io/kubernetes/pkg/apis/batch/install"

View File

@ -34,6 +34,7 @@ import (
apiv1 "k8s.io/kubernetes/pkg/api/v1" apiv1 "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/apimachinery/registered" "k8s.io/kubernetes/pkg/apimachinery/registered"
appsapi "k8s.io/kubernetes/pkg/apis/apps/v1alpha1" appsapi "k8s.io/kubernetes/pkg/apis/apps/v1alpha1"
authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
"k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/autoscaling"
autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1" autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
@ -200,6 +201,7 @@ func New(c *Config) (*Master, error) {
} }
c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{} c.RESTStorageProviders[policy.GroupName] = PolicyRESTStorageProvider{}
c.RESTStorageProviders[rbac.GroupName] = RBACRESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser} c.RESTStorageProviders[rbac.GroupName] = RBACRESTStorageProvider{AuthorizerRBACSuperUser: c.AuthorizerRBACSuperUser}
c.RESTStorageProviders[authenticationv1beta1.GroupName] = AuthenticationRESTStorageProvider{Authenticator: c.Authenticator}
m.InstallAPIs(c) m.InstallAPIs(c)
// TODO: Attempt clean shutdown? // TODO: Attempt clean shutdown?
@ -754,6 +756,7 @@ func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig {
apiv1.SchemeGroupVersion, apiv1.SchemeGroupVersion,
extensionsapiv1beta1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion,
batchapiv1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion,
authenticationv1beta1.SchemeGroupVersion,
autoscalingapiv1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion,
appsapi.SchemeGroupVersion, appsapi.SchemeGroupVersion,
policyapiv1alpha1.SchemeGroupVersion, policyapiv1alpha1.SchemeGroupVersion,

View File

@ -0,0 +1,62 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package master
import (
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/apis/authentication"
authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
"k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/genericapiserver"
"k8s.io/kubernetes/pkg/registry/tokenreview"
)
type AuthenticationRESTStorageProvider struct {
Authenticator authenticator.Request
}
var _ RESTStorageProvider = &AuthenticationRESTStorageProvider{}
func (p AuthenticationRESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
// TODO figure out how to make the swagger generation stable, while allowing this endpoint to be disabled.
// if p.Authenticator == nil {
// return genericapiserver.APIGroupInfo{}, false
// }
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(authentication.GroupName)
if apiResourceConfigSource.AnyResourcesForVersionEnabled(authenticationv1beta1.SchemeGroupVersion) {
apiGroupInfo.VersionedResourcesStorageMap[authenticationv1beta1.SchemeGroupVersion.Version] = p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter)
apiGroupInfo.GroupMeta.GroupVersion = authenticationv1beta1.SchemeGroupVersion
}
return apiGroupInfo, true
}
func (p AuthenticationRESTStorageProvider) v1beta1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter RESTOptionsGetter) map[string]rest.Storage {
version := authenticationv1beta1.SchemeGroupVersion
storage := map[string]rest.Storage{}
if apiResourceConfigSource.AnyResourcesForVersionEnabled(authenticationv1beta1.SchemeGroupVersion) {
if apiResourceConfigSource.ResourceEnabled(version.WithResource("tokenreviews")) {
tokenReviewStorage := tokenreview.NewREST(p.Authenticator)
storage["tokenreviews"] = tokenReviewStorage
}
}
return storage
}

View File

@ -0,0 +1,78 @@
/*
Copyright 2015 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tokenreview
import (
"fmt"
"net/http"
"k8s.io/kubernetes/pkg/api"
apierrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/runtime"
)
type REST struct {
tokenAuthenticator authenticator.Request
}
func NewREST(tokenAuthenticator authenticator.Request) *REST {
return &REST{tokenAuthenticator: tokenAuthenticator}
}
func (r *REST) New() runtime.Object {
return &authentication.TokenReview{}
}
func (r *REST) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) {
tokenReview, ok := obj.(*authentication.TokenReview)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("not a TokenReview: %#v", obj))
}
namespace := api.NamespaceValue(ctx)
if len(namespace) != 0 {
return nil, apierrors.NewBadRequest(fmt.Sprintf("namespace is not allowed on this type: %v", namespace))
}
if r.tokenAuthenticator == nil {
return tokenReview, nil
}
// create a header that contains nothing but the token
fakeReq := &http.Request{Header: http.Header{}}
fakeReq.Header.Add("Authorization", "Bearer "+tokenReview.Spec.Token)
tokenUser, ok, err := r.tokenAuthenticator.AuthenticateRequest(fakeReq)
tokenReview.Status.Authenticated = ok
if err != nil {
tokenReview.Status.Error = err.Error()
}
if tokenUser != nil {
tokenReview.Status.User = authentication.UserInfo{
Username: tokenUser.GetName(),
UID: tokenUser.GetUID(),
Groups: tokenUser.GetGroups(),
Extra: map[string]authentication.ExtraValue{},
}
for k, v := range tokenUser.GetExtra() {
tokenReview.Status.User.Extra[k] = authentication.ExtraValue(v)
}
}
return tokenReview, nil
}

View File

@ -22,14 +22,14 @@ import (
"time" "time"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io/v1beta1" "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
"k8s.io/kubernetes/pkg/auth/authenticator" "k8s.io/kubernetes/pkg/auth/authenticator"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/util/cache" "k8s.io/kubernetes/pkg/util/cache"
"k8s.io/kubernetes/plugin/pkg/webhook" "k8s.io/kubernetes/plugin/pkg/webhook"
_ "k8s.io/kubernetes/pkg/apis/authentication.k8s.io/install" _ "k8s.io/kubernetes/pkg/apis/authentication/install"
) )
var ( var (

View File

@ -30,7 +30,7 @@ import (
"time" "time"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/authentication.k8s.io/v1beta1" "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
"k8s.io/kubernetes/pkg/auth/user" "k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1"
) )
@ -353,10 +353,21 @@ func TestWebhookTokenAuthenticator(t *testing.T) {
type authenticationUserInfo v1beta1.UserInfo type authenticationUserInfo v1beta1.UserInfo
func (a *authenticationUserInfo) GetName() string { return a.Username } func (a *authenticationUserInfo) GetName() string { return a.Username }
func (a *authenticationUserInfo) GetUID() string { return a.UID } func (a *authenticationUserInfo) GetUID() string { return a.UID }
func (a *authenticationUserInfo) GetGroups() []string { return a.Groups } func (a *authenticationUserInfo) GetGroups() []string { return a.Groups }
func (a *authenticationUserInfo) GetExtra() map[string][]string { return a.Extra }
func (a *authenticationUserInfo) GetExtra() map[string][]string {
if a.Extra == nil {
return nil
}
ret := map[string][]string{}
for k, v := range a.Extra {
ret[k] = []string(v)
}
return ret
}
// Ensure v1beta1.UserInfo contains the fields necessary to implement the // Ensure v1beta1.UserInfo contains the fields necessary to implement the
// user.Info interface. // user.Info interface.

View File

@ -0,0 +1,7 @@
{
"apiVersion": "authentication.k8s.io/v1beta1",
"kind": "TokenReview",
"spec": {
"token": "test-token"
}
}

View File

@ -38,7 +38,7 @@ import (
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/testapi"
authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication.k8s.io/v1beta1" authenticationv1beta1 "k8s.io/kubernetes/pkg/apis/authentication/v1beta1"
"k8s.io/kubernetes/pkg/apis/autoscaling" "k8s.io/kubernetes/pkg/apis/autoscaling"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apiserver" "k8s.io/kubernetes/pkg/apiserver"