mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +00:00
Merge pull request #41682 from perotinus/unpwandtokens
Automatic merge from submit-queue (batch tested with PRs 41984, 41682, 41924, 41928) Add options to kubefed telling it to generate HTTP Basic and/or token credentials for the Federated API server fixes #41265. **Release notes**: ```release-note Adds two options to kubefed, `-apiserver-enable-basic-auth` and `-apiserver-enable-token-auth`, which generate an HTTP Basic username/password and a token respectively for the Federated API server. ```
This commit is contained in:
commit
4672314029
@ -85,7 +85,9 @@ function init() {
|
|||||||
--dns-zone-name="${DNS_ZONE_NAME}" \
|
--dns-zone-name="${DNS_ZONE_NAME}" \
|
||||||
--dns-provider="${DNS_PROVIDER}" \
|
--dns-provider="${DNS_PROVIDER}" \
|
||||||
--image="${kube_registry}/hyperkube-amd64:${kube_version}" \
|
--image="${kube_registry}/hyperkube-amd64:${kube_version}" \
|
||||||
--apiserver-arg-overrides="--storage-backend=etcd2"
|
--apiserver-arg-overrides="--storage-backend=etcd2" \
|
||||||
|
--apiserver-enable-basic-auth=true \
|
||||||
|
--apiserver-enable-token-auth=true
|
||||||
}
|
}
|
||||||
|
|
||||||
# join_clusters joins the clusters in the local kubeconfig to federation. The clusters
|
# join_clusters joins the clusters in the local kubeconfig to federation. The clusters
|
||||||
|
@ -27,6 +27,7 @@ go_library(
|
|||||||
"//vendor:github.com/spf13/pflag",
|
"//vendor:github.com/spf13/pflag",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
"//vendor:k8s.io/apimachinery/pkg/api/resource",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/util/uuid",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd",
|
"//vendor:k8s.io/client-go/tools/clientcmd",
|
||||||
"//vendor:k8s.io/client-go/tools/clientcmd/api",
|
"//vendor:k8s.io/client-go/tools/clientcmd/api",
|
||||||
|
@ -43,6 +43,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
@ -148,6 +149,8 @@ type initFederationOptions struct {
|
|||||||
apiServerServiceTypeString string
|
apiServerServiceTypeString string
|
||||||
apiServerServiceType v1.ServiceType
|
apiServerServiceType v1.ServiceType
|
||||||
apiServerAdvertiseAddress string
|
apiServerAdvertiseAddress string
|
||||||
|
apiServerEnableHTTPBasicAuth bool
|
||||||
|
apiServerEnableTokenAuth bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *initFederationOptions) Bind(flags *pflag.FlagSet) {
|
func (o *initFederationOptions) Bind(flags *pflag.FlagSet) {
|
||||||
@ -164,6 +167,8 @@ func (o *initFederationOptions) Bind(flags *pflag.FlagSet) {
|
|||||||
flags.StringVar(&o.controllerManagerOverridesString, "controllermanager-arg-overrides", "", "comma separated list of federation-controller-manager arguments to override: Example \"--arg1=value1,--arg2=value2...\"")
|
flags.StringVar(&o.controllerManagerOverridesString, "controllermanager-arg-overrides", "", "comma separated list of federation-controller-manager arguments to override: Example \"--arg1=value1,--arg2=value2...\"")
|
||||||
flags.StringVar(&o.apiServerServiceTypeString, apiserverServiceTypeFlag, string(v1.ServiceTypeLoadBalancer), "The type of service to create for federation API server. Options: 'LoadBalancer' (default), 'NodePort'.")
|
flags.StringVar(&o.apiServerServiceTypeString, apiserverServiceTypeFlag, string(v1.ServiceTypeLoadBalancer), "The type of service to create for federation API server. Options: 'LoadBalancer' (default), 'NodePort'.")
|
||||||
flags.StringVar(&o.apiServerAdvertiseAddress, apiserverAdvertiseAddressFlag, "", "Preferred address to advertise api server nodeport service. Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.")
|
flags.StringVar(&o.apiServerAdvertiseAddress, apiserverAdvertiseAddressFlag, "", "Preferred address to advertise api server nodeport service. Valid only if '"+apiserverServiceTypeFlag+"=NodePort'.")
|
||||||
|
flags.BoolVar(&o.apiServerEnableHTTPBasicAuth, "apiserver-enable-basic-auth", false, "Enables HTTP Basic authentication for the federation-apiserver. Defaults to false.")
|
||||||
|
flags.BoolVar(&o.apiServerEnableTokenAuth, "apiserver-enable-token-auth", false, "Enables token authentication for the federation-apiserver. Defaults to false.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCmdInit defines the `init` command that bootstraps a federation
|
// NewCmdInit defines the `init` command that bootstraps a federation
|
||||||
@ -196,6 +201,13 @@ type entityKeyPairs struct {
|
|||||||
admin *triple.KeyPair
|
admin *triple.KeyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type credentials struct {
|
||||||
|
username string
|
||||||
|
password string
|
||||||
|
token string
|
||||||
|
certEntKeyPairs *entityKeyPairs
|
||||||
|
}
|
||||||
|
|
||||||
// Complete ensures that options are valid and marshals them if necessary.
|
// Complete ensures that options are valid and marshals them if necessary.
|
||||||
func (i *initFederation) Complete(cmd *cobra.Command, args []string) error {
|
func (i *initFederation) Complete(cmd *cobra.Command, args []string) error {
|
||||||
if len(i.options.dnsProvider) == 0 {
|
if len(i.options.dnsProvider) == 0 {
|
||||||
@ -274,19 +286,20 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Generate TLS certificates and credentials
|
// 3a. Generate TLS certificates and credentials, and other credentials if needed
|
||||||
entKeyPairs, err := genCerts(i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, HostClusterLocalDNSZoneName, ips, hostnames)
|
credentials, err := generateCredentials(i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, HostClusterLocalDNSZoneName, serverCredName, ips, hostnames, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.dryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = createAPIServerCredentialsSecret(hostClientset, i.commonOptions.FederationSystemNamespace, serverCredName, entKeyPairs, i.options.dryRun)
|
// 3b. Create the secret containing the credentials.
|
||||||
|
_, err = createAPIServerCredentialsSecret(hostClientset, i.commonOptions.FederationSystemNamespace, serverCredName, credentials, i.options.dryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Create a kubeconfig secret
|
// 4. Create a kubeconfig secret
|
||||||
_, err = createControllerManagerKubeconfigSecret(hostClientset, i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, cmKubeconfigName, entKeyPairs, i.options.dryRun)
|
_, err = createControllerManagerKubeconfigSecret(hostClientset, i.commonOptions.FederationSystemNamespace, i.commonOptions.Name, svc.Name, cmKubeconfigName, credentials.certEntKeyPairs, i.options.dryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -311,7 +324,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 6. Create federation API server
|
// 6. Create federation API server
|
||||||
_, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.options.image, serverCredName, advertiseAddress, i.options.apiServerOverrides, pvc, i.options.dryRun)
|
_, err = createAPIServer(hostClientset, i.commonOptions.FederationSystemNamespace, serverName, i.options.image, advertiseAddress, serverCredName, i.options.apiServerEnableHTTPBasicAuth, i.options.apiServerEnableTokenAuth, i.options.apiServerOverrides, pvc, i.options.dryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -358,7 +371,7 @@ func (i *initFederation) Run(cmdOut io.Writer, config util.AdminConfig) error {
|
|||||||
|
|
||||||
// 8. Write the federation API server endpoint info, credentials
|
// 8. Write the federation API server endpoint info, credentials
|
||||||
// and context to kubeconfig
|
// and context to kubeconfig
|
||||||
err = updateKubeconfig(config, i.commonOptions.Name, endpoint, i.commonOptions.Kubeconfig, entKeyPairs, i.options.dryRun)
|
err = updateKubeconfig(config, i.commonOptions.Name, endpoint, i.commonOptions.Kubeconfig, credentials, i.options.dryRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -498,6 +511,25 @@ func waitForLoadBalancerAddress(clientset client.Interface, svc *api.Service, dr
|
|||||||
return ips, hostnames, nil
|
return ips, hostnames, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateCredentials(svcNamespace, name, svcName, localDNSZoneName, serverCredName string, ips, hostnames []string, enableHTTPBasicAuth, enableTokenAuth, dryRun bool) (*credentials, error) {
|
||||||
|
credentials := credentials{
|
||||||
|
username: AdminCN,
|
||||||
|
}
|
||||||
|
if enableHTTPBasicAuth {
|
||||||
|
credentials.password = string(uuid.NewUUID())
|
||||||
|
}
|
||||||
|
if enableTokenAuth {
|
||||||
|
credentials.token = string(uuid.NewUUID())
|
||||||
|
}
|
||||||
|
|
||||||
|
entKeyPairs, err := genCerts(svcNamespace, name, svcName, localDNSZoneName, ips, hostnames)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
credentials.certEntKeyPairs = entKeyPairs
|
||||||
|
return &credentials, nil
|
||||||
|
}
|
||||||
|
|
||||||
func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnames []string) (*entityKeyPairs, error) {
|
func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnames []string) (*entityKeyPairs, error) {
|
||||||
ca, err := triple.NewCA(name)
|
ca, err := triple.NewCA(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -523,18 +555,26 @@ func genCerts(svcNamespace, name, svcName, localDNSZoneName string, ips, hostnam
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAPIServerCredentialsSecret(clientset client.Interface, namespace, credentialsName string, entKeyPairs *entityKeyPairs, dryRun bool) (*api.Secret, error) {
|
func createAPIServerCredentialsSecret(clientset client.Interface, namespace, credentialsName string, credentials *credentials, dryRun bool) (*api.Secret, error) {
|
||||||
// Build the secret object with API server credentials.
|
// Build the secret object with API server credentials.
|
||||||
|
data := map[string][]byte{
|
||||||
|
"ca.crt": certutil.EncodeCertPEM(credentials.certEntKeyPairs.ca.Cert),
|
||||||
|
"server.crt": certutil.EncodeCertPEM(credentials.certEntKeyPairs.server.Cert),
|
||||||
|
"server.key": certutil.EncodePrivateKeyPEM(credentials.certEntKeyPairs.server.Key),
|
||||||
|
}
|
||||||
|
if credentials.password != "" {
|
||||||
|
data["basicauth.csv"] = authFileContents(credentials.username, credentials.password)
|
||||||
|
}
|
||||||
|
if credentials.token != "" {
|
||||||
|
data["token.csv"] = authFileContents(credentials.username, credentials.token)
|
||||||
|
}
|
||||||
|
|
||||||
secret := &api.Secret{
|
secret := &api.Secret{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: credentialsName,
|
Name: credentialsName,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
Data: data,
|
||||||
"ca.crt": certutil.EncodeCertPEM(entKeyPairs.ca.Cert),
|
|
||||||
"server.crt": certutil.EncodeCertPEM(entKeyPairs.server.Cert),
|
|
||||||
"server.key": certutil.EncodePrivateKeyPEM(entKeyPairs.server.Key),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if dryRun {
|
if dryRun {
|
||||||
@ -591,7 +631,7 @@ func createPVC(clientset client.Interface, namespace, svcName, etcdPVCapacity st
|
|||||||
return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc)
|
return clientset.Core().PersistentVolumeClaims(namespace).Create(pvc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAPIServer(clientset client.Interface, namespace, name, image, credentialsName, advertiseAddress string, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) {
|
func createAPIServer(clientset client.Interface, namespace, name, image, advertiseAddress, credentialsName string, hasHTTPBasicAuthFile, hasTokenAuthFile bool, argOverrides map[string]string, pvc *api.PersistentVolumeClaim, dryRun bool) (*extensions.Deployment, error) {
|
||||||
command := []string{
|
command := []string{
|
||||||
"/hyperkube",
|
"/hyperkube",
|
||||||
"federation-apiserver",
|
"federation-apiserver",
|
||||||
@ -609,6 +649,12 @@ func createAPIServer(clientset client.Interface, namespace, name, image, credent
|
|||||||
if advertiseAddress != "" {
|
if advertiseAddress != "" {
|
||||||
argsMap["--advertise-address"] = advertiseAddress
|
argsMap["--advertise-address"] = advertiseAddress
|
||||||
}
|
}
|
||||||
|
if hasHTTPBasicAuthFile {
|
||||||
|
argsMap["--basic-auth-file"] = "/etc/federation/apiserver/basicauth.csv"
|
||||||
|
}
|
||||||
|
if hasTokenAuthFile {
|
||||||
|
argsMap["--token-auth-file"] = "/etc/federation/apiserver/token.csv"
|
||||||
|
}
|
||||||
|
|
||||||
args := argMapsToArgStrings(argsMap, argOverrides)
|
args := argMapsToArgStrings(argsMap, argOverrides)
|
||||||
command = append(command, args...)
|
command = append(command, args...)
|
||||||
@ -936,7 +982,7 @@ func printSuccess(cmdOut io.Writer, ips, hostnames []string, svc *api.Service) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateKubeconfig(config util.AdminConfig, name, endpoint, kubeConfigPath string, entKeyPairs *entityKeyPairs, dryRun bool) error {
|
func updateKubeconfig(config util.AdminConfig, name, endpoint, kubeConfigPath string, credentials *credentials, dryRun bool) error {
|
||||||
po := config.PathOptions()
|
po := config.PathOptions()
|
||||||
po.LoadingRules.ExplicitPath = kubeConfigPath
|
po.LoadingRules.ExplicitPath = kubeConfigPath
|
||||||
kubeconfig, err := po.GetStartingConfig()
|
kubeconfig, err := po.GetStartingConfig()
|
||||||
@ -951,13 +997,20 @@ func updateKubeconfig(config util.AdminConfig, name, endpoint, kubeConfigPath st
|
|||||||
endpoint = fmt.Sprintf("https://%s", endpoint)
|
endpoint = fmt.Sprintf("https://%s", endpoint)
|
||||||
}
|
}
|
||||||
cluster.Server = endpoint
|
cluster.Server = endpoint
|
||||||
cluster.CertificateAuthorityData = certutil.EncodeCertPEM(entKeyPairs.ca.Cert)
|
cluster.CertificateAuthorityData = certutil.EncodeCertPEM(credentials.certEntKeyPairs.ca.Cert)
|
||||||
|
|
||||||
// Populate credentials.
|
// Populate credentials.
|
||||||
authInfo := clientcmdapi.NewAuthInfo()
|
authInfo := clientcmdapi.NewAuthInfo()
|
||||||
authInfo.ClientCertificateData = certutil.EncodeCertPEM(entKeyPairs.admin.Cert)
|
authInfo.ClientCertificateData = certutil.EncodeCertPEM(credentials.certEntKeyPairs.admin.Cert)
|
||||||
authInfo.ClientKeyData = certutil.EncodePrivateKeyPEM(entKeyPairs.admin.Key)
|
authInfo.ClientKeyData = certutil.EncodePrivateKeyPEM(credentials.certEntKeyPairs.admin.Key)
|
||||||
authInfo.Username = AdminCN
|
authInfo.Token = credentials.token
|
||||||
|
|
||||||
|
var httpBasicAuthInfo *clientcmdapi.AuthInfo
|
||||||
|
if credentials.password != "" {
|
||||||
|
httpBasicAuthInfo = clientcmdapi.NewAuthInfo()
|
||||||
|
httpBasicAuthInfo.Password = credentials.password
|
||||||
|
httpBasicAuthInfo.Username = credentials.username
|
||||||
|
}
|
||||||
|
|
||||||
// Populate context.
|
// Populate context.
|
||||||
context := clientcmdapi.NewContext()
|
context := clientcmdapi.NewContext()
|
||||||
@ -968,6 +1021,9 @@ func updateKubeconfig(config util.AdminConfig, name, endpoint, kubeConfigPath st
|
|||||||
// credentials and context.
|
// credentials and context.
|
||||||
kubeconfig.Clusters[name] = cluster
|
kubeconfig.Clusters[name] = cluster
|
||||||
kubeconfig.AuthInfos[name] = authInfo
|
kubeconfig.AuthInfos[name] = authInfo
|
||||||
|
if httpBasicAuthInfo != nil {
|
||||||
|
kubeconfig.AuthInfos[fmt.Sprintf("%s-basic-auth", name)] = httpBasicAuthInfo
|
||||||
|
}
|
||||||
kubeconfig.Contexts[name] = context
|
kubeconfig.Contexts[name] = context
|
||||||
|
|
||||||
if !dryRun {
|
if !dryRun {
|
||||||
@ -1034,3 +1090,9 @@ func addDNSProviderConfig(dep *extensions.Deployment, secretName string) *extens
|
|||||||
|
|
||||||
return dep
|
return dep
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// authFileContents returns a CSV string containing the contents of an
|
||||||
|
// authentication file in the format required by the federation-apiserver.
|
||||||
|
func authFileContents(username, authSecret string) []byte {
|
||||||
|
return []byte(fmt.Sprintf("%s,%s,%s\n", authSecret, username, uuid.NewUUID()))
|
||||||
|
}
|
||||||
|
@ -79,21 +79,23 @@ func TestInitFederation(t *testing.T) {
|
|||||||
defer kubefedtesting.RemoveFakeKubeconfigFiles(fakeKubeFiles)
|
defer kubefedtesting.RemoveFakeKubeconfigFiles(fakeKubeFiles)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
federation string
|
federation string
|
||||||
kubeconfigGlobal string
|
kubeconfigGlobal string
|
||||||
kubeconfigExplicit string
|
kubeconfigExplicit string
|
||||||
dnsZoneName string
|
dnsZoneName string
|
||||||
lbIP string
|
lbIP string
|
||||||
apiserverServiceType v1.ServiceType
|
apiserverServiceType v1.ServiceType
|
||||||
advertiseAddress string
|
advertiseAddress string
|
||||||
image string
|
image string
|
||||||
etcdPVCapacity string
|
etcdPVCapacity string
|
||||||
etcdPersistence string
|
etcdPersistence string
|
||||||
expectedErr string
|
expectedErr string
|
||||||
dnsProviderConfig string
|
dnsProviderConfig string
|
||||||
dryRun string
|
dryRun string
|
||||||
apiserverArgOverrides string
|
apiserverArgOverrides string
|
||||||
cmArgOverrides string
|
cmArgOverrides string
|
||||||
|
apiserverEnableHTTPBasicAuth bool
|
||||||
|
apiserverEnableTokenAuth bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
federation: "union",
|
federation: "union",
|
||||||
@ -175,6 +177,21 @@ func TestInitFederation(t *testing.T) {
|
|||||||
expectedErr: "",
|
expectedErr: "",
|
||||||
dryRun: "",
|
dryRun: "",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
federation: "union",
|
||||||
|
kubeconfigGlobal: fakeKubeFiles[0],
|
||||||
|
kubeconfigExplicit: "",
|
||||||
|
dnsZoneName: "example.test.",
|
||||||
|
apiserverServiceType: v1.ServiceTypeNodePort,
|
||||||
|
advertiseAddress: nodeIP,
|
||||||
|
image: "example.test/foo:bar",
|
||||||
|
etcdPVCapacity: "5Gi",
|
||||||
|
etcdPersistence: "true",
|
||||||
|
expectedErr: "",
|
||||||
|
dryRun: "",
|
||||||
|
apiserverEnableHTTPBasicAuth: true,
|
||||||
|
apiserverEnableTokenAuth: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: implement a negative case for dry run
|
//TODO: implement a negative case for dry run
|
||||||
@ -191,7 +208,7 @@ func TestInitFederation(t *testing.T) {
|
|||||||
tc.dnsProviderConfig = tmpfile.Name()
|
tc.dnsProviderConfig = tmpfile.Name()
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
}
|
}
|
||||||
hostFactory, err := fakeInitHostFactory(tc.apiserverServiceType, tc.federation, util.DefaultFederationSystemNamespace, tc.advertiseAddress, tc.lbIP, tc.dnsZoneName, tc.image, dnsProvider, tc.dnsProviderConfig, tc.etcdPersistence, tc.etcdPVCapacity, tc.apiserverArgOverrides, tc.cmArgOverrides)
|
hostFactory, err := fakeInitHostFactory(tc.apiserverServiceType, tc.federation, util.DefaultFederationSystemNamespace, tc.advertiseAddress, tc.lbIP, tc.dnsZoneName, tc.image, dnsProvider, tc.dnsProviderConfig, tc.etcdPersistence, tc.etcdPVCapacity, tc.apiserverArgOverrides, tc.cmArgOverrides, tc.apiserverEnableHTTPBasicAuth, tc.apiserverEnableTokenAuth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("[%d] unexpected error: %v", i, err)
|
t.Fatalf("[%d] unexpected error: %v", i, err)
|
||||||
}
|
}
|
||||||
@ -227,6 +244,12 @@ func TestInitFederation(t *testing.T) {
|
|||||||
if tc.dryRun == "valid-run" {
|
if tc.dryRun == "valid-run" {
|
||||||
cmd.Flags().Set("dry-run", "true")
|
cmd.Flags().Set("dry-run", "true")
|
||||||
}
|
}
|
||||||
|
if tc.apiserverEnableHTTPBasicAuth {
|
||||||
|
cmd.Flags().Set("apiserver-enable-basic-auth", "true")
|
||||||
|
}
|
||||||
|
if tc.apiserverEnableTokenAuth {
|
||||||
|
cmd.Flags().Set("apiserver-enable-token-auth", "true")
|
||||||
|
}
|
||||||
|
|
||||||
cmd.Run(cmd, []string{tc.federation})
|
cmd.Run(cmd, []string{tc.federation})
|
||||||
|
|
||||||
@ -253,7 +276,7 @@ func TestInitFederation(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
testKubeconfigUpdate(t, tc.apiserverServiceType, tc.federation, tc.advertiseAddress, tc.lbIP, tc.kubeconfigGlobal, tc.kubeconfigExplicit)
|
testKubeconfigUpdate(t, tc.apiserverServiceType, tc.federation, tc.advertiseAddress, tc.lbIP, tc.kubeconfigGlobal, tc.kubeconfigExplicit, tc.apiserverEnableHTTPBasicAuth, tc.apiserverEnableTokenAuth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +577,7 @@ func TestCertsHTTPS(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, namespaceName, advertiseAddress, lbIp, dnsZoneName, image, dnsProvider, dnsProviderConfig, etcdPersistence, etcdPVCapacity, apiserverOverrideArg, cmOverrideArg string) (cmdutil.Factory, error) {
|
func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, namespaceName, advertiseAddress, lbIp, dnsZoneName, image, dnsProvider, dnsProviderConfig, etcdPersistence, etcdPVCapacity, apiserverOverrideArg, cmOverrideArg string, apiserverEnableHTTPBasicAuth, apiserverEnableTokenAuth bool) (cmdutil.Factory, error) {
|
||||||
svcName := federationName + "-apiserver"
|
svcName := federationName + "-apiserver"
|
||||||
svcUrlPrefix := "/api/v1/namespaces/federation-system/services"
|
svcUrlPrefix := "/api/v1/namespaces/federation-system/services"
|
||||||
credSecretName := svcName + "-credentials"
|
credSecretName := svcName + "-credentials"
|
||||||
@ -782,6 +805,12 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
} else {
|
} else {
|
||||||
apiserverArgs = append(apiserverArgs, "--client-ca-file=/etc/federation/apiserver/ca.crt")
|
apiserverArgs = append(apiserverArgs, "--client-ca-file=/etc/federation/apiserver/ca.crt")
|
||||||
}
|
}
|
||||||
|
if apiserverEnableHTTPBasicAuth {
|
||||||
|
apiserverArgs = append(apiserverArgs, "--basic-auth-file=/etc/federation/apiserver/basicauth.csv")
|
||||||
|
}
|
||||||
|
if apiserverEnableTokenAuth {
|
||||||
|
apiserverArgs = append(apiserverArgs, "--token-auth-file=/etc/federation/apiserver/token.csv")
|
||||||
|
}
|
||||||
sort.Strings(apiserverArgs)
|
sort.Strings(apiserverArgs)
|
||||||
apiserverCommand = append(apiserverCommand, apiserverArgs...)
|
apiserverCommand = append(apiserverCommand, apiserverArgs...)
|
||||||
|
|
||||||
@ -1018,7 +1047,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !apiequality.Semantic.DeepEqual(got, namespace) {
|
if !apiequality.Semantic.DeepEqual(got, namespace) {
|
||||||
return nil, fmt.Errorf("Unexpected namespace object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, namespace))
|
return nil, fmt.Errorf("unexpected namespace object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, namespace))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &namespace)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &namespace)}, nil
|
||||||
case p == svcUrlPrefix && m == http.MethodPost:
|
case p == svcUrlPrefix && m == http.MethodPost:
|
||||||
@ -1032,7 +1061,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !apiequality.Semantic.DeepEqual(got, svc) {
|
if !apiequality.Semantic.DeepEqual(got, svc) {
|
||||||
return nil, fmt.Errorf("Unexpected service object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, svc))
|
return nil, fmt.Errorf("unexpected service object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, svc))
|
||||||
}
|
}
|
||||||
if apiserverServiceType == v1.ServiceTypeNodePort {
|
if apiserverServiceType == v1.ServiceTypeNodePort {
|
||||||
svc.Spec.Type = v1.ServiceTypeNodePort
|
svc.Spec.Type = v1.ServiceTypeNodePort
|
||||||
@ -1055,21 +1084,36 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Obtained secret contains generated data which cannot
|
|
||||||
// be compared, so we just nullify the generated part
|
|
||||||
// and compare the rest of the secret. The generated
|
|
||||||
// parts are tested in other tests.
|
|
||||||
got.Data = nil
|
|
||||||
switch got.Name {
|
switch got.Name {
|
||||||
case credSecretName:
|
case credSecretName:
|
||||||
want = credSecret
|
want = credSecret
|
||||||
|
if apiserverEnableHTTPBasicAuth {
|
||||||
|
if got.Data["basicauth.csv"] == nil {
|
||||||
|
return nil, fmt.Errorf("expected secret data key 'basicauth.csv', but got nil")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if got.Data["basicauth.csv"] != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected secret data key 'basicauth.csv'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if apiserverEnableTokenAuth {
|
||||||
|
if got.Data["token.csv"] == nil {
|
||||||
|
return nil, fmt.Errorf("expected secret data key 'token.csv', but got nil")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if got.Data["token.csv"] != nil {
|
||||||
|
return nil, fmt.Errorf("unexpected secret data key 'token.csv'")
|
||||||
|
}
|
||||||
|
}
|
||||||
case cmKubeconfigSecretName:
|
case cmKubeconfigSecretName:
|
||||||
want = cmKubeconfigSecret
|
want = cmKubeconfigSecret
|
||||||
case dnsProviderSecretName:
|
case dnsProviderSecretName:
|
||||||
want = cmDNSProviderSecret
|
want = cmDNSProviderSecret
|
||||||
}
|
}
|
||||||
|
got.Data = nil
|
||||||
if !apiequality.Semantic.DeepEqual(got, want) {
|
if !apiequality.Semantic.DeepEqual(got, want) {
|
||||||
return nil, fmt.Errorf("Unexpected secret object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, want))
|
return nil, fmt.Errorf("unexpected secret object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, want))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &want)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &want)}, nil
|
||||||
case p == "/api/v1/namespaces/federation-system/persistentvolumeclaims" && m == http.MethodPost:
|
case p == "/api/v1/namespaces/federation-system/persistentvolumeclaims" && m == http.MethodPost:
|
||||||
@ -1083,7 +1127,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !apiequality.Semantic.DeepEqual(got, pvc) {
|
if !apiequality.Semantic.DeepEqual(got, pvc) {
|
||||||
return nil, fmt.Errorf("Unexpected PVC object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, pvc))
|
return nil, fmt.Errorf("unexpected PVC object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, pvc))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &pvc)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &pvc)}, nil
|
||||||
case p == "/apis/extensions/v1beta1/namespaces/federation-system/deployments" && m == http.MethodPost:
|
case p == "/apis/extensions/v1beta1/namespaces/federation-system/deployments" && m == http.MethodPost:
|
||||||
@ -1103,7 +1147,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
want = *cm
|
want = *cm
|
||||||
}
|
}
|
||||||
if !apiequality.Semantic.DeepEqual(got, want) {
|
if !apiequality.Semantic.DeepEqual(got, want) {
|
||||||
return nil, fmt.Errorf("Unexpected deployment object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, want))
|
return nil, fmt.Errorf("unexpected deployment object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, want))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(extCodec, &want)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(extCodec, &want)}, nil
|
||||||
case p == "/api/v1/namespaces/federation-system/pods" && m == http.MethodGet:
|
case p == "/api/v1/namespaces/federation-system/pods" && m == http.MethodGet:
|
||||||
@ -1119,7 +1163,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !api.Semantic.DeepEqual(got, sa) {
|
if !api.Semantic.DeepEqual(got, sa) {
|
||||||
return nil, fmt.Errorf("Unexpected service account object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, sa))
|
return nil, fmt.Errorf("unexpected service account object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, sa))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &sa)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(codec, &sa)}, nil
|
||||||
case p == "/apis/rbac.authorization.k8s.io/v1beta1/namespaces/federation-system/roles" && m == http.MethodPost:
|
case p == "/apis/rbac.authorization.k8s.io/v1beta1/namespaces/federation-system/roles" && m == http.MethodPost:
|
||||||
@ -1133,7 +1177,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !api.Semantic.DeepEqual(got, role) {
|
if !api.Semantic.DeepEqual(got, role) {
|
||||||
return nil, fmt.Errorf("Unexpected role object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, role))
|
return nil, fmt.Errorf("unexpected role object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, role))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &role)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &role)}, nil
|
||||||
case p == "/apis/rbac.authorization.k8s.io/v1beta1/namespaces/federation-system/rolebindings" && m == http.MethodPost:
|
case p == "/apis/rbac.authorization.k8s.io/v1beta1/namespaces/federation-system/rolebindings" && m == http.MethodPost:
|
||||||
@ -1147,7 +1191,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !api.Semantic.DeepEqual(got, rolebinding) {
|
if !api.Semantic.DeepEqual(got, rolebinding) {
|
||||||
return nil, fmt.Errorf("Unexpected rolebinding object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, rolebinding))
|
return nil, fmt.Errorf("unexpected rolebinding object\n\tDiff: %s", diff.ObjectGoPrintDiff(got, rolebinding))
|
||||||
}
|
}
|
||||||
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &rolebinding)}, nil
|
return &http.Response{StatusCode: http.StatusCreated, Header: kubefedtesting.DefaultHeader(), Body: kubefedtesting.ObjBody(rbacCodec, &rolebinding)}, nil
|
||||||
case p == "/api/v1/nodes" && m == http.MethodGet:
|
case p == "/api/v1/nodes" && m == http.MethodGet:
|
||||||
@ -1160,7 +1204,7 @@ func fakeInitHostFactory(apiserverServiceType v1.ServiceType, federationName, na
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func testKubeconfigUpdate(t *testing.T, apiserverServiceType v1.ServiceType, federationName, advertiseAddress, lbIP, kubeconfigGlobal, kubeconfigExplicit string) {
|
func testKubeconfigUpdate(t *testing.T, apiserverServiceType v1.ServiceType, federationName, advertiseAddress, lbIP, kubeconfigGlobal, kubeconfigExplicit string, apiserverEnableHTTPBasicAuth, apiserverEnableTokenAuth bool) {
|
||||||
filename := kubeconfigGlobal
|
filename := kubeconfigGlobal
|
||||||
if kubeconfigExplicit != "" {
|
if kubeconfigExplicit != "" {
|
||||||
filename = kubeconfigExplicit
|
filename = kubeconfigExplicit
|
||||||
@ -1197,8 +1241,30 @@ func testKubeconfigUpdate(t *testing.T, apiserverServiceType v1.ServiceType, fed
|
|||||||
t.Errorf("Expected client key to be non-empty")
|
t.Errorf("Expected client key to be non-empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if authInfo.Username != AdminCN {
|
if !apiserverEnableTokenAuth && len(authInfo.Token) != 0 {
|
||||||
t.Errorf("Want username: %q, got: %q", AdminCN, authInfo.Username)
|
t.Errorf("Expected token to be empty: got: %s", authInfo.Token)
|
||||||
|
}
|
||||||
|
if apiserverEnableTokenAuth && len(authInfo.Token) == 0 {
|
||||||
|
t.Errorf("Expected token to be non-empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
httpBasicAuthInfo, ok := config.AuthInfos[fmt.Sprintf("%s-basic-auth", federationName)]
|
||||||
|
if !apiserverEnableHTTPBasicAuth && ok {
|
||||||
|
t.Errorf("Expected basic auth AuthInfo entry not to exist: got %v", httpBasicAuthInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if apiserverEnableHTTPBasicAuth {
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Expected basic auth AuthInfo entry to exist")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if httpBasicAuthInfo.Username != "admin" {
|
||||||
|
t.Errorf("Unexpected username in basic auth AuthInfo entry: got %s, want admin", httpBasicAuthInfo.Username)
|
||||||
|
}
|
||||||
|
if len(httpBasicAuthInfo.Password) == 0 {
|
||||||
|
t.Errorf("Expected basic auth AuthInfo entry to contain password")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context, ok := config.Contexts[federationName]
|
context, ok := config.Contexts[federationName]
|
||||||
|
@ -31,6 +31,11 @@ api-servers
|
|||||||
api-server-service-type
|
api-server-service-type
|
||||||
api-token
|
api-token
|
||||||
api-version
|
api-version
|
||||||
|
apiserver-arg-overrides
|
||||||
|
apiserver-count
|
||||||
|
apiserver-count
|
||||||
|
apiserver-enable-basic-auth
|
||||||
|
apiserver-enable-token-auth
|
||||||
attach-detach-reconcile-sync-period
|
attach-detach-reconcile-sync-period
|
||||||
audit-log-maxage
|
audit-log-maxage
|
||||||
audit-log-maxbackup
|
audit-log-maxbackup
|
||||||
|
@ -21,7 +21,6 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
||||||
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
fedframework "k8s.io/kubernetes/test/e2e_federation/framework"
|
fedframework "k8s.io/kubernetes/test/e2e_federation/framework"
|
||||||
@ -30,6 +29,8 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: These tests should be integration tests rather than e2e tests, when the
|
||||||
|
// integration test harness is ready.
|
||||||
var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
||||||
f := fedframework.NewDefaultFederatedFramework("federation-apiserver-authn")
|
f := fedframework.NewDefaultFederatedFramework("federation-apiserver-authn")
|
||||||
|
|
||||||
@ -38,72 +39,163 @@ var _ = framework.KubeDescribe("[Feature:Federation]", func() {
|
|||||||
fedframework.SkipUnlessFederated(f.ClientSet)
|
fedframework.SkipUnlessFederated(f.ClientSet)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should accept cluster resources when the client has right authentication credentials", func() {
|
It("should accept cluster resources when the client has certificate authentication credentials", func() {
|
||||||
fedframework.SkipUnlessFederated(f.ClientSet)
|
fcs, err := federationClientSetWithCert()
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
nsName := f.FederationNamespace.Name
|
nsName := f.FederationNamespace.Name
|
||||||
svc := createServiceOrFail(f.FederationClientset, nsName, FederatedServiceName)
|
svc := createServiceOrFail(fcs, nsName, FederatedServiceName)
|
||||||
deleteServiceOrFail(f.FederationClientset, nsName, svc.Name, nil)
|
deleteServiceOrFail(f.FederationClientset, nsName, svc.Name, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should not accept cluster resources when the client has invalid authentication credentials", func() {
|
It("should accept cluster resources when the client has HTTP Basic authentication credentials", func() {
|
||||||
fedframework.SkipUnlessFederated(f.ClientSet)
|
fcs, err := federationClientSetWithBasicAuth(true /* valid */)
|
||||||
|
|
||||||
contexts := f.GetUnderlyingFederatedContexts()
|
|
||||||
|
|
||||||
// `contexts` is obtained by calling
|
|
||||||
// `f.GetUnderlyingFederatedContexts()`. This function in turn
|
|
||||||
// checks that the contexts it returns does not include the
|
|
||||||
// federation API server context. So `contexts` is guaranteed to
|
|
||||||
// contain only the underlying Kubernetes cluster contexts.
|
|
||||||
fcs, err := invalidAuthFederationClientSet(contexts[0].User)
|
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
nsName := f.FederationNamespace.Name
|
nsName := f.FederationNamespace.Name
|
||||||
svc, err := createService(fcs, nsName, FederatedServiceName)
|
svc, err := createService(fcs, nsName, FederatedServiceName)
|
||||||
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
if err == nil && svc != nil {
|
deleteServiceOrFail(fcs, nsName, svc.Name, nil)
|
||||||
deleteServiceOrFail(fcs, nsName, svc.Name, nil)
|
})
|
||||||
}
|
|
||||||
|
It("should accept cluster resources when the client has token authentication credentials", func() {
|
||||||
|
fcs, err := federationClientSetWithToken(true /* valid */)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
nsName := f.FederationNamespace.Name
|
||||||
|
svc, err := createService(fcs, nsName, FederatedServiceName)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
deleteServiceOrFail(fcs, nsName, svc.Name, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
It("should not accept cluster resources when the client has no authentication credentials", func() {
|
It("should not accept cluster resources when the client has no authentication credentials", func() {
|
||||||
fedframework.SkipUnlessFederated(f.ClientSet)
|
fcs, err := unauthenticatedFederationClientSet()
|
||||||
|
|
||||||
fcs, err := invalidAuthFederationClientSet(nil)
|
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
nsName := f.FederationNamespace.Name
|
nsName := f.FederationNamespace.Name
|
||||||
svc, err := createService(fcs, nsName, FederatedServiceName)
|
_, err = createService(fcs, nsName, FederatedServiceName)
|
||||||
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
||||||
if err == nil && svc != nil {
|
|
||||||
deleteServiceOrFail(fcs, nsName, svc.Name, nil)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// TODO: Add a test for invalid certificate credentials. The certificate is validated for
|
||||||
|
// correct format, so it cannot contain random noise.
|
||||||
|
|
||||||
|
It("should not accept cluster resources when the client has invalid HTTP Basic authentication credentials", func() {
|
||||||
|
fcs, err := federationClientSetWithBasicAuth(false /* invalid */)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
nsName := f.FederationNamespace.Name
|
||||||
|
_, err = createService(fcs, nsName, FederatedServiceName)
|
||||||
|
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should not accept cluster resources when the client has invalid token authentication credentials", func() {
|
||||||
|
fcs, err := federationClientSetWithToken(false /* invalid */)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
|
||||||
|
nsName := f.FederationNamespace.Name
|
||||||
|
_, err = createService(fcs, nsName, FederatedServiceName)
|
||||||
|
Expect(errors.IsUnauthorized(err)).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
func invalidAuthFederationClientSet(user *framework.KubeUser) (*federation_clientset.Clientset, error) {
|
// unauthenticatedFederationClientSet returns a Federation Clientset configured with
|
||||||
overrides := &clientcmd.ConfigOverrides{}
|
// no authentication credentials.
|
||||||
if user != nil {
|
func unauthenticatedFederationClientSet() (*federation_clientset.Clientset, error) {
|
||||||
overrides = &clientcmd.ConfigOverrides{
|
config, err := fedframework.LoadFederatedConfig(&clientcmd.ConfigOverrides{})
|
||||||
AuthInfo: clientcmdapi.AuthInfo{
|
if err != nil {
|
||||||
Token: user.User.Token,
|
return nil, err
|
||||||
Username: user.User.Username,
|
}
|
||||||
Password: user.User.Password,
|
config.Insecure = true
|
||||||
},
|
config.CAData = []byte{}
|
||||||
}
|
config.CertData = []byte{}
|
||||||
|
config.KeyData = []byte{}
|
||||||
|
config.BearerToken = ""
|
||||||
|
|
||||||
|
c, err := federation_clientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating federation clientset: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := fedframework.LoadFederatedConfig(overrides)
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// federationClientSetWithCert returns a Federation Clientset configured with
|
||||||
|
// certificate authentication credentials.
|
||||||
|
func federationClientSetWithCert() (*federation_clientset.Clientset, error) {
|
||||||
|
config, err := fedframework.LoadFederatedConfig(&clientcmd.ConfigOverrides{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil {
|
config.BearerToken = ""
|
||||||
config.Password = ""
|
|
||||||
config.BearerToken = ""
|
c, err := federation_clientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating federation clientset: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// federationClientSetWithBasicAuth returns a Federation Clientset configured with
|
||||||
|
// HTTP Basic authentication credentials.
|
||||||
|
func federationClientSetWithBasicAuth(valid bool) (*federation_clientset.Clientset, error) {
|
||||||
|
config, err := fedframework.LoadFederatedConfig(&clientcmd.ConfigOverrides{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Insecure = true
|
||||||
|
config.CAData = []byte{}
|
||||||
|
config.CertData = []byte{}
|
||||||
|
config.KeyData = []byte{}
|
||||||
|
config.BearerToken = ""
|
||||||
|
|
||||||
|
if !valid {
|
||||||
config.Username = ""
|
config.Username = ""
|
||||||
|
config.Password = ""
|
||||||
|
} else {
|
||||||
|
// This is a hacky approach to getting the basic auth credentials, but since
|
||||||
|
// the token and the username/password cannot live in the same AuthInfo object,
|
||||||
|
// and because we do not want to store basic auth credentials with token and
|
||||||
|
// certificate credentials for security reasons, we must dig it out by hand.
|
||||||
|
c, err := framework.RestclientConfig(framework.TestContext.FederatedKubeContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if authInfo, ok := c.AuthInfos[fmt.Sprintf("%s-basic-auth", framework.TestContext.FederatedKubeContext)]; ok {
|
||||||
|
config.Username = authInfo.Username
|
||||||
|
config.Password = authInfo.Password
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := federation_clientset.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating federation clientset: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// federationClientSetWithToken returns a Federation Clientset configured with
|
||||||
|
// token authentication credentials.
|
||||||
|
func federationClientSetWithToken(valid bool) (*federation_clientset.Clientset, error) {
|
||||||
|
config, err := fedframework.LoadFederatedConfig(&clientcmd.ConfigOverrides{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
config.Insecure = true
|
||||||
|
config.CAData = []byte{}
|
||||||
|
config.CertData = []byte{}
|
||||||
|
config.KeyData = []byte{}
|
||||||
|
config.Username = ""
|
||||||
|
config.Password = ""
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
config.BearerToken = "invalid"
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := federation_clientset.NewForConfig(config)
|
c, err := federation_clientset.NewForConfig(config)
|
||||||
|
Loading…
Reference in New Issue
Block a user