blob: 61114c1c8669768f78a322396fc85544b5e6af4b [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package authenticatorfactory
18
19import (
20 "errors"
21 "fmt"
22 "time"
23
24 "github.com/go-openapi/spec"
25
26 "k8s.io/apiserver/pkg/authentication/authenticator"
27 "k8s.io/apiserver/pkg/authentication/group"
28 "k8s.io/apiserver/pkg/authentication/request/anonymous"
29 "k8s.io/apiserver/pkg/authentication/request/bearertoken"
30 "k8s.io/apiserver/pkg/authentication/request/headerrequest"
31 unionauth "k8s.io/apiserver/pkg/authentication/request/union"
32 "k8s.io/apiserver/pkg/authentication/request/websocket"
33 "k8s.io/apiserver/pkg/authentication/request/x509"
34 webhooktoken "k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
35 authenticationclient "k8s.io/client-go/kubernetes/typed/authentication/v1beta1"
36 "k8s.io/client-go/util/cert"
37)
38
39// DelegatingAuthenticatorConfig is the minimal configuration needed to create an authenticator
40// built to delegate authentication to a kube API server
41type DelegatingAuthenticatorConfig struct {
42 Anonymous bool
43
44 TokenAccessReviewClient authenticationclient.TokenReviewInterface
45
46 // CacheTTL is the length of time that a token authentication answer will be cached.
47 CacheTTL time.Duration
48
49 // ClientCAFile is the CA bundle file used to authenticate client certificates
50 ClientCAFile string
51
52 RequestHeaderConfig *RequestHeaderConfig
53}
54
55func (c DelegatingAuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDefinitions, error) {
56 authenticators := []authenticator.Request{}
57 securityDefinitions := spec.SecurityDefinitions{}
58
59 // front-proxy first, then remote
60 // Add the front proxy authenticator if requested
61 if c.RequestHeaderConfig != nil {
62 requestHeaderAuthenticator, err := headerrequest.NewSecure(
63 c.RequestHeaderConfig.ClientCA,
64 c.RequestHeaderConfig.AllowedClientNames,
65 c.RequestHeaderConfig.UsernameHeaders,
66 c.RequestHeaderConfig.GroupHeaders,
67 c.RequestHeaderConfig.ExtraHeaderPrefixes,
68 )
69 if err != nil {
70 return nil, nil, err
71 }
72 authenticators = append(authenticators, requestHeaderAuthenticator)
73 }
74
75 // x509 client cert auth
76 if len(c.ClientCAFile) > 0 {
77 clientCAs, err := cert.NewPool(c.ClientCAFile)
78 if err != nil {
79 return nil, nil, fmt.Errorf("unable to load client CA file %s: %v", c.ClientCAFile, err)
80 }
81 verifyOpts := x509.DefaultVerifyOptions()
82 verifyOpts.Roots = clientCAs
83 authenticators = append(authenticators, x509.New(verifyOpts, x509.CommonNameUserConversion))
84 }
85
86 if c.TokenAccessReviewClient != nil {
87 tokenAuth, err := webhooktoken.NewFromInterface(c.TokenAccessReviewClient, c.CacheTTL)
88 if err != nil {
89 return nil, nil, err
90 }
91 authenticators = append(authenticators, bearertoken.New(tokenAuth), websocket.NewProtocolAuthenticator(tokenAuth))
92
93 securityDefinitions["BearerToken"] = &spec.SecurityScheme{
94 SecuritySchemeProps: spec.SecuritySchemeProps{
95 Type: "apiKey",
96 Name: "authorization",
97 In: "header",
98 Description: "Bearer Token authentication",
99 },
100 }
101 }
102
103 if len(authenticators) == 0 {
104 if c.Anonymous {
105 return anonymous.NewAuthenticator(), &securityDefinitions, nil
106 }
107 return nil, nil, errors.New("No authentication method configured")
108 }
109
110 authenticator := group.NewAuthenticatedGroupAdder(unionauth.New(authenticators...))
111 if c.Anonymous {
112 authenticator = unionauth.NewFailOnError(authenticator, anonymous.NewAuthenticator())
113 }
114 return authenticator, &securityDefinitions, nil
115}