mirror of https://github.com/k3s-io/k3s
Merge pull request #35488 from dixudx/keystone-ca-cert
Automatic merge from submit-queue specify custom ca file to verify the keystone server <!-- Thanks for sending a pull request! Here are some tips for you: 1. If this is your first time, read our contributor guidelines https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md and developer guide https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md 2. If you want *faster* PR reviews, read how: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md 3. Follow the instructions for writing a release note: https://github.com/kubernetes/kubernetes/blob/master/docs/devel/pull-requests.md#release-notes --> **What this PR does / why we need it**: Sometimes the keystone server's certificate is self-signed, mainly used for internal development, testing and etc. For this kind of ca, we need a way to verify the keystone server. Otherwise, below error will occur. > x509: certificate signed by unknown authority This patch provide a way to pass in a ca file to verify the keystone server when starting `kube-apiserver`. **Which issue this PR fixes** : fixes #22695, #24984 **Special notes for your reviewer**: **Release note**: <!-- Steps to write your release note: 1. Use the release-note-* labels to set the release note state (if you have access) 2. Enter your extended release note in the below block; leaving it blank means using the PR title as the release note. If no release note is required, just write `NONE`. --> ``` release-note ```pull/6/head
commit
860cae0933
|
@ -234,6 +234,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(),
|
||||
|
|
|
@ -190,6 +190,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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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, ""+
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
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")
|
||||
}
|
||||
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}, nil
|
||||
return &KeystoneAuthenticator{authURL: authURL}, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue