specify custom ca file to verify the keystone server

This commit is contained in:
Di Xu 2016-10-25 11:26:44 +08:00
parent 3dec88d920
commit dd6c980949
6 changed files with 49 additions and 8 deletions

View File

@ -230,6 +230,7 @@ func Run(s *options.ServerRunOptions) error {
ServiceAccountLookup: s.ServiceAccountLookup,
ServiceAccountTokenGetter: serviceAccountGetter,
KeystoneURL: s.GenericServerRunOptions.KeystoneURL,
KeystoneCAFile: s.GenericServerRunOptions.KeystoneCAFile,
WebhookTokenAuthnConfigFile: s.WebhookTokenAuthnConfigFile,
WebhookTokenAuthnCacheTTL: s.WebhookTokenAuthnCacheTTL,
RequestHeaderConfig: s.GenericServerRunOptions.AuthenticationRequestHeaderConfig(),

View File

@ -189,6 +189,7 @@ exit-on-lock-contention
experimental-allowed-unsafe-sysctls
experimental-bootstrap-kubeconfig
experimental-keystone-url
experimental-keystone-ca-file
experimental-mounter-path
experimental-mounter-rootfs-path
experimental-nvidia-gpus

View File

@ -64,6 +64,7 @@ type AuthenticatorConfig struct {
ServiceAccountLookup bool
ServiceAccountTokenGetter serviceaccount.ServiceAccountTokenGetter
KeystoneURL string
KeystoneCAFile string
WebhookTokenAuthnConfigFile string
WebhookTokenAuthnCacheTTL time.Duration
@ -101,7 +102,7 @@ func New(config AuthenticatorConfig) (authenticator.Request, *spec.SecurityDefin
hasBasicAuth = true
}
if len(config.KeystoneURL) > 0 {
keystoneAuth, err := newAuthenticatorFromKeystoneURL(config.KeystoneURL)
keystoneAuth, err := newAuthenticatorFromKeystoneURL(config.KeystoneURL, config.KeystoneCAFile)
if err != nil {
return nil, nil, err
}
@ -283,8 +284,8 @@ func newAuthenticatorFromClientCAFile(clientCAFile string) (authenticator.Reques
}
// newAuthenticatorFromTokenFile returns an authenticator.Request or an error
func newAuthenticatorFromKeystoneURL(keystoneURL string) (authenticator.Request, error) {
keystoneAuthenticator, err := keystone.NewKeystoneAuthenticator(keystoneURL)
func newAuthenticatorFromKeystoneURL(keystoneURL string, keystoneCAFile string) (authenticator.Request, error) {
keystoneAuthenticator, err := keystone.NewKeystoneAuthenticator(keystoneURL, keystoneCAFile)
if err != nil {
return nil, err
}

View File

@ -91,6 +91,7 @@ type ServerRunOptions struct {
InsecureBindAddress net.IP
InsecurePort int
KeystoneURL string
KeystoneCAFile string
KubernetesServiceNodePort int
LongRunningRequestRE string
MasterCount int
@ -379,6 +380,10 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.KeystoneURL, "experimental-keystone-url", s.KeystoneURL,
"If passed, activates the keystone authentication plugin.")
fs.StringVar(&s.KeystoneCAFile, "experimental-keystone-ca-file", s.KeystoneCAFile, ""+
"If set, the Keystone server's certificate will be verified by one of the authorities "+
"in the experimental-keystone-ca-file, otherwise the host's root CA set will be used.")
// See #14282 for details on how to test/try this option out.
// TODO: remove this comment once this option is tested in CI.
fs.IntVar(&s.KubernetesServiceNodePort, "kubernetes-service-node-port", s.KubernetesServiceNodePort, ""+

View File

@ -19,6 +19,8 @@ go_library(
tags = ["automanaged"],
deps = [
"//pkg/auth/user:go_default_library",
"//pkg/util/cert:go_default_library",
"//pkg/util/net:go_default_library",
"//vendor:github.com/golang/glog",
"//vendor:github.com/rackspace/gophercloud",
"//vendor:github.com/rackspace/gophercloud/openstack",

View File

@ -17,19 +17,24 @@ limitations under the License.
package keystone
import (
"crypto/tls"
"errors"
"net/http"
"strings"
"github.com/golang/glog"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
"k8s.io/kubernetes/pkg/auth/user"
certutil "k8s.io/kubernetes/pkg/util/cert"
netutil "k8s.io/kubernetes/pkg/util/net"
)
// KeystoneAuthenticator contacts openstack keystone to validate user's credentials passed in the request.
// The keystone endpoint is passed during apiserver startup
type KeystoneAuthenticator struct {
authURL string
transport http.RoundTripper
}
// AuthenticatePassword checks the username, password via keystone call
@ -40,23 +45,49 @@ func (keystoneAuthenticator *KeystoneAuthenticator) AuthenticatePassword(usernam
Password: password,
}
_, err := openstack.AuthenticatedClient(opts)
_, err := keystoneAuthenticator.AuthenticatedClient(opts)
if err != nil {
glog.Info("Failed: Starting openstack authenticate client")
glog.Info("Failed: Starting openstack authenticate client:" + err.Error())
return nil, false, errors.New("Failed to authenticate")
}
return &user.DefaultInfo{Name: username}, true, nil
}
// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by options, acquires a
// token, and returns a Client instance that's ready to operate.
func (keystoneAuthenticator *KeystoneAuthenticator) AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
client, err := openstack.NewClient(options.IdentityEndpoint)
if err != nil {
return nil, err
}
if keystoneAuthenticator.transport != nil {
client.HTTPClient.Transport = keystoneAuthenticator.transport
}
err = openstack.Authenticate(client, options)
return client, err
}
// NewKeystoneAuthenticator returns a password authenticator that validates credentials using openstack keystone
func NewKeystoneAuthenticator(authURL string) (*KeystoneAuthenticator, error) {
func NewKeystoneAuthenticator(authURL string, caFile string) (*KeystoneAuthenticator, error) {
if !strings.HasPrefix(authURL, "https") {
return nil, errors.New("Auth URL should be secure and start with https")
}
if authURL == "" {
return nil, errors.New("Auth URL is empty")
}
return &KeystoneAuthenticator{authURL}, nil
if caFile != "" {
roots, err := certutil.NewPool(caFile)
if err != nil {
return nil, err
}
config := &tls.Config{}
config.RootCAs = roots
transport := netutil.SetOldTransportDefaults(&http.Transport{TLSClientConfig: config})
return &KeystoneAuthenticator{authURL, transport}, nil
}
return &KeystoneAuthenticator{authURL: authURL}, nil
}