mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Merge pull request #41810 from luxas/kubeadm_rbac_default
Automatic merge from submit-queue (batch tested with PRs 38702, 41810, 41778, 41858, 41872) Always enable RBAC in kubeadm and make a pkg with authorization constants **What this PR does / why we need it**: This PR: - Splits the authz constants out into a dedicated package, so consumers don't have to import lots of other things (informers, etc...) - Makes a `IsValidAuthorizationMode` function for easy checking - Hooks up kubeadm against the new constant package, for example using the validation method when validating the kubeadm API obj - Always enables RBAC in kubeadm as discussed with @liggitt and @jbeda - This because we have to grant some rules in all cases for kubeadm (for instance, making the cluster-info configmap public) - Adds more unit tests **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: **Release note**: ```release-note NONE ``` @liggitt @jbeda @errordeveloper @dmmcquay @pires @deads2k
This commit is contained in:
commit
3418c8eaf2
@ -15,6 +15,7 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||||
],
|
],
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,8 +44,9 @@ var cloudproviders = []string{
|
|||||||
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
|
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("discovery"))...)
|
||||||
allErrs = append(allErrs, ValidateDiscovery(&c.Discovery, field.NewPath("service subnet"))...)
|
allErrs = append(allErrs, ValidateServiceSubnet(c.Networking.ServiceSubnet, field.NewPath("service subnet"))...)
|
||||||
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
||||||
|
allErrs = append(allErrs, ValidateAuthorizationMode(c.AuthorizationMode, field.NewPath("authorization-mode"))...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +98,13 @@ func ValidateTokenDiscovery(c *kubeadm.TokenDiscovery, fldPath *field.Path) fiel
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidateAuthorizationMode(authzMode string, fldPath *field.Path) field.ErrorList {
|
||||||
|
if !authzmodes.IsValidAuthorizationMode(authzMode) {
|
||||||
|
return field.ErrorList{field.Invalid(fldPath, nil, "invalid authorization mode")}
|
||||||
|
}
|
||||||
|
return field.ErrorList{}
|
||||||
|
}
|
||||||
|
|
||||||
func ValidateServiceSubnet(subnet string, fldPath *field.Path) field.ErrorList {
|
func ValidateServiceSubnet(subnet string, fldPath *field.Path) field.ErrorList {
|
||||||
_, svcSubnet, err := net.ParseCIDR(subnet)
|
_, svcSubnet, err := net.ParseCIDR(subnet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -46,6 +46,30 @@ func TestValidateTokenDiscovery(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateAuthorizationMode(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
s string
|
||||||
|
f *field.Path
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"", nil, false},
|
||||||
|
{"rBAC", nil, false}, // not supported
|
||||||
|
{"not valid", nil, false}, // not supported
|
||||||
|
{"RBAC", nil, true}, // supported
|
||||||
|
{"Webhook", nil, true}, // supported
|
||||||
|
}
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := ValidateAuthorizationMode(rt.s, rt.f)
|
||||||
|
if (len(actual) == 0) != rt.expected {
|
||||||
|
t.Errorf(
|
||||||
|
"failed ValidateAuthorizationMode:\n\texpected: %t\n\t actual: %t",
|
||||||
|
rt.expected,
|
||||||
|
(len(actual) == 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateServiceSubnet(t *testing.T) {
|
func TestValidateServiceSubnet(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
s string
|
s string
|
||||||
@ -111,16 +135,28 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
|||||||
Addresses: []string{"foobar"},
|
Addresses: []string{"foobar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AuthorizationMode: "RBAC",
|
||||||
|
Networking: kubeadm.Networking{
|
||||||
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
},
|
||||||
}, false},
|
}, false},
|
||||||
{&kubeadm.MasterConfiguration{
|
{&kubeadm.MasterConfiguration{
|
||||||
Discovery: kubeadm.Discovery{
|
Discovery: kubeadm.Discovery{
|
||||||
HTTPS: &kubeadm.HTTPSDiscovery{URL: "foo"},
|
HTTPS: &kubeadm.HTTPSDiscovery{URL: "foo"},
|
||||||
},
|
},
|
||||||
|
AuthorizationMode: "RBAC",
|
||||||
|
Networking: kubeadm.Networking{
|
||||||
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
},
|
||||||
}, true},
|
}, true},
|
||||||
{&kubeadm.MasterConfiguration{
|
{&kubeadm.MasterConfiguration{
|
||||||
Discovery: kubeadm.Discovery{
|
Discovery: kubeadm.Discovery{
|
||||||
File: &kubeadm.FileDiscovery{Path: "foo"},
|
File: &kubeadm.FileDiscovery{Path: "foo"},
|
||||||
},
|
},
|
||||||
|
AuthorizationMode: "RBAC",
|
||||||
|
Networking: kubeadm.Networking{
|
||||||
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
},
|
||||||
}, true},
|
}, true},
|
||||||
{&kubeadm.MasterConfiguration{
|
{&kubeadm.MasterConfiguration{
|
||||||
Discovery: kubeadm.Discovery{
|
Discovery: kubeadm.Discovery{
|
||||||
@ -130,6 +166,10 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
|||||||
Addresses: []string{"foobar"},
|
Addresses: []string{"foobar"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
AuthorizationMode: "RBAC",
|
||||||
|
Networking: kubeadm.Networking{
|
||||||
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
},
|
||||||
}, true},
|
}, true},
|
||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
|
@ -253,12 +253,10 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.cfg.AuthorizationMode == kubeadmconstants.AuthzModeRBAC {
|
|
||||||
err = apiconfigphase.CreateRBACRules(client)
|
err = apiconfigphase.CreateRBACRules(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if err := addonsphase.CreateEssentialAddons(i.cfg, client); err != nil {
|
if err := addonsphase.CreateEssentialAddons(i.cfg, client); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -16,11 +16,14 @@ limitations under the License.
|
|||||||
|
|
||||||
package constants
|
package constants
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AuthorizationPolicyFile = "abac_policy.json"
|
// KubernetesDir is the directory kubernetes owns for storing various configuration files
|
||||||
AuthorizationWebhookConfigFile = "webhook_authz.conf"
|
KubernetesDir = "/etc/kubernetes"
|
||||||
|
|
||||||
CACertAndKeyBaseName = "ca"
|
CACertAndKeyBaseName = "ca"
|
||||||
CACertName = "ca.crt"
|
CACertName = "ca.crt"
|
||||||
@ -49,14 +52,6 @@ const (
|
|||||||
AdminKubeConfigFileName = "admin.conf"
|
AdminKubeConfigFileName = "admin.conf"
|
||||||
KubeletKubeConfigFileName = "kubelet.conf"
|
KubeletKubeConfigFileName = "kubelet.conf"
|
||||||
|
|
||||||
// TODO: These constants should actually come from pkg/kubeapiserver/authorizer, but we can't vendor that package in now
|
|
||||||
// because of all the other sub-packages that would get vendored. To fix this, a pkg/kubeapiserver/authorizer/modes package
|
|
||||||
// or similar should exist that only has these constants; then we can vendor it.
|
|
||||||
AuthzModeAlwaysAllow = "AlwaysAllow"
|
|
||||||
AuthzModeABAC = "ABAC"
|
|
||||||
AuthzModeRBAC = "RBAC"
|
|
||||||
AuthzModeWebhook = "Webhook"
|
|
||||||
|
|
||||||
// Important: a "v"-prefix shouldn't exist here; semver doesn't allow that
|
// Important: a "v"-prefix shouldn't exist here; semver doesn't allow that
|
||||||
MinimumControlPlaneVersion = "1.6.0-alpha.2"
|
MinimumControlPlaneVersion = "1.6.0-alpha.2"
|
||||||
|
|
||||||
@ -83,3 +78,8 @@ const (
|
|||||||
// The file name of the tokens file that can be used for bootstrapping
|
// The file name of the tokens file that can be used for bootstrapping
|
||||||
CSVTokenFileName = "tokens.csv"
|
CSVTokenFileName = "tokens.csv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
AuthorizationPolicyPath = path.Join(KubernetesDir, "abac_policy.json")
|
||||||
|
AuthorizationWebhookConfigPath = path.Join(KubernetesDir, "webhook_authz.conf")
|
||||||
|
)
|
||||||
|
@ -24,6 +24,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/images:go_default_library",
|
"//cmd/kubeadm/app/images:go_default_library",
|
||||||
"//cmd/kubeadm/app/util:go_default_library",
|
"//cmd/kubeadm/app/util:go_default_library",
|
||||||
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//vendor:github.com/ghodss/yaml",
|
"//vendor:github.com/ghodss/yaml",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
"k8s.io/kubernetes/cmd/kubeadm/app/images"
|
||||||
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -326,15 +327,7 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [
|
|||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
)
|
)
|
||||||
|
|
||||||
if cfg.AuthorizationMode != "" {
|
command = append(command, getAuthzParameters(cfg.AuthorizationMode)...)
|
||||||
command = append(command, "--authorization-mode="+cfg.AuthorizationMode)
|
|
||||||
switch cfg.AuthorizationMode {
|
|
||||||
case kubeadmconstants.AuthzModeABAC:
|
|
||||||
command = append(command, "--authorization-policy-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.AuthorizationPolicyFile))
|
|
||||||
case kubeadmconstants.AuthzModeWebhook:
|
|
||||||
command = append(command, "--authorization-webhook-config-file="+path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.AuthorizationWebhookConfigFile))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use first address we are given
|
// Use first address we are given
|
||||||
if len(cfg.API.AdvertiseAddresses) > 0 {
|
if len(cfg.API.AdvertiseAddresses) > 0 {
|
||||||
@ -459,3 +452,22 @@ func getSelfHostedAPIServerEnv() []api.EnvVar {
|
|||||||
|
|
||||||
return append(getProxyEnvVars(), podIPEnvVar)
|
return append(getProxyEnvVars(), podIPEnvVar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAuthzParameters(authzMode string) []string {
|
||||||
|
command := []string{}
|
||||||
|
// RBAC is always on. If the user specified
|
||||||
|
authzModes := []string{authzmodes.ModeRBAC}
|
||||||
|
if len(authzMode) != 0 && authzMode != authzmodes.ModeRBAC {
|
||||||
|
authzModes = append(authzModes, authzMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
command = append(command, "--authorization-mode="+strings.Join(authzModes, ","))
|
||||||
|
|
||||||
|
switch authzMode {
|
||||||
|
case authzmodes.ModeABAC:
|
||||||
|
command = append(command, "--authorization-policy-file="+kubeadmconstants.AuthorizationPolicyPath)
|
||||||
|
case authzmodes.ModeWebhook:
|
||||||
|
command = append(command, "--authorization-webhook-config-file="+kubeadmconstants.AuthorizationWebhookConfigPath)
|
||||||
|
}
|
||||||
|
return command
|
||||||
|
}
|
||||||
|
@ -388,6 +388,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
|
"--authorization-mode=RBAC",
|
||||||
"--etcd-servers=http://127.0.0.1:2379",
|
"--etcd-servers=http://127.0.0.1:2379",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -417,6 +418,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
|
"--authorization-mode=RBAC",
|
||||||
"--advertise-address=foo",
|
"--advertise-address=foo",
|
||||||
"--etcd-servers=http://127.0.0.1:2379",
|
"--etcd-servers=http://127.0.0.1:2379",
|
||||||
},
|
},
|
||||||
@ -448,6 +450,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
|
"--authorization-mode=RBAC",
|
||||||
"--etcd-servers=http://127.0.0.1:2379",
|
"--etcd-servers=http://127.0.0.1:2379",
|
||||||
"--etcd-certfile=fiz",
|
"--etcd-certfile=fiz",
|
||||||
"--etcd-keyfile=faz",
|
"--etcd-keyfile=faz",
|
||||||
@ -567,3 +570,62 @@ func TestGetSchedulerCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAuthzParameters(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
authMode string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
authMode: "",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
authMode: "RBAC",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
authMode: "AlwaysAllow",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC,AlwaysAllow",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
authMode: "AlwaysDeny",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC,AlwaysDeny",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
authMode: "ABAC",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC,ABAC",
|
||||||
|
"--authorization-policy-file=/etc/kubernetes/abac_policy.json",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
authMode: "Webhook",
|
||||||
|
expected: []string{
|
||||||
|
"--authorization-mode=RBAC,Webhook",
|
||||||
|
"--authorization-webhook-config-file=/etc/kubernetes/webhook_authz.conf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := getAuthzParameters(rt.authMode)
|
||||||
|
for i := range actual {
|
||||||
|
if actual[i] != rt.expected[i] {
|
||||||
|
t.Errorf(
|
||||||
|
"failed getAuthzParameters:\n\texpected: %s\n\t actual: %s",
|
||||||
|
rt.expected[i],
|
||||||
|
actual[i],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//pkg/api/validation:go_default_library",
|
"//pkg/api/validation:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//pkg/util/initsystem:go_default_library",
|
"//pkg/util/initsystem:go_default_library",
|
||||||
"//pkg/util/node:go_default_library",
|
"//pkg/util/node:go_default_library",
|
||||||
"//test/e2e_node/system:go_default_library",
|
"//test/e2e_node/system:go_default_library",
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"k8s.io/kubernetes/pkg/util/initsystem"
|
"k8s.io/kubernetes/pkg/util/initsystem"
|
||||||
"k8s.io/kubernetes/pkg/util/node"
|
"k8s.io/kubernetes/pkg/util/node"
|
||||||
"k8s.io/kubernetes/test/e2e_node/system"
|
"k8s.io/kubernetes/test/e2e_node/system"
|
||||||
@ -363,12 +364,10 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error {
|
|||||||
|
|
||||||
// Check the config for authorization mode
|
// Check the config for authorization mode
|
||||||
switch cfg.AuthorizationMode {
|
switch cfg.AuthorizationMode {
|
||||||
case kubeadmconstants.AuthzModeABAC:
|
case authzmodes.ModeABAC:
|
||||||
authorizationPolicyPath := filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.AuthorizationPolicyFile)
|
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationPolicyPath})
|
||||||
checks = append(checks, FileExistingCheck{Path: authorizationPolicyPath})
|
case authzmodes.ModeWebhook:
|
||||||
case kubeadmconstants.AuthzModeWebhook:
|
checks = append(checks, FileExistingCheck{Path: kubeadmconstants.AuthorizationWebhookConfigPath})
|
||||||
authorizationWebhookConfigPath := filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.AuthorizationWebhookConfigFile)
|
|
||||||
checks = append(checks, FileExistingCheck{Path: authorizationWebhookConfigPath})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return RunChecks(checks, os.Stderr)
|
return RunChecks(checks, os.Stderr)
|
||||||
|
@ -16,6 +16,7 @@ go_test(
|
|||||||
],
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
|
deps = ["//pkg/kubeapiserver/authorizer/modes:go_default_library"],
|
||||||
)
|
)
|
||||||
|
|
||||||
go_library(
|
go_library(
|
||||||
@ -25,6 +26,7 @@ go_library(
|
|||||||
deps = [
|
deps = [
|
||||||
"//pkg/auth/authorizer/abac:go_default_library",
|
"//pkg/auth/authorizer/abac:go_default_library",
|
||||||
"//pkg/controller/informers:go_default_library",
|
"//pkg/controller/informers:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//plugin/pkg/auth/authorizer/rbac:go_default_library",
|
"//plugin/pkg/auth/authorizer/rbac:go_default_library",
|
||||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizerfactory",
|
"//vendor:k8s.io/apiserver/pkg/authorization/authorizerfactory",
|
||||||
@ -42,6 +44,9 @@ filegroup(
|
|||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:all-srcs",
|
||||||
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
)
|
)
|
||||||
|
@ -27,17 +27,10 @@ import (
|
|||||||
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
|
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
|
||||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||||
"k8s.io/kubernetes/pkg/controller/informers"
|
"k8s.io/kubernetes/pkg/controller/informers"
|
||||||
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
ModeAlwaysAllow string = "AlwaysAllow"
|
|
||||||
ModeAlwaysDeny string = "AlwaysDeny"
|
|
||||||
ModeABAC string = "ABAC"
|
|
||||||
ModeWebhook string = "Webhook"
|
|
||||||
ModeRBAC string = "RBAC"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AuthorizationConfig struct {
|
type AuthorizationConfig struct {
|
||||||
AuthorizationModes []string
|
AuthorizationModes []string
|
||||||
|
|
||||||
@ -79,11 +72,11 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) {
|
|||||||
}
|
}
|
||||||
// Keep cases in sync with constant list above.
|
// Keep cases in sync with constant list above.
|
||||||
switch authorizationMode {
|
switch authorizationMode {
|
||||||
case ModeAlwaysAllow:
|
case modes.ModeAlwaysAllow:
|
||||||
authorizers = append(authorizers, authorizerfactory.NewAlwaysAllowAuthorizer())
|
authorizers = append(authorizers, authorizerfactory.NewAlwaysAllowAuthorizer())
|
||||||
case ModeAlwaysDeny:
|
case modes.ModeAlwaysDeny:
|
||||||
authorizers = append(authorizers, authorizerfactory.NewAlwaysDenyAuthorizer())
|
authorizers = append(authorizers, authorizerfactory.NewAlwaysDenyAuthorizer())
|
||||||
case ModeABAC:
|
case modes.ModeABAC:
|
||||||
if config.PolicyFile == "" {
|
if config.PolicyFile == "" {
|
||||||
return nil, errors.New("ABAC's authorization policy file not passed")
|
return nil, errors.New("ABAC's authorization policy file not passed")
|
||||||
}
|
}
|
||||||
@ -92,7 +85,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
authorizers = append(authorizers, abacAuthorizer)
|
authorizers = append(authorizers, abacAuthorizer)
|
||||||
case ModeWebhook:
|
case modes.ModeWebhook:
|
||||||
if config.WebhookConfigFile == "" {
|
if config.WebhookConfigFile == "" {
|
||||||
return nil, errors.New("Webhook's configuration file not passed")
|
return nil, errors.New("Webhook's configuration file not passed")
|
||||||
}
|
}
|
||||||
@ -103,7 +96,7 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
authorizers = append(authorizers, webhookAuthorizer)
|
authorizers = append(authorizers, webhookAuthorizer)
|
||||||
case ModeRBAC:
|
case modes.ModeRBAC:
|
||||||
rbacAuthorizer := rbac.New(
|
rbacAuthorizer := rbac.New(
|
||||||
config.InformerFactory.Roles().Lister(),
|
config.InformerFactory.Roles().Lister(),
|
||||||
config.InformerFactory.RoleBindings().Lister(),
|
config.InformerFactory.RoleBindings().Lister(),
|
||||||
@ -117,13 +110,13 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, error) {
|
|||||||
authorizerMap[authorizationMode] = true
|
authorizerMap[authorizationMode] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !authorizerMap[ModeABAC] && config.PolicyFile != "" {
|
if !authorizerMap[modes.ModeABAC] && config.PolicyFile != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
|
return nil, errors.New("Cannot specify --authorization-policy-file without mode ABAC")
|
||||||
}
|
}
|
||||||
if !authorizerMap[ModeWebhook] && config.WebhookConfigFile != "" {
|
if !authorizerMap[modes.ModeWebhook] && config.WebhookConfigFile != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
|
return nil, errors.New("Cannot specify --authorization-webhook-config-file without mode Webhook")
|
||||||
}
|
}
|
||||||
if !authorizerMap[ModeRBAC] && config.RBACSuperUser != "" {
|
if !authorizerMap[modes.ModeRBAC] && config.RBACSuperUser != "" {
|
||||||
return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC")
|
return nil, errors.New("Cannot specify --authorization-rbac-super-user without mode RBAC")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package authorizer
|
package authorizer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,19 +40,19 @@ func TestNew(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile
|
// ModeAlwaysAllow and ModeAlwaysDeny should return without authorizationPolicyFile
|
||||||
// but error if one is given
|
// but error if one is given
|
||||||
config: AuthorizationConfig{AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny}},
|
config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny}},
|
||||||
msg: "returned an error for valid config",
|
msg: "returned an error for valid config",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeABAC requires a policy file
|
// ModeABAC requires a policy file
|
||||||
config: AuthorizationConfig{AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC}},
|
config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC}},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "specifying ABAC with no policy file should return an error",
|
msg: "specifying ABAC with no policy file should return an error",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeABAC should not error if a valid policy path is provided
|
// ModeABAC should not error if a valid policy path is provided
|
||||||
config: AuthorizationConfig{
|
config: AuthorizationConfig{
|
||||||
AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC},
|
AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny, modes.ModeABAC},
|
||||||
PolicyFile: examplePolicyFile,
|
PolicyFile: examplePolicyFile,
|
||||||
},
|
},
|
||||||
msg: "errored while using a valid policy file",
|
msg: "errored while using a valid policy file",
|
||||||
@ -60,7 +61,7 @@ func TestNew(t *testing.T) {
|
|||||||
|
|
||||||
// Authorization Policy file cannot be used without ModeABAC
|
// Authorization Policy file cannot be used without ModeABAC
|
||||||
config: AuthorizationConfig{
|
config: AuthorizationConfig{
|
||||||
AuthorizationModes: []string{ModeAlwaysAllow, ModeAlwaysDeny},
|
AuthorizationModes: []string{modes.ModeAlwaysAllow, modes.ModeAlwaysDeny},
|
||||||
PolicyFile: examplePolicyFile,
|
PolicyFile: examplePolicyFile,
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
@ -74,14 +75,14 @@ func TestNew(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ModeWebhook requires at minimum a target.
|
// ModeWebhook requires at minimum a target.
|
||||||
config: AuthorizationConfig{AuthorizationModes: []string{ModeWebhook}},
|
config: AuthorizationConfig{AuthorizationModes: []string{modes.ModeWebhook}},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
msg: "should have errored when config was empty with ModeWebhook",
|
msg: "should have errored when config was empty with ModeWebhook",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Cannot provide webhook flags without ModeWebhook
|
// Cannot provide webhook flags without ModeWebhook
|
||||||
config: AuthorizationConfig{
|
config: AuthorizationConfig{
|
||||||
AuthorizationModes: []string{ModeAlwaysAllow},
|
AuthorizationModes: []string{modes.ModeAlwaysAllow},
|
||||||
WebhookConfigFile: "authz_webhook_config.yml",
|
WebhookConfigFile: "authz_webhook_config.yml",
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
|
35
pkg/kubeapiserver/authorizer/modes/BUILD
Normal file
35
pkg/kubeapiserver/authorizer/modes/BUILD
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
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 = ["modes_test.go"],
|
||||||
|
library = ":go_default_library",
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = ["modes.go"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
)
|
37
pkg/kubeapiserver/authorizer/modes/modes.go
Normal file
37
pkg/kubeapiserver/authorizer/modes/modes.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 modes
|
||||||
|
|
||||||
|
const (
|
||||||
|
ModeAlwaysAllow string = "AlwaysAllow"
|
||||||
|
ModeAlwaysDeny string = "AlwaysDeny"
|
||||||
|
ModeABAC string = "ABAC"
|
||||||
|
ModeWebhook string = "Webhook"
|
||||||
|
ModeRBAC string = "RBAC"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AuthorizationModeChoices = []string{ModeAlwaysAllow, ModeAlwaysDeny, ModeABAC, ModeWebhook, ModeRBAC}
|
||||||
|
|
||||||
|
// IsValidAuthorizationMode returns true if the given authorization mode is a valid one for the apiserver
|
||||||
|
func IsValidAuthorizationMode(authzMode string) bool {
|
||||||
|
for _, validMode := range AuthorizationModeChoices {
|
||||||
|
if authzMode == validMode {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
45
pkg/kubeapiserver/authorizer/modes/modes_test.go
Normal file
45
pkg/kubeapiserver/authorizer/modes/modes_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 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 modes
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestIsValidAuthorizationMode(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
authzMode string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"", false},
|
||||||
|
{"rBAC", false}, // not supported
|
||||||
|
{"falsy value", false}, // not supported
|
||||||
|
{"RBAC", true}, // supported
|
||||||
|
{"ABAC", true}, // supported
|
||||||
|
{"Webhook", true}, // supported
|
||||||
|
{"AlwaysAllow", true}, // supported
|
||||||
|
{"AlwaysDeny", true}, // supported
|
||||||
|
}
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := IsValidAuthorizationMode(rt.authzMode)
|
||||||
|
if actual != rt.expected {
|
||||||
|
t.Errorf(
|
||||||
|
"failed ValidAuthorizationMode:\n\texpected: %t\n\t actual: %t",
|
||||||
|
rt.expected,
|
||||||
|
actual,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ go_library(
|
|||||||
"//pkg/controller/informers:go_default_library",
|
"//pkg/controller/informers:go_default_library",
|
||||||
"//pkg/kubeapiserver/authenticator:go_default_library",
|
"//pkg/kubeapiserver/authenticator:go_default_library",
|
||||||
"//pkg/kubeapiserver/authorizer:go_default_library",
|
"//pkg/kubeapiserver/authorizer:go_default_library",
|
||||||
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//vendor:github.com/golang/glog",
|
"//vendor:github.com/golang/glog",
|
||||||
"//vendor:github.com/spf13/pflag",
|
"//vendor:github.com/spf13/pflag",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
"//vendor:k8s.io/apimachinery/pkg/runtime/schema",
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
|
"k8s.io/kubernetes/pkg/kubeapiserver/authenticator"
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BuiltInAuthenticationOptions struct {
|
type BuiltInAuthenticationOptions struct {
|
||||||
@ -353,7 +353,7 @@ func (o *BuiltInAuthenticationOptions) ApplyAuthorization(authorization *BuiltIn
|
|||||||
if o.Anonymous.Allow {
|
if o.Anonymous.Allow {
|
||||||
found := false
|
found := false
|
||||||
for _, mode := range strings.Split(authorization.Mode, ",") {
|
for _, mode := range strings.Split(authorization.Mode, ",") {
|
||||||
if mode == authorizer.ModeAlwaysAllow {
|
if mode == authzmodes.ModeAlwaysAllow {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,9 @@ import (
|
|||||||
|
|
||||||
"k8s.io/kubernetes/pkg/controller/informers"
|
"k8s.io/kubernetes/pkg/controller/informers"
|
||||||
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer"
|
||||||
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
)
|
)
|
||||||
|
|
||||||
var AuthorizationModeChoices = []string{authorizer.ModeAlwaysAllow, authorizer.ModeAlwaysDeny, authorizer.ModeABAC, authorizer.ModeWebhook, authorizer.ModeRBAC}
|
|
||||||
|
|
||||||
type BuiltInAuthorizationOptions struct {
|
type BuiltInAuthorizationOptions struct {
|
||||||
Mode string
|
Mode string
|
||||||
PolicyFile string
|
PolicyFile string
|
||||||
@ -38,7 +37,7 @@ type BuiltInAuthorizationOptions struct {
|
|||||||
|
|
||||||
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
|
func NewBuiltInAuthorizationOptions() *BuiltInAuthorizationOptions {
|
||||||
return &BuiltInAuthorizationOptions{
|
return &BuiltInAuthorizationOptions{
|
||||||
Mode: authorizer.ModeAlwaysAllow,
|
Mode: authzmodes.ModeAlwaysAllow,
|
||||||
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
WebhookCacheAuthorizedTTL: 5 * time.Minute,
|
||||||
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
WebhookCacheUnauthorizedTTL: 30 * time.Second,
|
||||||
}
|
}
|
||||||
@ -52,7 +51,7 @@ func (s *BuiltInAuthorizationOptions) Validate() []error {
|
|||||||
func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
|
||||||
fs.StringVar(&s.Mode, "authorization-mode", s.Mode, ""+
|
fs.StringVar(&s.Mode, "authorization-mode", s.Mode, ""+
|
||||||
"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. Comma-delimited list of: "+
|
||||||
strings.Join(AuthorizationModeChoices, ",")+".")
|
strings.Join(authzmodes.AuthorizationModeChoices, ",")+".")
|
||||||
|
|
||||||
fs.StringVar(&s.PolicyFile, "authorization-policy-file", s.PolicyFile, ""+
|
fs.StringVar(&s.PolicyFile, "authorization-policy-file", s.PolicyFile, ""+
|
||||||
"File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")
|
"File with authorization policy in csv format, used with --authorization-mode=ABAC, on the secure port.")
|
||||||
|
Loading…
Reference in New Issue
Block a user