*: remove --insecure-allow-any-token option

e2e and integration tests have been switched over to the tokenfile
authenticator instead.

```release-note
The --insecure-allow-any-token flag has been removed from kube-apiserver. Users of the flag should use impersonation headers instead for debugging.
```
pull/6/head
Eric Chiang 2017-07-17 15:59:15 -07:00
parent ebf24c14a9
commit e2f2ab67f2
16 changed files with 55 additions and 212 deletions

View File

@ -691,7 +691,6 @@ staging/src/k8s.io/apiserver/plugin/pkg/audit
staging/src/k8s.io/apiserver/plugin/pkg/audit/log
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/keystone
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/anytoken
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/testing
staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest

View File

@ -76,7 +76,6 @@ ENABLE_CLUSTER_DASHBOARD=${KUBE_ENABLE_CLUSTER_DASHBOARD:-false}
ENABLE_APISERVER_BASIC_AUDIT=${ENABLE_APISERVER_BASIC_AUDIT:-false}
# RBAC Mode options
ALLOW_ANY_TOKEN=${ALLOW_ANY_TOKEN:-false}
ENABLE_RBAC=${ENABLE_RBAC:-false}
AUTHORIZATION_MODE=${AUTHORIZATION_MODE:-""}
KUBECONFIG_TOKEN=${KUBECONFIG_TOKEN:-""}
@ -434,11 +433,6 @@ function start_apiserver {
swagger_arg="--enable-swagger-ui=true "
fi
anytoken_arg=""
if [[ "${ALLOW_ANY_TOKEN}" = true ]]; then
anytoken_arg="--insecure-allow-any-token "
KUBECONFIG_TOKEN="${KUBECONFIG_TOKEN:-system:admin/system:masters}"
fi
authorizer_arg=""
if [[ "${ENABLE_RBAC}" = true ]]; then
authorizer_arg="--authorization-mode=RBAC "
@ -498,7 +492,7 @@ function start_apiserver {
APISERVER_LOG=${LOG_DIR}/kube-apiserver.log
${CONTROLPLANE_SUDO} "${GO_OUT}/hyperkube" apiserver ${swagger_arg} ${audit_arg} ${anytoken_arg} ${authorizer_arg} ${priv_arg} ${runtime_config}\
${CONTROLPLANE_SUDO} "${GO_OUT}/hyperkube" apiserver ${swagger_arg} ${audit_arg} ${authorizer_arg} ${priv_arg} ${runtime_config}\
${advertise_address} \
--v=${LOG_LEVEL} \
--vmodule="${LOG_SPEC}" \
@ -548,17 +542,7 @@ function start_apiserver {
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" scheduler
if [[ -z "${AUTH_ARGS}" ]]; then
if [[ "${ALLOW_ANY_TOKEN}" = true ]]; then
# use token authentication
if [[ -n "${KUBECONFIG_TOKEN}" ]]; then
AUTH_ARGS="--token=${KUBECONFIG_TOKEN}"
else
AUTH_ARGS="--token=system:admin/system:masters"
fi
else
# default to the admin client cert/key
AUTH_ARGS="--client-key=${CERT_DIR}/client-admin.key --client-certificate=${CERT_DIR}/client-admin.crt"
fi
AUTH_ARGS="--client-key=${CERT_DIR}/client-admin.key --client-certificate=${CERT_DIR}/client-admin.crt"
fi
${CONTROLPLANE_SUDO} cp "${CERT_DIR}/admin.kubeconfig" "${CERT_DIR}/admin-kube-aggregator.kubeconfig"

View File

@ -4132,8 +4132,9 @@ runTests() {
-s "http://127.0.0.1:${API_PORT}"
)
# token defined in hack/testdata/auth-tokens.csv
kube_flags_with_token=(
-s "https://127.0.0.1:${SECURE_API_PORT}" --token=admin/system:masters --insecure-skip-tls-verify=true
-s "https://127.0.0.1:${SECURE_API_PORT}" --token=admin-token --insecure-skip-tls-verify=true
)
if [[ -z "${ALLOW_SKEW:-}" ]]; then

View File

@ -51,7 +51,7 @@ function run_kube_apiserver() {
--storage-media-type="${KUBE_TEST_API_STORAGE_TYPE-}" \
--cert-dir="${TMPDIR:-/tmp/}" \
--service-cluster-ip-range="10.0.0.0/24" \
--insecure-allow-any-token 1>&2 &
--token-auth-file=hack/testdata/auth-tokens.csv 1>&2 &
APISERVER_PID=$!
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver"

View File

@ -43,7 +43,7 @@ function run_federation_apiserver() {
--etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \
--storage-media-type="${KUBE_TEST_API_STORAGE_TYPE-}" \
--cert-dir="${TMPDIR:-/tmp/}" \
--insecure-allow-any-token 1>&2 &
--token-auth-file=hack/testdata/auth-tokens.csv 1>&2 &
APISERVER_PID=$!
kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver"

1
hack/testdata/auth-tokens.csv vendored Normal file
View File

@ -0,0 +1 @@
admin-token,admin,,"system:masters"
1 admin-token admin system:masters

View File

@ -348,7 +348,6 @@ include-extended-apis
initial-sync-timeout
input-base
input-dirs
insecure-allow-any-token
insecure-bind-address
insecure-experimental-approve-all-kubelet-csrs-for-group
insecure-port

View File

@ -27,7 +27,6 @@ go_library(
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/keystone:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/anytoken:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook:go_default_library",
"//vendor/k8s.io/client-go/plugin/pkg/client/auth/gcp:go_default_library",

View File

@ -34,7 +34,6 @@ import (
"k8s.io/apiserver/plugin/pkg/authenticator/password/keystone"
"k8s.io/apiserver/plugin/pkg/authenticator/password/passwordfile"
"k8s.io/apiserver/plugin/pkg/authenticator/request/basicauth"
"k8s.io/apiserver/plugin/pkg/authenticator/token/anytoken"
"k8s.io/apiserver/plugin/pkg/authenticator/token/oidc"
"k8s.io/apiserver/plugin/pkg/authenticator/token/webhook"
certutil "k8s.io/client-go/util/cert"
@ -47,7 +46,6 @@ import (
type AuthenticatorConfig struct {
Anonymous bool
AnyToken bool
BasicAuthFile string
BootstrapToken bool
ClientCAFile string
@ -168,12 +166,6 @@ func (config AuthenticatorConfig) New() (authenticator.Request, *spec.SecurityDe
hasTokenAuth = true
}
// always add anytoken last, so that every other token authenticator gets to try first
if config.AnyToken {
authenticators = append(authenticators, bearertoken.New(anytoken.AnyTokenAuthenticator{}), websocket.NewProtocolAuthenticator(anytoken.AnyTokenAuthenticator{}))
hasTokenAuth = true
}
if hasBasicAuth {
securityDefinitions["HTTPBasic"] = &spec.SecurityScheme{
SecuritySchemeProps: spec.SecuritySchemeProps{

View File

@ -32,7 +32,6 @@ import (
type BuiltInAuthenticationOptions struct {
Anonymous *AnonymousAuthenticationOptions
AnyToken *AnyTokenAuthenticationOptions
BootstrapToken *BootstrapTokenAuthenticationOptions
ClientCert *genericoptions.ClientCertAuthenticationOptions
Keystone *KeystoneAuthenticationOptions
@ -44,10 +43,6 @@ type BuiltInAuthenticationOptions struct {
WebHook *WebHookAuthenticationOptions
}
type AnyTokenAuthenticationOptions struct {
Allow bool
}
type AnonymousAuthenticationOptions struct {
Allow bool
}
@ -94,7 +89,6 @@ func NewBuiltInAuthenticationOptions() *BuiltInAuthenticationOptions {
func (s *BuiltInAuthenticationOptions) WithAll() *BuiltInAuthenticationOptions {
return s.
WithAnyonymous().
WithAnyToken().
WithBootstrapToken().
WithClientCert().
WithKeystone().
@ -111,11 +105,6 @@ func (s *BuiltInAuthenticationOptions) WithAnyonymous() *BuiltInAuthenticationOp
return s
}
func (s *BuiltInAuthenticationOptions) WithAnyToken() *BuiltInAuthenticationOptions {
s.AnyToken = &AnyTokenAuthenticationOptions{}
return s
}
func (s *BuiltInAuthenticationOptions) WithBootstrapToken() *BuiltInAuthenticationOptions {
s.BootstrapToken = &BootstrapTokenAuthenticationOptions{}
return s
@ -182,13 +171,6 @@ func (s *BuiltInAuthenticationOptions) AddFlags(fs *pflag.FlagSet) {
"Anonymous requests have a username of system:anonymous, and a group name of system:unauthenticated.")
}
if s.AnyToken != nil {
fs.BoolVar(&s.AnyToken.Allow, "insecure-allow-any-token", s.AnyToken.Allow, ""+
"If set, your server will be INSECURE. Any token will be allowed and user information will be parsed "+
"from the token as `username/group1,group2`")
}
if s.BootstrapToken != nil {
fs.BoolVar(&s.BootstrapToken.Allow, "experimental-bootstrap-token-auth", s.BootstrapToken.Allow, ""+
"Enable to allow secrets of type 'bootstrap.kubernetes.io/token' in the 'kube-system' "+
@ -274,10 +256,6 @@ func (s *BuiltInAuthenticationOptions) ToAuthenticationConfig() authenticator.Au
ret.Anonymous = s.Anonymous.Allow
}
if s.AnyToken != nil {
ret.AnyToken = s.AnyToken.Allow
}
if s.BootstrapToken != nil {
ret.BootstrapToken = s.BootstrapToken.Allow
}

View File

@ -1,24 +0,0 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = ["anytoken_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = ["//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library"],
)
go_library(
name = "go_default_library",
srcs = ["anytoken.go"],
tags = ["automanaged"],
deps = ["//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library"],
)

View File

@ -1,42 +0,0 @@
/*
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 anytoken
import (
"strings"
"k8s.io/apiserver/pkg/authentication/user"
)
type AnyTokenAuthenticator struct{}
func (AnyTokenAuthenticator) AuthenticateToken(value string) (user.Info, bool, error) {
lastSlash := strings.LastIndex(value, "/")
if lastSlash == -1 {
return &user.DefaultInfo{Name: value}, true, nil
}
ret := &user.DefaultInfo{Name: value[:lastSlash]}
groupString := value[lastSlash+1:]
if len(groupString) == 0 {
return ret, true, nil
}
ret.Groups = strings.Split(groupString, ",")
return ret, true, nil
}

View File

@ -1,71 +0,0 @@
/*
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 anytoken
import (
"reflect"
"testing"
"k8s.io/apiserver/pkg/authentication/user"
)
func TestAnyTokenAuthenticator(t *testing.T) {
tests := []struct {
name string
token string
expectedUser user.Info
}{
{
name: "user only",
token: "joe",
expectedUser: &user.DefaultInfo{Name: "joe"},
},
{
name: "user with slash",
token: "scheme/joe/",
expectedUser: &user.DefaultInfo{Name: "scheme/joe"},
},
{
name: "user with groups",
token: "joe/group1,group2",
expectedUser: &user.DefaultInfo{Name: "joe", Groups: []string{"group1", "group2"}},
},
{
name: "user with slash and groups",
token: "scheme/joe/group1,group2",
expectedUser: &user.DefaultInfo{Name: "scheme/joe", Groups: []string{"group1", "group2"}},
},
}
for _, tc := range tests {
actualUser, _, _ := AnyTokenAuthenticator{}.AuthenticateToken(tc.token)
if len(actualUser.GetExtra()) != 0 {
t.Errorf("%q: got extra: %v", tc.name, actualUser.GetExtra())
}
if len(actualUser.GetUID()) != 0 {
t.Errorf("%q: got extra: %v", tc.name, actualUser.GetUID())
}
if e, a := tc.expectedUser.GetName(), actualUser.GetName(); e != a {
t.Errorf("%q: expected %v, got %v", tc.name, e, a)
}
if e, a := tc.expectedUser.GetGroups(), actualUser.GetGroups(); !reflect.DeepEqual(e, a) {
t.Errorf("%q: expected %v, got %v", tc.name, e, a)
}
}
}

View File

@ -59,11 +59,11 @@ go_test(
"//vendor/k8s.io/apiserver/pkg/authentication/group:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/request/bearertoken:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/token/tokenfile:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/anytoken:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/tokentest:go_default_library",
"//vendor/k8s.io/apiserver/plugin/pkg/authenticator/token/webhook:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",

View File

@ -27,6 +27,9 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
"k8s.io/apiserver/pkg/authentication/user"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
@ -46,9 +49,24 @@ func TestNodeAuthorizer(t *testing.T) {
h.M.GenericAPIServer.Handler.ServeHTTP(w, req)
}))
const (
// Define credentials
tokenMaster = "master-token"
tokenNodeUnknown = "unknown-token"
tokenNode1 = "node1-token"
tokenNode2 = "node2-token"
)
authenticator := bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
tokenMaster: {Name: "admin", Groups: []string{"system:masters"}},
tokenNodeUnknown: {Name: "unknown", Groups: []string{"system:nodes"}},
tokenNode1: {Name: "system:node:node1", Groups: []string{"system:nodes"}},
tokenNode2: {Name: "system:node:node2", Groups: []string{"system:nodes"}},
}))
// Build client config, clientset, and informers
clientConfig := &restclient.Config{Host: apiServer.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
superuserClient := clientsetForUser("admin/system:masters", clientConfig)
superuserClient := clientsetForToken(tokenMaster, clientConfig)
informerFactory := informers.NewSharedInformerFactory(superuserClient, time.Minute)
// Set up Node+RBAC authorizer
@ -71,7 +89,8 @@ func TestNodeAuthorizer(t *testing.T) {
// Start the server
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authenticator = newFakeAuthenticator()
masterConfig.GenericConfig.Authenticator = authenticator
masterConfig.GenericConfig.Authorizer = nodeRBACAuthorizer
masterConfig.GenericConfig.AdmissionControl = nodeRestrictionAdmission
_, _, closeFn := framework.RunAMasterUsingServer(masterConfig, apiServer, h)
@ -206,9 +225,9 @@ func TestNodeAuthorizer(t *testing.T) {
return client.Core().Nodes().Delete("node2", nil)
}
nodeanonClient := clientsetForUser("unknown/system:nodes", clientConfig)
node1Client := clientsetForUser("system:node:node1/system:nodes", clientConfig)
node2Client := clientsetForUser("system:node:node2/system:nodes", clientConfig)
nodeanonClient := clientsetForToken(tokenNodeUnknown, clientConfig)
node1Client := clientsetForToken(tokenNode1, clientConfig)
node2Client := clientsetForToken(tokenNode2, clientConfig)
// all node requests from node1 and unknown node fail
expectForbidden(t, getSecret(nodeanonClient))

View File

@ -31,11 +31,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/authentication/authenticator"
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
"k8s.io/apiserver/pkg/authentication/token/tokenfile"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/plugin/pkg/authenticator/token/anytoken"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/transport"
"k8s.io/kubernetes/pkg/api"
@ -55,11 +55,7 @@ import (
"k8s.io/kubernetes/test/integration/framework"
)
func newFakeAuthenticator() authenticator.Request {
return bearertoken.New(anytoken.AnyTokenAuthenticator{})
}
func clientForUser(user string) *http.Client {
func clientForToken(user string) *http.Client {
return &http.Client{
Transport: transport.NewBearerAuthRoundTripper(
user,
@ -68,7 +64,7 @@ func clientForUser(user string) *http.Client {
}
}
func clientsetForUser(user string, config *restclient.Config) clientset.Interface {
func clientsetForToken(user string, config *restclient.Config) clientset.Interface {
configCopy := *config
configCopy.BearerToken = user
return clientset.NewForConfigOrDie(&configCopy)
@ -137,8 +133,8 @@ func (b bootstrapRoles) bootstrap(client clientset.Interface) error {
// request is a test case which can.
type request struct {
// The username attempting to send the request.
user string
// The bearer token sent as part of the request
token string
// Resource metadata
verb string
@ -155,7 +151,7 @@ type request struct {
}
func (r request) String() string {
return fmt.Sprintf("%s %s %s", r.user, r.verb, r.resource)
return fmt.Sprintf("%s %s %s", r.token, r.verb, r.resource)
}
type statusCode int
@ -414,14 +410,24 @@ func TestRBAC(t *testing.T) {
// Create an API Server.
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig)
masterConfig.GenericConfig.Authenticator = newFakeAuthenticator()
masterConfig.GenericConfig.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
superUser: {Name: "admin", Groups: []string{"system:masters"}},
"any-rolebinding-writer": {Name: "any-rolebinding-writer"},
"any-rolebinding-writer-namespace": {Name: "any-rolebinding-writer-namespace"},
"bob": {Name: "bob"},
"job-writer": {Name: "job-writer"},
"job-writer-namespace": {Name: "job-writer-namespace"},
"nonescalating-rolebinding-writer": {Name: "nonescalating-rolebinding-writer"},
"pod-reader": {Name: "pod-reader"},
"user-with-no-permissions": {Name: "user-with-no-permissions"},
}))
_, s, closeFn := framework.RunAMaster(masterConfig)
defer closeFn()
clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}}
// Bootstrap the API Server with the test case's initial roles.
if err := tc.bootstrapRoles.bootstrap(clientsetForUser(superUser, clientConfig)); err != nil {
if err := tc.bootstrapRoles.bootstrap(clientsetForToken(superUser, clientConfig)); err != nil {
t.Errorf("case %d: failed to apply initial roles: %v", i, err)
continue
}
@ -459,7 +465,7 @@ func TestRBAC(t *testing.T) {
return
}
resp, err := clientForUser(r.user).Do(req)
resp, err := clientForToken(r.token).Do(req)
if err != nil {
t.Errorf("case %d, req %d: failed to make request: %v", i, j, err)
return
@ -506,7 +512,9 @@ func TestBootstrapping(t *testing.T) {
masterConfig := framework.NewIntegrationTestMasterConfig()
masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig)
masterConfig.GenericConfig.Authenticator = newFakeAuthenticator()
masterConfig.GenericConfig.Authenticator = bearertoken.New(tokenfile.New(map[string]*user.DefaultInfo{
superUser: {Name: "admin", Groups: []string{"system:masters"}},
}))
_, s, closeFn := framework.RunAMaster(masterConfig)
defer closeFn()