2019-01-12 04:58:27 +00:00
/ *
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 options
import (
"fmt"
"net/url"
"strings"
"time"
"github.com/spf13/pflag"
"k8s.io/klog"
"k8s.io/apiserver/pkg/authentication/authenticator"
genericapiserver "k8s.io/apiserver/pkg/server"
2019-04-07 17:07:55 +00:00
genericoptions "k8s.io/apiserver/pkg/server/options"
2019-01-12 04:58:27 +00:00
kubeauthenticator "k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
)
type BuiltInAuthenticationOptions struct {
APIAudiences [ ] string
2019-04-07 17:07:55 +00:00
ClientCert * genericoptions . ClientCertAuthenticationOptions
2019-01-12 04:58:27 +00:00
PasswordFile * PasswordFileAuthenticationOptions
2019-04-07 17:07:55 +00:00
RequestHeader * genericoptions . RequestHeaderAuthenticationOptions
2019-01-12 04:58:27 +00:00
ServiceAccounts * ServiceAccountAuthenticationOptions
TokenFile * TokenFileAuthenticationOptions
WebHook * WebHookAuthenticationOptions
TokenSuccessCacheTTL time . Duration
TokenFailureCacheTTL time . Duration
}
type PasswordFileAuthenticationOptions struct {
BasicAuthFile string
}
type ServiceAccountAuthenticationOptions struct {
KeyFiles [ ] string
Lookup bool
Issuer string
MaxExpiration time . Duration
}
type TokenFileAuthenticationOptions struct {
TokenFile string
}
type WebHookAuthenticationOptions struct {
ConfigFile string
CacheTTL time . Duration
}
func NewBuiltInAuthenticationOptions ( ) * BuiltInAuthenticationOptions {
return & BuiltInAuthenticationOptions {
TokenSuccessCacheTTL : 10 * time . Second ,
TokenFailureCacheTTL : 0 * time . Second ,
}
}
func ( s * BuiltInAuthenticationOptions ) WithAll ( ) * BuiltInAuthenticationOptions {
return s .
2019-04-07 17:07:55 +00:00
WithClientCert ( ) .
2019-01-12 04:58:27 +00:00
WithPasswordFile ( ) .
2019-04-07 17:07:55 +00:00
WithRequestHeader ( ) .
2019-01-12 04:58:27 +00:00
WithServiceAccounts ( ) .
WithTokenFile ( ) .
WithWebHook ( )
}
2019-04-07 17:07:55 +00:00
func ( s * BuiltInAuthenticationOptions ) WithClientCert ( ) * BuiltInAuthenticationOptions {
s . ClientCert = & genericoptions . ClientCertAuthenticationOptions { }
return s
}
2019-01-12 04:58:27 +00:00
func ( s * BuiltInAuthenticationOptions ) WithPasswordFile ( ) * BuiltInAuthenticationOptions {
s . PasswordFile = & PasswordFileAuthenticationOptions { }
return s
}
2019-04-07 17:07:55 +00:00
func ( s * BuiltInAuthenticationOptions ) WithRequestHeader ( ) * BuiltInAuthenticationOptions {
s . RequestHeader = & genericoptions . RequestHeaderAuthenticationOptions { }
return s
}
2019-01-12 04:58:27 +00:00
func ( s * BuiltInAuthenticationOptions ) WithServiceAccounts ( ) * BuiltInAuthenticationOptions {
s . ServiceAccounts = & ServiceAccountAuthenticationOptions { Lookup : true }
return s
}
func ( s * BuiltInAuthenticationOptions ) WithTokenFile ( ) * BuiltInAuthenticationOptions {
s . TokenFile = & TokenFileAuthenticationOptions { }
return s
}
func ( s * BuiltInAuthenticationOptions ) WithWebHook ( ) * BuiltInAuthenticationOptions {
s . WebHook = & WebHookAuthenticationOptions {
CacheTTL : 2 * time . Minute ,
}
return s
}
// Validate checks invalid config combination
func ( s * BuiltInAuthenticationOptions ) Validate ( ) [ ] error {
allErrors := [ ] error { }
if s . ServiceAccounts != nil && len ( s . ServiceAccounts . Issuer ) > 0 && strings . Contains ( s . ServiceAccounts . Issuer , ":" ) {
if _ , err := url . Parse ( s . ServiceAccounts . Issuer ) ; err != nil {
allErrors = append ( allErrors , fmt . Errorf ( "service-account-issuer contained a ':' but was not a valid URL: %v" , err ) )
}
}
return allErrors
}
func ( s * BuiltInAuthenticationOptions ) AddFlags ( fs * pflag . FlagSet ) {
fs . StringSliceVar ( & s . APIAudiences , "api-audiences" , s . APIAudiences , "" +
"Identifiers of the API. The service account token authenticator will validate that " +
"tokens used against the API are bound to at least one of these audiences. If the " +
"--service-account-issuer flag is configured and this flag is not, this field " +
"defaults to a single element list containing the issuer URL ." )
2019-04-07 17:07:55 +00:00
if s . ClientCert != nil {
s . ClientCert . AddFlags ( fs )
}
2019-01-12 04:58:27 +00:00
if s . PasswordFile != nil {
fs . StringVar ( & s . PasswordFile . BasicAuthFile , "basic-auth-file" , s . PasswordFile . BasicAuthFile , "" +
"If set, the file that will be used to admit requests to the secure port of the API server " +
"via http basic authentication." )
}
2019-04-07 17:07:55 +00:00
if s . RequestHeader != nil {
s . RequestHeader . AddFlags ( fs )
}
2019-01-12 04:58:27 +00:00
if s . ServiceAccounts != nil {
fs . StringArrayVar ( & s . ServiceAccounts . KeyFiles , "service-account-key-file" , s . ServiceAccounts . KeyFiles , "" +
"File containing PEM-encoded x509 RSA or ECDSA private or public keys, used to verify " +
"ServiceAccount tokens. The specified file can contain multiple keys, and the flag can " +
"be specified multiple times with different files. If unspecified, " +
"--tls-private-key-file is used. Must be specified when " +
"--service-account-signing-key is provided" )
fs . BoolVar ( & s . ServiceAccounts . Lookup , "service-account-lookup" , s . ServiceAccounts . Lookup ,
"If true, validate ServiceAccount tokens exist in etcd as part of authentication." )
fs . StringVar ( & s . ServiceAccounts . Issuer , "service-account-issuer" , s . ServiceAccounts . Issuer , "" +
"Identifier of the service account token issuer. The issuer will assert this identifier " +
"in \"iss\" claim of issued tokens. This value is a string or URI." )
// Deprecated in 1.13
fs . StringSliceVar ( & s . APIAudiences , "service-account-api-audiences" , s . APIAudiences , "" +
"Identifiers of the API. The service account token authenticator will validate that " +
"tokens used against the API are bound to at least one of these audiences." )
fs . MarkDeprecated ( "service-account-api-audiences" , "Use --api-audiences" )
fs . DurationVar ( & s . ServiceAccounts . MaxExpiration , "service-account-max-token-expiration" , s . ServiceAccounts . MaxExpiration , "" +
"The maximum validity duration of a token created by the service account token issuer. If an otherwise valid " +
"TokenRequest with a validity duration larger than this value is requested, a token will be issued with a validity duration of this value." )
}
if s . TokenFile != nil {
fs . StringVar ( & s . TokenFile . TokenFile , "token-auth-file" , s . TokenFile . TokenFile , "" +
"If set, the file that will be used to secure the secure port of the API server " +
"via token authentication." )
}
if s . WebHook != nil {
fs . StringVar ( & s . WebHook . ConfigFile , "authentication-token-webhook-config-file" , s . WebHook . ConfigFile , "" +
"File with webhook configuration for token authentication in kubeconfig format. " +
"The API server will query the remote service to determine authentication for bearer tokens." )
fs . DurationVar ( & s . WebHook . CacheTTL , "authentication-token-webhook-cache-ttl" , s . WebHook . CacheTTL ,
"The duration to cache responses from the webhook token authenticator." )
}
}
func ( s * BuiltInAuthenticationOptions ) ToAuthenticationConfig ( ) kubeauthenticator . Config {
ret := kubeauthenticator . Config {
TokenSuccessCacheTTL : s . TokenSuccessCacheTTL ,
TokenFailureCacheTTL : s . TokenFailureCacheTTL ,
}
2019-04-07 17:07:55 +00:00
if s . ClientCert != nil {
ret . ClientCAFile = s . ClientCert . ClientCA
}
2019-01-12 04:58:27 +00:00
if s . PasswordFile != nil {
ret . BasicAuthFile = s . PasswordFile . BasicAuthFile
}
2019-04-07 17:07:55 +00:00
if s . RequestHeader != nil {
ret . RequestHeaderConfig = s . RequestHeader . ToAuthenticationRequestHeaderConfig ( )
}
2019-01-12 04:58:27 +00:00
2019-04-07 17:07:55 +00:00
ret . APIAudiences = s . APIAudiences
2019-01-12 04:58:27 +00:00
if s . ServiceAccounts != nil {
if s . ServiceAccounts . Issuer != "" && len ( s . APIAudiences ) == 0 {
ret . APIAudiences = authenticator . Audiences { s . ServiceAccounts . Issuer }
}
ret . ServiceAccountKeyFiles = s . ServiceAccounts . KeyFiles
ret . ServiceAccountIssuer = s . ServiceAccounts . Issuer
ret . ServiceAccountLookup = s . ServiceAccounts . Lookup
}
if s . TokenFile != nil {
ret . TokenAuthFile = s . TokenFile . TokenFile
}
if s . WebHook != nil {
ret . WebhookTokenAuthnConfigFile = s . WebHook . ConfigFile
ret . WebhookTokenAuthnCacheTTL = s . WebHook . CacheTTL
if len ( s . WebHook . ConfigFile ) > 0 && s . WebHook . CacheTTL > 0 {
if s . TokenSuccessCacheTTL > 0 && s . WebHook . CacheTTL < s . TokenSuccessCacheTTL {
klog . Warningf ( "the webhook cache ttl of %s is shorter than the overall cache ttl of %s for successful token authentication attempts." , s . WebHook . CacheTTL , s . TokenSuccessCacheTTL )
}
if s . TokenFailureCacheTTL > 0 && s . WebHook . CacheTTL < s . TokenFailureCacheTTL {
klog . Warningf ( "the webhook cache ttl of %s is shorter than the overall cache ttl of %s for failed token authentication attempts." , s . WebHook . CacheTTL , s . TokenFailureCacheTTL )
}
}
}
return ret
}
func ( o * BuiltInAuthenticationOptions ) ApplyTo ( c * genericapiserver . Config ) error {
if o == nil {
return nil
}
2019-04-07 17:07:55 +00:00
var err error
if o . ClientCert != nil {
if err = c . Authentication . ApplyClientCert ( o . ClientCert . ClientCA , c . SecureServing ) ; err != nil {
return fmt . Errorf ( "unable to load client CA file: %v" , err )
}
}
if o . RequestHeader != nil {
if err = c . Authentication . ApplyClientCert ( o . RequestHeader . ClientCAFile , c . SecureServing ) ; err != nil {
return fmt . Errorf ( "unable to load client CA file: %v" , err )
}
}
2019-01-12 04:58:27 +00:00
c . Authentication . SupportsBasicAuth = o . PasswordFile != nil && len ( o . PasswordFile . BasicAuthFile ) > 0
c . Authentication . APIAudiences = o . APIAudiences
if o . ServiceAccounts != nil && o . ServiceAccounts . Issuer != "" && len ( o . APIAudiences ) == 0 {
c . Authentication . APIAudiences = authenticator . Audiences { o . ServiceAccounts . Issuer }
}
return nil
}
// ApplyAuthorization will conditionally modify the authentication options based on the authorization options
func ( o * BuiltInAuthenticationOptions ) ApplyAuthorization ( authorization * BuiltInAuthorizationOptions ) {
if o == nil || authorization == nil {
return
}
}