mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
Merge pull request #121818 from liggitt/authz-config-rbac-anonymous
Test authz config file with RBAC and anonymous auth
This commit is contained in:
commit
d26c154984
@ -99,8 +99,6 @@ ENABLE_TRACING=${ENABLE_TRACING:-false}
|
|||||||
# enable Kubernetes-CSI snapshotter
|
# enable Kubernetes-CSI snapshotter
|
||||||
ENABLE_CSI_SNAPSHOTTER=${ENABLE_CSI_SNAPSHOTTER:-false}
|
ENABLE_CSI_SNAPSHOTTER=${ENABLE_CSI_SNAPSHOTTER:-false}
|
||||||
|
|
||||||
# RBAC Mode options
|
|
||||||
AUTHORIZATION_MODE=${AUTHORIZATION_MODE:-"Node,RBAC"}
|
|
||||||
KUBECONFIG_TOKEN=${KUBECONFIG_TOKEN:-""}
|
KUBECONFIG_TOKEN=${KUBECONFIG_TOKEN:-""}
|
||||||
AUTH_ARGS=${AUTH_ARGS:-""}
|
AUTH_ARGS=${AUTH_ARGS:-""}
|
||||||
|
|
||||||
@ -494,10 +492,19 @@ function start_apiserver {
|
|||||||
# Append security_admission plugin
|
# Append security_admission plugin
|
||||||
ENABLE_ADMISSION_PLUGINS="${ENABLE_ADMISSION_PLUGINS}${security_admission}"
|
ENABLE_ADMISSION_PLUGINS="${ENABLE_ADMISSION_PLUGINS}${security_admission}"
|
||||||
|
|
||||||
authorizer_arg=""
|
authorizer_args=()
|
||||||
if [[ -n "${AUTHORIZATION_MODE}" ]]; then
|
if [[ -n "${AUTHORIZATION_CONFIG:-}" ]]; then
|
||||||
authorizer_arg="--authorization-mode=${AUTHORIZATION_MODE}"
|
authorizer_args+=("--authorization-config=${AUTHORIZATION_CONFIG}")
|
||||||
|
else
|
||||||
|
if [[ -n "${AUTHORIZATION_MODE:-Node,RBAC}" ]]; then
|
||||||
|
authorizer_args+=("--authorization-mode=${AUTHORIZATION_MODE:-Node,RBAC}")
|
||||||
|
fi
|
||||||
|
authorizer_args+=(
|
||||||
|
"--authorization-webhook-config-file=${AUTHORIZATION_WEBHOOK_CONFIG_FILE}"
|
||||||
|
"--authentication-token-webhook-config-file=${AUTHENTICATION_WEBHOOK_CONFIG_FILE}"
|
||||||
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
priv_arg=""
|
priv_arg=""
|
||||||
if [[ -n "${ALLOW_PRIVILEGED}" ]]; then
|
if [[ -n "${ALLOW_PRIVILEGED}" ]]; then
|
||||||
priv_arg="--allow-privileged=${ALLOW_PRIVILEGED}"
|
priv_arg="--allow-privileged=${ALLOW_PRIVILEGED}"
|
||||||
@ -570,7 +577,7 @@ EOF
|
|||||||
|
|
||||||
APISERVER_LOG=${LOG_DIR}/kube-apiserver.log
|
APISERVER_LOG=${LOG_DIR}/kube-apiserver.log
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
${CONTROLPLANE_SUDO} "${GO_OUT}/kube-apiserver" "${authorizer_arg}" "${priv_arg}" ${runtime_config} \
|
${CONTROLPLANE_SUDO} "${GO_OUT}/kube-apiserver" "${authorizer_args[@]}" "${priv_arg}" ${runtime_config} \
|
||||||
${cloud_config_arg} \
|
${cloud_config_arg} \
|
||||||
"${advertise_address}" \
|
"${advertise_address}" \
|
||||||
"${node_port_range}" \
|
"${node_port_range}" \
|
||||||
@ -578,8 +585,6 @@ EOF
|
|||||||
--vmodule="${LOG_SPEC}" \
|
--vmodule="${LOG_SPEC}" \
|
||||||
--audit-policy-file="${AUDIT_POLICY_FILE}" \
|
--audit-policy-file="${AUDIT_POLICY_FILE}" \
|
||||||
--audit-log-path="${LOG_DIR}/kube-apiserver-audit.log" \
|
--audit-log-path="${LOG_DIR}/kube-apiserver-audit.log" \
|
||||||
--authorization-webhook-config-file="${AUTHORIZATION_WEBHOOK_CONFIG_FILE}" \
|
|
||||||
--authentication-token-webhook-config-file="${AUTHENTICATION_WEBHOOK_CONFIG_FILE}" \
|
|
||||||
--cert-dir="${CERT_DIR}" \
|
--cert-dir="${CERT_DIR}" \
|
||||||
--egress-selector-config-file="${EGRESS_SELECTOR_CONFIG_FILE:-}" \
|
--egress-selector-config-file="${EGRESS_SELECTOR_CONFIG_FILE:-}" \
|
||||||
--client-ca-file="${CERT_DIR}/client-ca.crt" \
|
--client-ca-file="${CERT_DIR}/client-ca.crt" \
|
||||||
@ -613,14 +618,15 @@ EOF
|
|||||||
--cors-allowed-origins="${API_CORS_ALLOWED_ORIGINS}" >"${APISERVER_LOG}" 2>&1 &
|
--cors-allowed-origins="${API_CORS_ALLOWED_ORIGINS}" >"${APISERVER_LOG}" 2>&1 &
|
||||||
APISERVER_PID=$!
|
APISERVER_PID=$!
|
||||||
|
|
||||||
|
# Create kubeconfigs for all components, using client certs
|
||||||
|
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" admin
|
||||||
|
${CONTROLPLANE_SUDO} chown "${USER}" "${CERT_DIR}/client-admin.key" # make readable for kubectl
|
||||||
|
|
||||||
# Wait for kube-apiserver to come up before launching the rest of the components.
|
# Wait for kube-apiserver to come up before launching the rest of the components.
|
||||||
echo "Waiting for apiserver to come up"
|
echo "Waiting for apiserver to come up"
|
||||||
kube::util::wait_for_url "https://${API_HOST_IP}:${API_SECURE_PORT}/healthz" "apiserver: " 1 "${WAIT_FOR_URL_API_SERVER}" "${MAX_TIME_FOR_URL_API_SERVER}" \
|
kube::util::wait_for_url "https://${API_HOST_IP}:${API_SECURE_PORT}/healthz" "apiserver: " 1 "${WAIT_FOR_URL_API_SERVER}" "${MAX_TIME_FOR_URL_API_SERVER}" \
|
||||||
|| { echo "check apiserver logs: ${APISERVER_LOG}" ; exit 1 ; }
|
|| { echo "check apiserver logs: ${APISERVER_LOG}" ; exit 1 ; }
|
||||||
|
|
||||||
# Create kubeconfigs for all components, using client certs
|
|
||||||
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" admin
|
|
||||||
${CONTROLPLANE_SUDO} chown "${USER}" "${CERT_DIR}/client-admin.key" # make readable for kubectl
|
|
||||||
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" controller
|
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" controller
|
||||||
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" scheduler
|
kube::util::write_client_kubeconfig "${CONTROLPLANE_SUDO}" "${CERT_DIR}" "${ROOT_CA_FILE}" "${API_HOST}" "${API_SECURE_PORT}" scheduler
|
||||||
|
|
||||||
|
@ -147,12 +147,13 @@ func BuildGenericConfig(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, err = BuildAuthorizer(s, genericConfig.EgressSelector, versionedInformers)
|
var enablesRBAC bool
|
||||||
|
genericConfig.Authorization.Authorizer, genericConfig.RuleResolver, enablesRBAC, err = BuildAuthorizer(s, genericConfig.EgressSelector, versionedInformers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lastErr = fmt.Errorf("invalid authorization config: %v", err)
|
lastErr = fmt.Errorf("invalid authorization config: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.Authorization != nil && !sets.NewString(s.Authorization.Modes...).Has(modes.ModeRBAC) {
|
if s.Authorization != nil && !enablesRBAC {
|
||||||
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
|
genericConfig.DisabledPostStartHooks.Insert(rbacrest.PostStartHookName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,25 +169,35 @@ func BuildGenericConfig(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildAuthorizer constructs the authorizer. If authorization is not set in s, it returns nil, nil, nil
|
// BuildAuthorizer constructs the authorizer. If authorization is not set in s, it returns nil, nil, false, nil
|
||||||
func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, EgressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, error) {
|
func BuildAuthorizer(s controlplaneapiserver.CompletedOptions, egressSelector *egressselector.EgressSelector, versionedInformers clientgoinformers.SharedInformerFactory) (authorizer.Authorizer, authorizer.RuleResolver, bool, error) {
|
||||||
authorizationConfig, err := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
authorizationConfig, err := s.Authorization.ToAuthorizationConfig(versionedInformers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, false, err
|
||||||
}
|
}
|
||||||
if authorizationConfig == nil {
|
if authorizationConfig == nil {
|
||||||
return nil, nil, nil
|
return nil, nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if EgressSelector != nil {
|
if egressSelector != nil {
|
||||||
egressDialer, err := EgressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
|
egressDialer, err := egressSelector.Lookup(egressselector.ControlPlane.AsNetworkContext())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, false, err
|
||||||
}
|
}
|
||||||
authorizationConfig.CustomDial = egressDialer
|
authorizationConfig.CustomDial = egressDialer
|
||||||
}
|
}
|
||||||
|
|
||||||
return authorizationConfig.New()
|
enablesRBAC := false
|
||||||
|
for _, a := range authorizationConfig.AuthorizationConfiguration.Authorizers {
|
||||||
|
if string(a.Type) == modes.ModeRBAC {
|
||||||
|
enablesRBAC = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizer, ruleResolver, err := authorizationConfig.New()
|
||||||
|
|
||||||
|
return authorizer, ruleResolver, enablesRBAC, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreatePeerEndpointLeaseReconciler creates a apiserver endpoint lease reconciliation loop
|
// CreatePeerEndpointLeaseReconciler creates a apiserver endpoint lease reconciliation loop
|
||||||
|
@ -222,6 +222,9 @@ func (o *Options) Complete(alternateDNS []string, alternateIPs []net.IP) (Comple
|
|||||||
klog.Infof("external host was not specified, using %v", completed.GenericServerRunOptions.ExternalHost)
|
klog.Infof("external host was not specified, using %v", completed.GenericServerRunOptions.ExternalHost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// put authorization options in final state
|
||||||
|
completed.Authorization.Complete()
|
||||||
|
// adjust authentication for completed authorization
|
||||||
completed.Authentication.ApplyAuthorization(completed.Authorization)
|
completed.Authentication.ApplyAuthorization(completed.Authorization)
|
||||||
|
|
||||||
// Use (ServiceAccountSigningKeyFile != "") as a proxy to the user enabling
|
// Use (ServiceAccountSigningKeyFile != "") as a proxy to the user enabling
|
||||||
|
@ -80,7 +80,7 @@ type BuiltInAuthorizationOptions struct {
|
|||||||
// NewBuiltInAuthorizationOptions create a BuiltInAuthorizationOptions with default value
|
// NewBuiltInAuthorizationOptions create a BuiltInAuthorizationOptions with default value
|
||||||
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
|
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
|
||||||
return &BuiltInAuthorizationOptions{
|
return &BuiltInAuthorizationOptions{
|
||||||
Modes: []string{authzmodes.ModeAlwaysAllow},
|
Modes: []string{},
|
||||||
WebhookVersion: "v1beta1",
|
WebhookVersion: "v1beta1",
|
||||||
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
||||||
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
||||||
@ -88,6 +88,14 @@ func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complete modifies authorization options
|
||||||
|
func (o *BuiltInAuthorizationOptions) Complete() []error {
|
||||||
|
if len(o.AuthorizationConfigurationFile) == 0 && len(o.Modes) == 0 {
|
||||||
|
o.Modes = []string{authzmodes.ModeAlwaysAllow}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Validate checks invalid config combination
|
// Validate checks invalid config combination
|
||||||
func (o *BuiltInAuthorizationOptions) Validate() []error {
|
func (o *BuiltInAuthorizationOptions) Validate() []error {
|
||||||
if o == nil {
|
if o == nil {
|
||||||
@ -185,7 +193,7 @@ func (o *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fs.StringSliceVar(&o.Modes, authorizationModeFlag, o.Modes, ""+
|
fs.StringSliceVar(&o.Modes, authorizationModeFlag, o.Modes, ""+
|
||||||
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "+
|
"Ordered list of plug-ins to do authorization on secure port. Defaults to AlwaysAllow if --authorization-config is not used. Comma-delimited list of: "+
|
||||||
strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")
|
strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")
|
||||||
|
|
||||||
fs.StringVar(&o.PolicyFile, authorizationPolicyFileFlag, o.PolicyFile, ""+
|
fs.StringVar(&o.PolicyFile, authorizationPolicyFileFlag, o.PolicyFile, ""+
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -34,6 +35,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/features"
|
"k8s.io/apiserver/pkg/features"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
"k8s.io/kubernetes/test/integration/authutil"
|
"k8s.io/kubernetes/test/integration/authutil"
|
||||||
@ -63,6 +65,16 @@ authorizers:
|
|||||||
)
|
)
|
||||||
t.Cleanup(server.TearDownFn)
|
t.Cleanup(server.TearDownFn)
|
||||||
|
|
||||||
|
// Make sure anonymous requests work
|
||||||
|
anonymousClient := clientset.NewForConfigOrDie(rest.AnonymousClientConfig(server.ClientConfig))
|
||||||
|
healthzResult, err := anonymousClient.DiscoveryClient.RESTClient().Get().AbsPath("/healthz").Do(context.TODO()).Raw()
|
||||||
|
if !bytes.Equal(healthzResult, []byte(`ok`)) {
|
||||||
|
t.Fatalf("expected 'ok', got %s", string(healthzResult))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
adminClient := clientset.NewForConfigOrDie(server.ClientConfig)
|
adminClient := clientset.NewForConfigOrDie(server.ClientConfig)
|
||||||
|
|
||||||
sar := &authorizationv1.SubjectAccessReview{Spec: authorizationv1.SubjectAccessReviewSpec{
|
sar := &authorizationv1.SubjectAccessReview{Spec: authorizationv1.SubjectAccessReviewSpec{
|
||||||
|
Loading…
Reference in New Issue
Block a user