mirror of https://github.com/k3s-io/k3s
add delegating auth options
parent
7c0e48f544
commit
5cea15ac9f
|
@ -41,7 +41,6 @@ go_library(
|
|||
"//pkg/master:go_default_library",
|
||||
"//pkg/registry/cachesize:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//pkg/util/errors:go_default_library",
|
||||
"//pkg/util/net:go_default_library",
|
||||
"//pkg/util/wait:go_default_library",
|
||||
|
|
|
@ -26,10 +26,9 @@ go_library(
|
|||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/apis/componentconfig:go_default_library",
|
||||
"//pkg/apis/componentconfig/v1alpha1:go_default_library",
|
||||
"//pkg/apiserver/authenticator:go_default_library",
|
||||
"//pkg/auth/authenticator:go_default_library",
|
||||
"//pkg/auth/authenticator/bearertoken:go_default_library",
|
||||
"//pkg/auth/authorizer:go_default_library",
|
||||
"//pkg/auth/group:go_default_library",
|
||||
"//pkg/capabilities:go_default_library",
|
||||
"//pkg/client/chaosclient:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5:go_default_library",
|
||||
|
@ -99,10 +98,6 @@ go_library(
|
|||
"//pkg/volume/rbd:go_default_library",
|
||||
"//pkg/volume/secret:go_default_library",
|
||||
"//pkg/volume/vsphere_volume:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/request/anonymous:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/request/union:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/request/x509:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/token/webhook:go_default_library",
|
||||
"//plugin/pkg/auth/authorizer/webhook:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:github.com/spf13/cobra",
|
||||
|
|
|
@ -22,21 +22,15 @@ import (
|
|||
"reflect"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/componentconfig"
|
||||
apiserverauthenticator "k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator"
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/auth/group"
|
||||
clientset "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5"
|
||||
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1"
|
||||
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authorization/v1beta1"
|
||||
alwaysallowauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||
"k8s.io/kubernetes/pkg/kubelet/server"
|
||||
"k8s.io/kubernetes/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous"
|
||||
unionauth "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509"
|
||||
webhooktoken "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook"
|
||||
webhooksar "k8s.io/kubernetes/plugin/pkg/auth/authorizer/webhook"
|
||||
)
|
||||
|
||||
|
@ -67,43 +61,21 @@ func buildAuth(nodeName types.NodeName, client clientset.Interface, config compo
|
|||
}
|
||||
|
||||
func buildAuthn(client authenticationclient.TokenReviewInterface, authn componentconfig.KubeletAuthentication) (authenticator.Request, error) {
|
||||
authenticators := []authenticator.Request{}
|
||||
|
||||
// x509 client cert auth
|
||||
if len(authn.X509.ClientCAFile) > 0 {
|
||||
clientCAs, err := cert.NewPool(authn.X509.ClientCAFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to load client CA file %s: %v", authn.X509.ClientCAFile, err)
|
||||
}
|
||||
verifyOpts := x509.DefaultVerifyOptions()
|
||||
verifyOpts.Roots = clientCAs
|
||||
authenticators = append(authenticators, x509.New(verifyOpts, x509.CommonNameUserConversion))
|
||||
authenticatorConfig := apiserverauthenticator.DelegatingAuthenticatorConfig{
|
||||
Anonymous: authn.Anonymous.Enabled,
|
||||
CacheTTL: authn.Webhook.CacheTTL.Duration,
|
||||
ClientCAFile: authn.X509.ClientCAFile,
|
||||
}
|
||||
|
||||
// bearer token auth that uses authentication.k8s.io TokenReview to determine userinfo
|
||||
if authn.Webhook.Enabled {
|
||||
if client == nil {
|
||||
return nil, errors.New("no client provided, cannot use webhook authentication")
|
||||
}
|
||||
tokenAuth, err := webhooktoken.NewFromInterface(client, authn.Webhook.CacheTTL.Duration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(tokenAuth))
|
||||
authenticatorConfig.TokenAccessReviewClient = client
|
||||
}
|
||||
|
||||
if len(authenticators) == 0 {
|
||||
if authn.Anonymous.Enabled {
|
||||
return anonymous.NewAuthenticator(), nil
|
||||
}
|
||||
return nil, errors.New("No authentication method configured")
|
||||
}
|
||||
|
||||
authenticator := group.NewGroupAdder(unionauth.New(authenticators...), []string{"system:authenticated"})
|
||||
if authn.Anonymous.Enabled {
|
||||
authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator())
|
||||
}
|
||||
return authenticator, nil
|
||||
authenticator, _, err := authenticatorConfig.New()
|
||||
return authenticator, err
|
||||
}
|
||||
|
||||
func buildAuthz(client authorizationclient.SubjectAccessReviewInterface, authz componentconfig.KubeletAuthorization) (authorizer.Authorizer, error) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -127,7 +127,7 @@ func Run(s *options.ServerRunOptions) error {
|
|||
storageFactory.SetEtcdLocation(groupResource, servers)
|
||||
}
|
||||
|
||||
apiAuthenticator, securityDefinitions, err := authenticator.New(s.Authentication.ToAuthenticationConfig())
|
||||
apiAuthenticator, securityDefinitions, err := authenticator.New(s.Authentication.ToAuthenticationConfig(s.SecureServing.ClientCA))
|
||||
if err != nil {
|
||||
glog.Fatalf("Invalid Authentication Config: %v", err)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ auth-provider
|
|||
auth-provider
|
||||
auth-provider-arg
|
||||
auth-provider-arg
|
||||
authentication-kubeconfig
|
||||
authentication-token-webhook
|
||||
authentication-token-webhook-cache-ttl
|
||||
authentication-token-webhook-config-file
|
||||
|
|
|
@ -12,13 +12,17 @@ load(
|
|||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["authn.go"],
|
||||
srcs = [
|
||||
"builtin.go",
|
||||
"delegating.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/auth/authenticator:go_default_library",
|
||||
"//pkg/auth/authenticator/bearertoken:go_default_library",
|
||||
"//pkg/auth/group:go_default_library",
|
||||
"//pkg/auth/user:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//pkg/util/cert:go_default_library",
|
||||
"//plugin/pkg/auth/authenticator/password/keystone:go_default_library",
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
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 authenticator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator"
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||
"k8s.io/kubernetes/pkg/auth/group"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/util/cert"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/anonymous"
|
||||
unionauth "k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/x509"
|
||||
webhooktoken "k8s.io/kubernetes/plugin/pkg/auth/authenticator/token/webhook"
|
||||
)
|
||||
|
||||
// DelegatingAuthenticatorConfig is the minimal configuration needed to create an authenticator
|
||||
// built to delegate authentication to a kube API server
|
||||
type DelegatingAuthenticatorConfig struct {
|
||||
Anonymous bool
|
||||
|
||||
TokenAccessReviewClient authenticationclient.TokenReviewInterface
|
||||
|
||||
// CacheTTL is the length of time that a token authentication answer will be cached.
|
||||
CacheTTL time.Duration
|
||||
|
||||
// ClientCAFile is the CA bundle file used to authenticate client certificates
|
||||
ClientCAFile string
|
||||
}
|
||||
|
||||
func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
|
||||
authenticators := []authenticator.Request{}
|
||||
securityDefinitions := spec.SecurityDefinitions{}
|
||||
|
||||
// x509 client cert auth
|
||||
if len(c.ClientCAFile) > 0 {
|
||||
clientCAs, err := cert.NewPool(c.ClientCAFile)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to load client CA file %s: %v", c.ClientCAFile, err)
|
||||
}
|
||||
verifyOpts := x509.DefaultVerifyOptions()
|
||||
verifyOpts.Roots = clientCAs
|
||||
authenticators = append(authenticators, x509.New(verifyOpts, x509.CommonNameUserConversion))
|
||||
}
|
||||
|
||||
if c.TokenAccessReviewClient != nil {
|
||||
tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.CacheTTL)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
authenticators = append(authenticators, bearertoken.New(tokenAuth))
|
||||
|
||||
securityDefinitions["BearerToken"] = &spec.SecurityScheme{
|
||||
SecuritySchemeProps: spec.SecuritySchemeProps{
|
||||
Type: "apiKey",
|
||||
Name: "authorization",
|
||||
In: "header",
|
||||
Description: "Bearer Token authentication",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if len(authenticators) == 0 {
|
||||
if c.Anonymous {
|
||||
return anonymous.NewAuthenticator(), &securityDefinitions, nil
|
||||
}
|
||||
return nil, nil, errors.New("No authentication method configured")
|
||||
}
|
||||
|
||||
authenticator := group.NewGroupAdder(unionauth.New(authenticators...), []string{user.AllAuthenticated})
|
||||
if c.Anonymous {
|
||||
authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator())
|
||||
}
|
||||
return authenticator, &securityDefinitions, nil
|
||||
|
||||
}
|
|
@ -13,7 +13,7 @@ load(
|
|||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"authenticator.go",
|
||||
"authentication.go",
|
||||
"doc.go",
|
||||
"etcd.go",
|
||||
"server_run_options.go",
|
||||
|
@ -25,7 +25,9 @@ go_library(
|
|||
"//pkg/api:go_default_library",
|
||||
"//pkg/apimachinery/registered:go_default_library",
|
||||
"//pkg/apiserver/authenticator:go_default_library",
|
||||
"//pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1:go_default_library",
|
||||
"//pkg/client/restclient:go_default_library",
|
||||
"//pkg/client/unversioned/clientcmd:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
"//pkg/storage/storagebackend:go_default_library",
|
||||
"//pkg/util/config:go_default_library",
|
||||
|
|
|
@ -22,6 +22,8 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apiserver/authenticator"
|
||||
authenticationclient "k8s.io/kubernetes/pkg/client/clientset_generated/release_1_5/typed/authentication/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
|
||||
)
|
||||
|
||||
type BuiltInAuthenticationOptions struct {
|
||||
|
@ -243,8 +245,10 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.AuthenticatorConfig {
|
||||
ret := authenticator.AuthenticatorConfig{}
|
||||
func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig(clientCAFile string) authenticator.AuthenticatorConfig {
|
||||
ret := authenticator.AuthenticatorConfig{
|
||||
ClientCAFile: clientCAFile,
|
||||
}
|
||||
if s.Anonymous != nil {
|
||||
ret.Anonymous = s.Anonymous.Allow
|
||||
}
|
||||
|
@ -305,11 +309,21 @@ func (s *RequestHeaderAuthenticationOptions) AuthenticationRequestHeaderConfig()
|
|||
}
|
||||
}
|
||||
|
||||
// DelegatingAuthenticationOptions provides an easy way for composing API servers to delegate their authentication to
|
||||
// the root kube API server
|
||||
type DelegatingAuthenticationOptions struct {
|
||||
// RemoteKubeConfigFile is the file to use to connect to a "normal" kube API server which hosts the
|
||||
// TokenAcessReview.authentication.k8s.io endpoint for checking tokens.
|
||||
RemoteKubeConfigFile string
|
||||
|
||||
// CacheTTL is the length of time that a token authentication answer will be cached.
|
||||
CacheTTL time.Duration
|
||||
}
|
||||
|
||||
func NewDelegatingAuthenticationOptions() *DelegatingAuthenticationOptions {
|
||||
return &DelegatingAuthenticationOptions{}
|
||||
return &DelegatingAuthenticationOptions{
|
||||
CacheTTL: 5 * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) Validate() []error {
|
||||
|
@ -318,4 +332,44 @@ func (s *DelegatingAuthenticationOptions) Validate() []error {
|
|||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&s.RemoteKubeConfigFile, "authentication-kubeconfig", s.RemoteKubeConfigFile, ""+
|
||||
"kubeconfig file pointing at the 'core' kubernetes server with enough rights to create "+
|
||||
" tokenaccessreviews.authencation.k8s.io.")
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) ToAuthenticationConfig(clientCAFile string) (authenticator.DelegatingAuthenticatorConfig, error) {
|
||||
tokenClient, err := s.newTokenAccessReview()
|
||||
if err != nil {
|
||||
return authenticator.DelegatingAuthenticatorConfig{}, err
|
||||
}
|
||||
|
||||
ret := authenticator.DelegatingAuthenticatorConfig{
|
||||
Anonymous: true,
|
||||
TokenAccessReviewClient: tokenClient,
|
||||
CacheTTL: s.CacheTTL,
|
||||
ClientCAFile: clientCAFile,
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) newTokenAccessReview() (authenticationclient.TokenReviewInterface, error) {
|
||||
if len(s.RemoteKubeConfigFile) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
loadingRules.ExplicitPath = s.RemoteKubeConfigFile
|
||||
loader := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{})
|
||||
|
||||
clientConfig, err := loader.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := authenticationclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client.TokenReviews(), nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue