allow multiple of --service-account-issuer
This commit is contained in:
@@ -20,15 +20,25 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
apiserver "k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
)
|
||||
|
||||
const clusterIPRange = "10.0.0.1/24"
|
||||
const (
|
||||
clusterIPRange = "10.0.0.1/24"
|
||||
// This key is for testing purposes only and is not considered secure.
|
||||
ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49
|
||||
AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0
|
||||
/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
)
|
||||
|
||||
// APIServer is a server which manages apiserver.
|
||||
type APIServer struct {
|
||||
@@ -65,6 +75,20 @@ func (a *APIServer) Start() error {
|
||||
}
|
||||
o.Authentication.TokenFile.TokenFile = tokenFilePath
|
||||
o.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"}
|
||||
|
||||
saSigningKeyFile, err := ioutil.TempFile("/tmp", "insecure_test_key")
|
||||
if err != nil {
|
||||
return fmt.Errorf("create temp file failed: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(saSigningKeyFile.Name())
|
||||
if err = ioutil.WriteFile(saSigningKeyFile.Name(), []byte(ecdsaPrivateKey), 0666); err != nil {
|
||||
return fmt.Errorf("write file %s failed: %v", saSigningKeyFile.Name(), err)
|
||||
}
|
||||
o.ServiceAccountSigningKeyFile = saSigningKeyFile.Name()
|
||||
o.Authentication.APIAudiences = []string{"https://foo.bar.example.com"}
|
||||
o.Authentication.ServiceAccounts.Issuers = []string{"https://foo.bar.example.com"}
|
||||
o.Authentication.ServiceAccounts.KeyFiles = []string{saSigningKeyFile.Name()}
|
||||
|
||||
errCh := make(chan error)
|
||||
go func() {
|
||||
defer close(errCh)
|
||||
@@ -73,6 +97,11 @@ func (a *APIServer) Start() error {
|
||||
errCh <- fmt.Errorf("set apiserver default options error: %v", err)
|
||||
return
|
||||
}
|
||||
if errs := completedOptions.Validate(); len(errs) != 0 {
|
||||
errCh <- fmt.Errorf("failed to validate ServerRunOptions: %v", utilerrors.NewAggregate(errs))
|
||||
return
|
||||
}
|
||||
|
||||
err = apiserver.Run(completedOptions, a.stopCh)
|
||||
if err != nil {
|
||||
errCh <- fmt.Errorf("run apiserver error: %v", err)
|
||||
|
||||
@@ -39,6 +39,7 @@ import (
|
||||
admissionv1 "k8s.io/api/admissionregistration/v1"
|
||||
admissionv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
authenticationv1 "k8s.io/api/authentication/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
@@ -127,6 +128,8 @@ var (
|
||||
gvr("", "v1", "pods/proxy"): {"*": testSubresourceProxy},
|
||||
gvr("", "v1", "services/proxy"): {"*": testSubresourceProxy},
|
||||
|
||||
gvr("", "v1", "serviceaccounts/token"): {"create": testTokenCreate},
|
||||
|
||||
gvr("random.numbers.com", "v1", "integers"): {"create": testPruningRandomNumbers},
|
||||
gvr("custom.fancy.com", "v2", "pants"): {"create": testNoPruningCustomFancy},
|
||||
}
|
||||
@@ -882,6 +885,27 @@ func getParentGVR(gvr schema.GroupVersionResource) schema.GroupVersionResource {
|
||||
return parentGVR
|
||||
}
|
||||
|
||||
func testTokenCreate(c *testContext) {
|
||||
saGVR := gvr("", "v1", "serviceaccounts")
|
||||
sa, err := createOrGetResource(c.client, saGVR, c.resources[saGVR])
|
||||
if err != nil {
|
||||
c.t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
c.admissionHolder.expect(c.gvr, gvk(c.resource.Group, c.resource.Version, c.resource.Kind), gvkCreateOptions, v1beta1.Create, sa.GetName(), sa.GetNamespace(), true, false, true)
|
||||
if err = c.clientset.CoreV1().RESTClient().Post().Namespace(sa.GetNamespace()).Resource("serviceaccounts").Name(sa.GetName()).SubResource("token").Body(&authenticationv1.TokenRequest{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: sa.GetName()},
|
||||
Spec: authenticationv1.TokenRequestSpec{
|
||||
Audiences: []string{"api"},
|
||||
},
|
||||
}).Do(context.TODO()).Error(); err != nil {
|
||||
c.t.Error(err)
|
||||
return
|
||||
}
|
||||
c.admissionHolder.verify(c.t)
|
||||
}
|
||||
|
||||
func testSubresourceUpdate(c *testContext) {
|
||||
if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
||||
parentGVR := getParentGVR(c.gvr)
|
||||
|
||||
@@ -69,7 +69,7 @@ func TestDynamicClientBuilder(t *testing.T) {
|
||||
if opts.Authentication.ServiceAccounts == nil {
|
||||
opts.Authentication.ServiceAccounts = &kubeoptions.ServiceAccountAuthenticationOptions{}
|
||||
}
|
||||
opts.Authentication.ServiceAccounts.Issuer = iss
|
||||
opts.Authentication.ServiceAccounts.Issuers = []string{iss}
|
||||
opts.Authentication.ServiceAccounts.KeyFiles = []string{tmpfile.Name()}
|
||||
},
|
||||
ModifyServerConfig: func(config *controlplane.Config) {
|
||||
|
||||
@@ -54,6 +54,7 @@ import (
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
)
|
||||
|
||||
// This key is for testing purposes only and is not considered secure.
|
||||
const ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49
|
||||
AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0
|
||||
@@ -87,7 +88,7 @@ func TestServiceAccountTokenCreate(t *testing.T) {
|
||||
masterConfig.GenericConfig.Authentication.APIAudiences = aud
|
||||
masterConfig.GenericConfig.Authentication.Authenticator = bearertoken.New(
|
||||
serviceaccount.JWTTokenAuthenticator(
|
||||
iss,
|
||||
[]string{iss},
|
||||
[]interface{}{&pk},
|
||||
aud,
|
||||
serviceaccount.NewValidator(serviceaccountgetter.NewGetterFromClient(
|
||||
|
||||
@@ -37,6 +37,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||
cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
|
||||
@@ -53,6 +54,13 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/controlplane"
|
||||
)
|
||||
|
||||
// This key is for testing purposes only and is not considered secure.
|
||||
const ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49
|
||||
AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0
|
||||
/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
// StartRealMasterOrDie starts an API master that is appropriate for use in tests that require one of every resource
|
||||
func StartRealMasterOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOptions)) *Master {
|
||||
certDir, err := ioutil.TempDir("", t.Name())
|
||||
@@ -70,12 +78,25 @@ func StartRealMasterOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOp
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
saSigningKeyFile, err := ioutil.TempFile("/tmp", "insecure_test_key")
|
||||
if err != nil {
|
||||
t.Fatalf("create temp file failed: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(saSigningKeyFile.Name())
|
||||
if err = ioutil.WriteFile(saSigningKeyFile.Name(), []byte(ecdsaPrivateKey), 0666); err != nil {
|
||||
t.Fatalf("write file %s failed: %v", saSigningKeyFile.Name(), err)
|
||||
}
|
||||
|
||||
kubeAPIServerOptions := options.NewServerRunOptions()
|
||||
kubeAPIServerOptions.SecureServing.Listener = listener
|
||||
kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir
|
||||
kubeAPIServerOptions.ServiceAccountSigningKeyFile = saSigningKeyFile.Name()
|
||||
kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{framework.GetEtcdURL()}
|
||||
kubeAPIServerOptions.Etcd.DefaultStorageMediaType = runtime.ContentTypeJSON // force json we can easily interpret the result in etcd
|
||||
kubeAPIServerOptions.ServiceClusterIPRanges = defaultServiceClusterIPRange.String()
|
||||
kubeAPIServerOptions.Authentication.APIAudiences = []string{"https://foo.bar.example.com"}
|
||||
kubeAPIServerOptions.Authentication.ServiceAccounts.Issuers = []string{"https://foo.bar.example.com"}
|
||||
kubeAPIServerOptions.Authentication.ServiceAccounts.KeyFiles = []string{saSigningKeyFile.Name()}
|
||||
kubeAPIServerOptions.Authorization.Modes = []string{"RBAC"}
|
||||
kubeAPIServerOptions.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount"}
|
||||
kubeAPIServerOptions.APIEnablement.RuntimeConfig["api/all"] = "true"
|
||||
@@ -87,6 +108,10 @@ func StartRealMasterOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOp
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if errs := completedOptions.Validate(); len(errs) != 0 {
|
||||
t.Fatalf("failed to validate ServerRunOptions: %v", utilerrors.NewAggregate(errs))
|
||||
}
|
||||
|
||||
// get etcd client before starting API server
|
||||
rawClient, kvClient, err := integration.GetEtcdClients(completedOptions.Etcd.StorageConfig.Transport)
|
||||
if err != nil {
|
||||
|
||||
@@ -172,7 +172,7 @@ func startApiserverOrDie(controlPlaneConfig *controlplane.Config, incomingServer
|
||||
Groups: []string{user.SystemPrivilegedGroup},
|
||||
}
|
||||
|
||||
tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens)
|
||||
tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens, controlPlaneConfig.GenericConfig.Authentication.APIAudiences)
|
||||
if controlPlaneConfig.GenericConfig.Authentication.Authenticator == nil {
|
||||
controlPlaneConfig.GenericConfig.Authentication.Authenticator = authenticatorunion.New(tokenAuthenticator, authauthenticator.RequestFunc(alwaysEmpty))
|
||||
} else {
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||
@@ -41,6 +42,13 @@ import (
|
||||
"k8s.io/kubernetes/test/utils"
|
||||
)
|
||||
|
||||
// This key is for testing purposes only and is not considered secure.
|
||||
const ecdsaPrivateKey = `-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIEZmTmUhuanLjPA2CLquXivuwBDHTt5XYwgIr/kA1LtRoAoGCCqGSM49
|
||||
AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0
|
||||
/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg==
|
||||
-----END EC PRIVATE KEY-----`
|
||||
|
||||
// TestServerSetup holds configuration information for a kube-apiserver test server.
|
||||
type TestServerSetup struct {
|
||||
ModifyServerRunOptions func(*options.ServerRunOptions)
|
||||
@@ -86,10 +94,20 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
saSigningKeyFile, err := ioutil.TempFile("/tmp", "insecure_test_key")
|
||||
if err != nil {
|
||||
t.Fatalf("create temp file failed: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(saSigningKeyFile.Name())
|
||||
if err = ioutil.WriteFile(saSigningKeyFile.Name(), []byte(ecdsaPrivateKey), 0666); err != nil {
|
||||
t.Fatalf("write file %s failed: %v", saSigningKeyFile.Name(), err)
|
||||
}
|
||||
|
||||
kubeAPIServerOptions := options.NewServerRunOptions()
|
||||
kubeAPIServerOptions.SecureServing.Listener = listener
|
||||
kubeAPIServerOptions.SecureServing.BindAddress = net.ParseIP("127.0.0.1")
|
||||
kubeAPIServerOptions.SecureServing.ServerCert.CertDirectory = certDir
|
||||
kubeAPIServerOptions.ServiceAccountSigningKeyFile = saSigningKeyFile.Name()
|
||||
kubeAPIServerOptions.Etcd.StorageConfig.Prefix = path.Join("/", uuid.New().String(), "registry")
|
||||
kubeAPIServerOptions.Etcd.StorageConfig.Transport.ServerList = []string{GetEtcdURL()}
|
||||
kubeAPIServerOptions.ServiceClusterIPRanges = defaultServiceClusterIPRange.String()
|
||||
@@ -98,6 +116,9 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup
|
||||
kubeAPIServerOptions.Authentication.RequestHeader.ExtraHeaderPrefixes = []string{"X-Remote-Extra-"}
|
||||
kubeAPIServerOptions.Authentication.RequestHeader.AllowedNames = []string{"kube-aggregator"}
|
||||
kubeAPIServerOptions.Authentication.RequestHeader.ClientCAFile = proxyCACertFile.Name()
|
||||
kubeAPIServerOptions.Authentication.APIAudiences = []string{"https://foo.bar.example.com"}
|
||||
kubeAPIServerOptions.Authentication.ServiceAccounts.Issuers = []string{"https://foo.bar.example.com"}
|
||||
kubeAPIServerOptions.Authentication.ServiceAccounts.KeyFiles = []string{saSigningKeyFile.Name()}
|
||||
kubeAPIServerOptions.Authentication.ClientCert.ClientCA = clientCACertFile.Name()
|
||||
kubeAPIServerOptions.Authorization.Modes = []string{"Node", "RBAC"}
|
||||
|
||||
@@ -109,6 +130,11 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if errs := completedOptions.Validate(); len(errs) != 0 {
|
||||
t.Fatalf("failed to validate ServerRunOptions: %v", utilerrors.NewAggregate(errs))
|
||||
}
|
||||
|
||||
tunneler, proxyTransport, err := app.CreateNodeDialer(completedOptions)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -395,7 +395,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
|
||||
externalInformers.Core().V1().ServiceAccounts().Lister(),
|
||||
externalInformers.Core().V1().Pods().Lister(),
|
||||
)
|
||||
serviceAccountTokenAuth := serviceaccount.JWTTokenAuthenticator(serviceaccount.LegacyIssuer, []interface{}{&serviceAccountKey.PublicKey}, nil, serviceaccount.NewLegacyValidator(true, serviceAccountTokenGetter))
|
||||
serviceAccountTokenAuth := serviceaccount.JWTTokenAuthenticator([]string{serviceaccount.LegacyIssuer}, []interface{}{&serviceAccountKey.PublicKey}, nil, serviceaccount.NewLegacyValidator(true, serviceAccountTokenGetter))
|
||||
authenticator := union.New(
|
||||
bearertoken.New(rootTokenAuth),
|
||||
bearertoken.New(serviceAccountTokenAuth),
|
||||
|
||||
Reference in New Issue
Block a user