mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Convert user/group * to match authenticated users only in ABAC
This commit is contained in:
parent
034571ce3c
commit
742ef34484
@ -75,6 +75,7 @@ pkg/api/v1
|
||||
pkg/api/v1/service
|
||||
pkg/apimachinery
|
||||
pkg/apis/abac/v0
|
||||
pkg/apis/abac/v1beta1
|
||||
pkg/apis/apps/install
|
||||
pkg/apis/authentication.k8s.io/install
|
||||
pkg/apis/authentication/install
|
||||
|
@ -19,6 +19,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/abac:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/auth/user:go_default_library",
|
||||
"//pkg/conversion:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
@ -32,5 +33,6 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/apis/abac:go_default_library",
|
||||
"//pkg/apis/abac/v0:go_default_library",
|
||||
"//pkg/auth/user:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -18,6 +18,7 @@ package v0
|
||||
|
||||
import (
|
||||
api "k8s.io/kubernetes/pkg/apis/abac"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
@ -32,9 +33,14 @@ func addConversionFuncs(scheme *runtime.Scheme) error {
|
||||
out.Spec.Resource = in.Resource
|
||||
out.Spec.Readonly = in.Readonly
|
||||
|
||||
// In v0, unspecified user and group matches all subjects
|
||||
// In v0, unspecified user and group matches all authenticated subjects
|
||||
if len(in.User) == 0 && len(in.Group) == 0 {
|
||||
out.Spec.User = "*"
|
||||
out.Spec.Group = user.AllAuthenticated
|
||||
}
|
||||
// In v0, user or group of * matches all authenticated subjects
|
||||
if in.User == "*" || in.Group == "*" {
|
||||
out.Spec.Group = user.AllAuthenticated
|
||||
out.Spec.User = ""
|
||||
}
|
||||
|
||||
// In v0, leaving namespace empty matches all namespaces
|
||||
|
@ -22,9 +22,10 @@ import (
|
||||
|
||||
api "k8s.io/kubernetes/pkg/apis/abac"
|
||||
"k8s.io/kubernetes/pkg/apis/abac/v0"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
)
|
||||
|
||||
func TestConversion(t *testing.T) {
|
||||
func TestV0Conversion(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
old *v0.Policy
|
||||
expected *api.Policy
|
||||
@ -32,7 +33,7 @@ func TestConversion(t *testing.T) {
|
||||
// a completely empty policy rule allows everything to all users
|
||||
"empty": {
|
||||
old: &v0.Policy{},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{User: "*", Readonly: false, NonResourcePath: "*", Namespace: "*", Resource: "*", APIGroup: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "*", Namespace: "*", Resource: "*", APIGroup: "*"}},
|
||||
},
|
||||
|
||||
// specifying a user is preserved
|
||||
@ -47,22 +48,32 @@ func TestConversion(t *testing.T) {
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: "mygroup", Readonly: false, NonResourcePath: "*", Namespace: "*", Resource: "*", APIGroup: "*"}},
|
||||
},
|
||||
|
||||
// specifying * for user or group maps to all authenticated subjects
|
||||
"* user": {
|
||||
old: &v0.Policy{User: "*"},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "*", Namespace: "*", Resource: "*", APIGroup: "*"}},
|
||||
},
|
||||
"* group": {
|
||||
old: &v0.Policy{Group: "*"},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "*", Namespace: "*", Resource: "*", APIGroup: "*"}},
|
||||
},
|
||||
|
||||
// specifying a namespace removes the * match on non-resource path
|
||||
"namespace": {
|
||||
old: &v0.Policy{Namespace: "myns"},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{User: "*", Readonly: false, NonResourcePath: "", Namespace: "myns", Resource: "*", APIGroup: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "", Namespace: "myns", Resource: "*", APIGroup: "*"}},
|
||||
},
|
||||
|
||||
// specifying a resource removes the * match on non-resource path
|
||||
"resource": {
|
||||
old: &v0.Policy{Resource: "myresource"},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{User: "*", Readonly: false, NonResourcePath: "", Namespace: "*", Resource: "myresource", APIGroup: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "", Namespace: "*", Resource: "myresource", APIGroup: "*"}},
|
||||
},
|
||||
|
||||
// specifying a namespace+resource removes the * match on non-resource path
|
||||
"namespace+resource": {
|
||||
old: &v0.Policy{Namespace: "myns", Resource: "myresource"},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{User: "*", Readonly: false, NonResourcePath: "", Namespace: "myns", Resource: "myresource", APIGroup: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated, Readonly: false, NonResourcePath: "", Namespace: "myns", Resource: "myresource", APIGroup: "*"}},
|
||||
},
|
||||
}
|
||||
for k, tc := range testcases {
|
||||
|
@ -5,19 +5,37 @@ licenses(["notice"])
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"conversion.go",
|
||||
"doc.go",
|
||||
"register.go",
|
||||
"types.go",
|
||||
"zz_generated.conversion.go",
|
||||
"zz_generated.deepcopy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/abac:go_default_library",
|
||||
"//pkg/apis/meta/v1:go_default_library",
|
||||
"//pkg/auth/user:go_default_library",
|
||||
"//pkg/conversion:go_default_library",
|
||||
"//pkg/runtime:go_default_library",
|
||||
"//pkg/runtime/schema:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = ["conversion_test.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/abac:go_default_library",
|
||||
"//pkg/apis/abac/v1beta1:go_default_library",
|
||||
"//pkg/auth/user:go_default_library",
|
||||
],
|
||||
)
|
||||
|
43
pkg/apis/abac/v1beta1/conversion.go
Normal file
43
pkg/apis/abac/v1beta1/conversion.go
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
api "k8s.io/kubernetes/pkg/apis/abac"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
"k8s.io/kubernetes/pkg/conversion"
|
||||
"k8s.io/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) error {
|
||||
return scheme.AddConversionFuncs(
|
||||
func(in *Policy, out *api.Policy, s conversion.Scope) error {
|
||||
// Begin by copying all fields
|
||||
if err := autoConvert_v1beta1_Policy_To_abac_Policy(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// In v1beta1, * user or group maps to all authenticated subjects
|
||||
if in.Spec.User == "*" || in.Spec.Group == "*" {
|
||||
out.Spec.Group = user.AllAuthenticated
|
||||
out.Spec.User = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
64
pkg/apis/abac/v1beta1/conversion_test.go
Normal file
64
pkg/apis/abac/v1beta1/conversion_test.go
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 v1beta1_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
api "k8s.io/kubernetes/pkg/apis/abac"
|
||||
"k8s.io/kubernetes/pkg/apis/abac/v1beta1"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
)
|
||||
|
||||
func TestV1Beta1Conversion(t *testing.T) {
|
||||
testcases := map[string]struct {
|
||||
old *v1beta1.Policy
|
||||
expected *api.Policy
|
||||
}{
|
||||
// specifying a user is preserved
|
||||
"user": {
|
||||
old: &v1beta1.Policy{Spec: v1beta1.PolicySpec{User: "bob"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{User: "bob"}},
|
||||
},
|
||||
|
||||
// specifying a group is preserved
|
||||
"group": {
|
||||
old: &v1beta1.Policy{Spec: v1beta1.PolicySpec{Group: "mygroup"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: "mygroup"}},
|
||||
},
|
||||
|
||||
// specifying * for user or group maps to all authenticated subjects
|
||||
"* user": {
|
||||
old: &v1beta1.Policy{Spec: v1beta1.PolicySpec{User: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated}},
|
||||
},
|
||||
"* group": {
|
||||
old: &v1beta1.Policy{Spec: v1beta1.PolicySpec{Group: "*"}},
|
||||
expected: &api.Policy{Spec: api.PolicySpec{Group: user.AllAuthenticated}},
|
||||
},
|
||||
}
|
||||
for k, tc := range testcases {
|
||||
internal := &api.Policy{}
|
||||
if err := api.Scheme.Convert(tc.old, internal, nil); err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", k, err)
|
||||
}
|
||||
if !reflect.DeepEqual(internal, tc.expected) {
|
||||
t.Errorf("%s: expected\n\t%#v, got \n\t%#v", k, tc.expected, internal)
|
||||
}
|
||||
}
|
||||
}
|
@ -33,10 +33,14 @@ func init() {
|
||||
// Programmer error.
|
||||
panic(err)
|
||||
}
|
||||
if err := addConversionFuncs(api.Scheme); err != nil {
|
||||
// Programmer error.
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addConversionFuncs)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
|
@ -73,9 +73,11 @@ func TestAuthorizeV0(t *testing.T) {
|
||||
t.Fatalf("unable to read policy file: %v", err)
|
||||
}
|
||||
|
||||
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1"}
|
||||
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3"}
|
||||
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5"}
|
||||
authenticatedGroup := []string{user.AllAuthenticated}
|
||||
|
||||
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup}
|
||||
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
|
||||
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
|
||||
|
||||
testCases := []struct {
|
||||
User user.DefaultInfo
|
||||
@ -163,12 +165,14 @@ func TestAuthorizeV1beta1(t *testing.T) {
|
||||
t.Fatalf("unable to read policy file: %v", err)
|
||||
}
|
||||
|
||||
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1"}
|
||||
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3"}
|
||||
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5"}
|
||||
uDebbie := user.DefaultInfo{Name: "debbie", UID: "uid6"}
|
||||
uNoResource := user.DefaultInfo{Name: "noresource", UID: "uid7"}
|
||||
uAPIGroup := user.DefaultInfo{Name: "apigroupuser", UID: "uid8"}
|
||||
authenticatedGroup := []string{user.AllAuthenticated}
|
||||
|
||||
uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup}
|
||||
uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup}
|
||||
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
|
||||
uDebbie := user.DefaultInfo{Name: "debbie", UID: "uid6", Groups: authenticatedGroup}
|
||||
uNoResource := user.DefaultInfo{Name: "noresource", UID: "uid7", Groups: authenticatedGroup}
|
||||
uAPIGroup := user.DefaultInfo{Name: "apigroupuser", UID: "uid8", Groups: authenticatedGroup}
|
||||
|
||||
testCases := []struct {
|
||||
User user.DefaultInfo
|
||||
@ -263,16 +267,32 @@ func TestSubjectMatches(t *testing.T) {
|
||||
Policy runtime.Object
|
||||
ExpectMatch bool
|
||||
}{
|
||||
"v0 empty policy matches unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
"v0 empty policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "",
|
||||
},
|
||||
ExpectMatch: true,
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 * user policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v0.Policy{
|
||||
User: "*",
|
||||
Group: "",
|
||||
},
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 * group policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "*",
|
||||
},
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 empty policy matches authed user": {
|
||||
User: user.DefaultInfo{Name: "Foo"},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "",
|
||||
@ -280,7 +300,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: true,
|
||||
},
|
||||
"v0 empty policy matches authed user with groups": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "",
|
||||
@ -289,7 +309,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v0 user policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "",
|
||||
@ -297,7 +317,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user policy does not match different user": {
|
||||
User: user.DefaultInfo{Name: "Bar"},
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "",
|
||||
@ -305,7 +325,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user policy is case-sensitive": {
|
||||
User: user.DefaultInfo{Name: "foo"},
|
||||
User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "",
|
||||
@ -313,7 +333,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user policy does not match substring": {
|
||||
User: user.DefaultInfo{Name: "FooBar"},
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "",
|
||||
@ -321,7 +341,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user policy matches username": {
|
||||
User: user.DefaultInfo{Name: "Foo"},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "",
|
||||
@ -330,7 +350,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v0 group policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "Foo",
|
||||
@ -338,7 +358,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 group policy does not match user in different group": {
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B"}},
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "A",
|
||||
@ -346,7 +366,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 group policy is case-sensitive": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "b",
|
||||
@ -354,7 +374,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 group policy does not match substring": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "B",
|
||||
@ -362,7 +382,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 group policy matches user in group": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "",
|
||||
Group: "B",
|
||||
@ -371,7 +391,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v0 user and group policy requires user match": {
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "B",
|
||||
@ -379,7 +399,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user and group policy requires group match": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "D",
|
||||
@ -387,7 +407,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v0 user and group policy matches": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v0.Policy{
|
||||
User: "Foo",
|
||||
Group: "B",
|
||||
@ -396,7 +416,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v1 empty policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -405,8 +425,28 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 * user policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "*",
|
||||
Group: "",
|
||||
},
|
||||
},
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 * group policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
Group: "*",
|
||||
},
|
||||
},
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 empty policy does not match authed user": {
|
||||
User: user.DefaultInfo{Name: "Foo"},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -416,7 +456,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 empty policy does not match authed user with groups": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -427,7 +467,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v1 user policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -437,7 +477,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user policy does not match different user": {
|
||||
User: user.DefaultInfo{Name: "Bar"},
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -447,7 +487,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user policy is case-sensitive": {
|
||||
User: user.DefaultInfo{Name: "foo"},
|
||||
User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -457,7 +497,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user policy does not match substring": {
|
||||
User: user.DefaultInfo{Name: "FooBar"},
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -467,7 +507,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user policy matches username": {
|
||||
User: user.DefaultInfo{Name: "Foo"},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -478,7 +518,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v1 group policy does not match unauthed user": {
|
||||
User: user.DefaultInfo{},
|
||||
User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -488,7 +528,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 group policy does not match user in different group": {
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B"}},
|
||||
User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -498,7 +538,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 group policy is case-sensitive": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -508,7 +548,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 group policy does not match substring": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -518,7 +558,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 group policy matches user in group": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "",
|
||||
@ -529,7 +569,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
},
|
||||
|
||||
"v1 user and group policy requires user match": {
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -539,7 +579,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user and group policy requires group match": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -549,7 +589,7 @@ func TestSubjectMatches(t *testing.T) {
|
||||
ExpectMatch: false,
|
||||
},
|
||||
"v1 user and group policy matches": {
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C"}},
|
||||
User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}},
|
||||
Policy: &v1beta1.Policy{
|
||||
Spec: v1beta1.PolicySpec{
|
||||
User: "Foo",
|
||||
@ -600,20 +640,18 @@ func TestPolicy(t *testing.T) {
|
||||
matches bool
|
||||
name string
|
||||
}{
|
||||
// v0
|
||||
{
|
||||
policy: &v0.Policy{},
|
||||
attr: authorizer.AttributesRecord{},
|
||||
matches: true,
|
||||
name: "v0 null",
|
||||
},
|
||||
|
||||
// v0 mismatches
|
||||
{
|
||||
policy: &v0.Policy{
|
||||
Readonly: true,
|
||||
},
|
||||
attr: authorizer.AttributesRecord{},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Verb: "create",
|
||||
},
|
||||
matches: false,
|
||||
name: "v0 read-only mismatch",
|
||||
},
|
||||
@ -623,7 +661,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "bar",
|
||||
Name: "bar",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
},
|
||||
matches: false,
|
||||
@ -634,6 +673,10 @@ func TestPolicy(t *testing.T) {
|
||||
Resource: "foo",
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Resource: "bar",
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -648,7 +691,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Resource: "foo",
|
||||
Namespace: "foo",
|
||||
@ -660,8 +704,14 @@ func TestPolicy(t *testing.T) {
|
||||
|
||||
// v0 matches
|
||||
{
|
||||
policy: &v0.Policy{},
|
||||
attr: authorizer.AttributesRecord{ResourceRequest: true},
|
||||
policy: &v0.Policy{},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
matches: true,
|
||||
name: "v0 null resource",
|
||||
},
|
||||
@ -670,6 +720,10 @@ func TestPolicy(t *testing.T) {
|
||||
Readonly: true,
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Verb: "get",
|
||||
},
|
||||
matches: true,
|
||||
@ -681,7 +735,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
},
|
||||
matches: true,
|
||||
@ -692,6 +747,10 @@ func TestPolicy(t *testing.T) {
|
||||
Resource: "foo",
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Resource: "foo",
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -703,6 +762,10 @@ func TestPolicy(t *testing.T) {
|
||||
{
|
||||
policy: &v1beta1.Policy{},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
matches: false,
|
||||
@ -716,7 +779,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "bar",
|
||||
Name: "bar",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -731,6 +795,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
matches: false,
|
||||
@ -744,6 +812,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Resource: "bar",
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -760,7 +832,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Namespace: "bar",
|
||||
Resource: "baz",
|
||||
@ -777,6 +850,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Path: "/api2",
|
||||
ResourceRequest: false,
|
||||
},
|
||||
@ -791,6 +868,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Path: "/api2/foo",
|
||||
ResourceRequest: false,
|
||||
},
|
||||
@ -807,7 +888,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -821,6 +903,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
matches: true,
|
||||
@ -835,7 +921,7 @@ func TestPolicy(t *testing.T) {
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{"bar"},
|
||||
Groups: []string{"bar", user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -851,7 +937,7 @@ func TestPolicy(t *testing.T) {
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{"bar"},
|
||||
Groups: []string{"bar", user.AllAuthenticated},
|
||||
},
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -866,6 +952,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Verb: "get",
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -880,6 +970,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Resource: "foo",
|
||||
ResourceRequest: true,
|
||||
},
|
||||
@ -896,7 +990,8 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Namespace: "bar",
|
||||
Resource: "baz",
|
||||
@ -913,6 +1008,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Path: "/api",
|
||||
ResourceRequest: false,
|
||||
},
|
||||
@ -927,6 +1026,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Path: "/api",
|
||||
ResourceRequest: false,
|
||||
},
|
||||
@ -941,6 +1044,10 @@ func TestPolicy(t *testing.T) {
|
||||
},
|
||||
},
|
||||
attr: authorizer.AttributesRecord{
|
||||
User: &user.DefaultInfo{
|
||||
Name: "foo",
|
||||
Groups: []string{user.AllAuthenticated},
|
||||
},
|
||||
Path: "/api/foo",
|
||||
ResourceRequest: false,
|
||||
},
|
||||
|
@ -1,4 +1,5 @@
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"*", "nonResourcePath": "*", "readonly": true}}
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group":"system:authenticated", "nonResourcePath": "*", "readonly": true}}
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"system:unauthenticated", "nonResourcePath": "*", "readonly": true}}
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"admin", "namespace": "*", "resource": "*", "apiGroup": "*" }}
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"scheduler", "namespace": "*", "resource": "pods", "readonly": true }}
|
||||
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"scheduler", "namespace": "*", "resource": "bindings" }}
|
||||
|
@ -46,6 +46,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer"
|
||||
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
|
||||
"k8s.io/kubernetes/pkg/auth/group"
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1"
|
||||
apiserverauthorizer "k8s.io/kubernetes/pkg/genericapiserver/authorizer"
|
||||
@ -67,7 +68,7 @@ func getTestTokenAuth() authenticator.Request {
|
||||
tokenAuthenticator := tokentest.New()
|
||||
tokenAuthenticator.Tokens[AliceToken] = &user.DefaultInfo{Name: "alice", UID: "1"}
|
||||
tokenAuthenticator.Tokens[BobToken] = &user.DefaultInfo{Name: "bob", UID: "2"}
|
||||
return bearertoken.New(tokenAuthenticator)
|
||||
return group.NewGroupAdder(bearertoken.New(tokenAuthenticator), []string{user.AllAuthenticated})
|
||||
}
|
||||
|
||||
func getTestWebhookTokenAuth(serverURL string) (authenticator.Request, error) {
|
||||
|
@ -559,6 +559,7 @@ k8s.io/kubernetes/pkg/apimachinery,gmarek,1
|
||||
k8s.io/kubernetes/pkg/apimachinery/announced,kargakis,1
|
||||
k8s.io/kubernetes/pkg/apimachinery/registered,jlowdermilk,1
|
||||
k8s.io/kubernetes/pkg/apis/abac/v0,liggitt,0
|
||||
k8s.io/kubernetes/pkg/apis/abac/v1beta1,liggitt,0
|
||||
k8s.io/kubernetes/pkg/apis/apps/validation,derekwaynecarr,1
|
||||
k8s.io/kubernetes/pkg/apis/authorization/validation,erictune,0
|
||||
k8s.io/kubernetes/pkg/apis/autoscaling/v1,yarntime,0
|
||||
|
|
Loading…
Reference in New Issue
Block a user