diff --git a/openshift-kube-apiserver/enablement/intialization.go b/openshift-kube-apiserver/enablement/intialization.go index 37da08f69ed0..e6f8b43b0859 100644 --- a/openshift-kube-apiserver/enablement/intialization.go +++ b/openshift-kube-apiserver/enablement/intialization.go @@ -4,21 +4,21 @@ import ( "io/ioutil" "path" + configv1 "github.com/openshift/api/config/v1" + kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1" + osinv1 "github.com/openshift/api/osin/v1" + "github.com/openshift/library-go/pkg/config/helpers" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apiserver/pkg/server" "k8s.io/client-go/tools/clientcmd/api" aggregatorapiserver "k8s.io/kube-aggregator/pkg/apiserver" "k8s.io/kubernetes/openshift-kube-apiserver/configdefault" "k8s.io/kubernetes/pkg/capabilities" kubelettypes "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" - - configv1 "github.com/openshift/api/config/v1" - kubecontrolplanev1 "github.com/openshift/api/kubecontrolplane/v1" - osinv1 "github.com/openshift/api/osin/v1" - "github.com/openshift/library-go/pkg/config/helpers" ) func GetOpenshiftConfig(openshiftConfigFile string) (*kubecontrolplanev1.KubeAPIServerConfig, error) { @@ -78,4 +78,8 @@ func ForceGlobalInitializationForOpenShift() { // TODO, we should scrub these out bootstrappolicy.ClusterRoles = bootstrappolicy.OpenshiftClusterRoles bootstrappolicy.ClusterRoleBindings = bootstrappolicy.OpenshiftClusterRoleBindings + + // we need to have the authorization chain place something before system:masters + // SkipSystemMastersAuthorizer disable implicitly added system/master authz, and turn it into another authz mode "SystemMasters", to be added via authorization-mode + server.SkipSystemMastersAuthorizer() } diff --git a/openshift-kube-apiserver/openshiftkubeapiserver/flags.go b/openshift-kube-apiserver/openshiftkubeapiserver/flags.go index b3faf6bd5452..b28dd265ee29 100644 --- a/openshift-kube-apiserver/openshiftkubeapiserver/flags.go +++ b/openshift-kube-apiserver/openshiftkubeapiserver/flags.go @@ -102,7 +102,7 @@ func ConfigToFlags(kubeAPIServerConfig *kubecontrolplanev1.KubeAPIServerConfig) } configflags.SetIfUnset(args, "allow-privileged", "true") configflags.SetIfUnset(args, "anonymous-auth", "true") - configflags.SetIfUnset(args, "authorization-mode", "RBAC", "Node") // overridden later, but this runs the poststarthook for bootstrapping RBAC + configflags.SetIfUnset(args, "authorization-mode", "Scope", "SystemMasters", "RBAC", "Node") // overridden later, but this runs the poststarthook for bootstrapping RBAC for flag, value := range configflags.AuditFlags(&kubeAPIServerConfig.AuditConfig, configflags.ArgsWithPrefix(args, "audit-")) { configflags.SetIfUnset(args, flag, value...) } diff --git a/openshift-kube-apiserver/openshiftkubeapiserver/patch.go b/openshift-kube-apiserver/openshiftkubeapiserver/patch.go index f66d9a1ab545..6c446c9fb8ff 100644 --- a/openshift-kube-apiserver/openshiftkubeapiserver/patch.go +++ b/openshift-kube-apiserver/openshiftkubeapiserver/patch.go @@ -45,8 +45,6 @@ func NewOpenShiftKubeAPIServerConfigPatch(kubeAPIServerConfig *kubecontrolplanev // AUTHORIZER genericConfig.RequestInfoResolver = apiserverconfig.OpenshiftRequestInfoResolver() - authorizer := NewAuthorizer(kubeInformers) - genericConfig.Authorization.Authorizer = authorizer // END AUTHORIZER // Inject OpenShift API long running endpoints (like for binary builds). diff --git a/openshift-kube-apiserver/openshiftkubeapiserver/patch_authorizer.go b/openshift-kube-apiserver/openshiftkubeapiserver/patch_authorizer.go deleted file mode 100644 index 26a6f5273d63..000000000000 --- a/openshift-kube-apiserver/openshiftkubeapiserver/patch_authorizer.go +++ /dev/null @@ -1,52 +0,0 @@ -package openshiftkubeapiserver - -import ( - "k8s.io/apiserver/pkg/authentication/user" - "k8s.io/apiserver/pkg/authorization/authorizer" - "k8s.io/apiserver/pkg/authorization/authorizerfactory" - authorizerunion "k8s.io/apiserver/pkg/authorization/union" - "k8s.io/client-go/informers" - "k8s.io/kubernetes/pkg/auth/nodeidentifier" - "k8s.io/kubernetes/plugin/pkg/auth/authorizer/node" - rbacauthorizer "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac" - kbootstrappolicy "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy" - - "k8s.io/kubernetes/openshift-kube-apiserver/authorization/browsersafe" - "k8s.io/kubernetes/openshift-kube-apiserver/authorization/scopeauthorizer" -) - -func NewAuthorizer(versionedInformers informers.SharedInformerFactory) authorizer.Authorizer { - rbacInformers := versionedInformers.Rbac().V1() - - scopeLimitedAuthorizer := scopeauthorizer.NewAuthorizer(rbacInformers.ClusterRoles().Lister()) - - kubeAuthorizer := rbacauthorizer.New( - &rbacauthorizer.RoleGetter{Lister: rbacInformers.Roles().Lister()}, - &rbacauthorizer.RoleBindingLister{Lister: rbacInformers.RoleBindings().Lister()}, - &rbacauthorizer.ClusterRoleGetter{Lister: rbacInformers.ClusterRoles().Lister()}, - &rbacauthorizer.ClusterRoleBindingLister{Lister: rbacInformers.ClusterRoleBindings().Lister()}, - ) - - graph := node.NewGraph() - node.AddGraphEventHandlers( - graph, - versionedInformers.Core().V1().Nodes(), - versionedInformers.Core().V1().Pods(), - versionedInformers.Core().V1().PersistentVolumes(), - versionedInformers.Storage().V1().VolumeAttachments(), - ) - nodeAuthorizer := node.NewAuthorizer(graph, nodeidentifier.NewDefaultNodeIdentifier(), kbootstrappolicy.NodeRules()) - - openshiftAuthorizer := authorizerunion.New( - // Wrap with an authorizer that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately. - // Scopes are first because they will authoritatively deny and can logically be attached to anyone. - browsersafe.NewBrowserSafeAuthorizer(scopeLimitedAuthorizer, user.AllAuthenticated), - // authorizes system:masters to do anything, just like upstream - authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup), - nodeAuthorizer, - // Wrap with an authorizer that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately - browsersafe.NewBrowserSafeAuthorizer(kubeAuthorizer, user.AllAuthenticated), - ) - - return openshiftAuthorizer -} diff --git a/pkg/kubeapiserver/authorizer/config.go b/pkg/kubeapiserver/authorizer/config.go index ed3cf6decc1b..7817c7e5bd93 100644 --- a/pkg/kubeapiserver/authorizer/config.go +++ b/pkg/kubeapiserver/authorizer/config.go @@ -21,6 +21,10 @@ import ( "fmt" "time" + "k8s.io/apiserver/pkg/authentication/user" + "k8s.io/kubernetes/openshift-kube-apiserver/authorization/browsersafe" + "k8s.io/kubernetes/openshift-kube-apiserver/authorization/scopeauthorizer" + utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -132,8 +136,16 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro &rbac.ClusterRoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoles().Lister()}, &rbac.ClusterRoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoleBindings().Lister()}, ) - authorizers = append(authorizers, rbacAuthorizer) + // Wrap with an authorizer that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately + authorizers = append(authorizers, browsersafe.NewBrowserSafeAuthorizer(rbacAuthorizer, user.AllAuthenticated)) ruleResolvers = append(ruleResolvers, rbacAuthorizer) + case modes.ModeScope: + // Wrap with an authorizer that detects unsafe requests and modifies verbs/resources appropriately so policy can address them separately + scopeLimitedAuthorizer := scopeauthorizer.NewAuthorizer(config.VersionedInformerFactory.Rbac().V1().ClusterRoles().Lister()) + authorizers = append(authorizers, browsersafe.NewBrowserSafeAuthorizer(scopeLimitedAuthorizer, user.AllAuthenticated)) + case modes.ModeSystemMasters: + // no browsersafeauthorizer here becase that rewrites the resources. This authorizer matches no matter which resource matches. + authorizers = append(authorizers, authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup)) default: return nil, nil, fmt.Errorf("unknown authorization mode %s specified", authorizationMode) } diff --git a/pkg/kubeapiserver/authorizer/modes/patch.go b/pkg/kubeapiserver/authorizer/modes/patch.go new file mode 100644 index 000000000000..bc892601ebe6 --- /dev/null +++ b/pkg/kubeapiserver/authorizer/modes/patch.go @@ -0,0 +1,8 @@ +package modes + +var ModeScope = "Scope" +var ModeSystemMasters = "SystemMasters" + +func init() { + AuthorizationModeChoices = append(AuthorizationModeChoices, ModeScope, ModeSystemMasters) +} diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index c4bbe15119e4..ff86b3c21932 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -885,6 +885,8 @@ func AuthorizeClientBearerToken(loopback *restclient.Config, authn *Authenticati tokenAuthenticator := authenticatorfactory.NewFromTokens(tokens, authn.APIAudiences) authn.Authenticator = authenticatorunion.New(tokenAuthenticator, authn.Authenticator) - tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) - authz.Authorizer = authorizerunion.New(tokenAuthorizer, authz.Authorizer) + if !skipSystemMastersAuthorizer { + tokenAuthorizer := authorizerfactory.NewPrivilegedGroups(user.SystemPrivilegedGroup) + authz.Authorizer = authorizerunion.New(tokenAuthorizer, authz.Authorizer) + } } diff --git a/staging/src/k8s.io/apiserver/pkg/server/patch.go b/staging/src/k8s.io/apiserver/pkg/server/patch.go new file mode 100644 index 000000000000..75d9a5bfc8d9 --- /dev/null +++ b/staging/src/k8s.io/apiserver/pkg/server/patch.go @@ -0,0 +1,8 @@ +package server + +var skipSystemMastersAuthorizer = false + +// SkipSystemMastersAuthorizer disable implicitly added system/master authz, and turn it into another authz mode "SystemMasters", to be added via authorization-mode +func SkipSystemMastersAuthorizer() { + skipSystemMastersAuthorizer = true +}