Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
6014ace9
Commit
6014ace9
authored
Oct 07, 2018
by
Darren Shepherd
Committed by
Erik Wilson
Aug 05, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove ABAC
parent
afa0802f
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1 addition
and
1641 deletions
+1
-1641
BUILD
pkg/auth/authorizer/abac/BUILD
+0
-60
abac.go
pkg/auth/authorizer/abac/abac.go
+0
-273
abac_test.go
pkg/auth/authorizer/abac/abac_test.go
+0
-1268
example_policy_file.jsonl
pkg/auth/authorizer/abac/example_policy_file.jsonl
+0
-12
config.go
pkg/kubeapiserver/authorizer/config.go
+0
-11
modes.go
pkg/kubeapiserver/authorizer/modes/modes.go
+1
-3
authorization.go
pkg/kubeapiserver/options/authorization.go
+0
-14
No files found.
pkg/auth/authorizer/abac/BUILD
deleted
100644 → 0
View file @
afa0802f
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = ["abac.go"],
importpath = "k8s.io/kubernetes/pkg/auth/authorizer/abac",
deps = [
"//pkg/apis/abac:go_default_library",
"//pkg/apis/abac/latest:go_default_library",
"//pkg/apis/abac/v0:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],
)
filegroup(
name = "example_policy",
testonly = True,
srcs = [
"example_policy_file.jsonl",
],
)
go_test(
name = "go_default_test",
srcs = ["abac_test.go"],
data = [
":example_policy",
],
embed = [":go_default_library"],
deps = [
"//pkg/apis/abac:go_default_library",
"//pkg/apis/abac/v0:go_default_library",
"//pkg/apis/abac/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
pkg/auth/authorizer/abac/abac.go
deleted
100644 → 0
View file @
afa0802f
/*
Copyright 2014 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
abac
// Policy authorizes Kubernetes API actions using an Attribute-based access
// control scheme.
import
(
"bufio"
"fmt"
"os"
"strings"
"k8s.io/klog"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/kubernetes/pkg/apis/abac"
_
"k8s.io/kubernetes/pkg/apis/abac/latest"
"k8s.io/kubernetes/pkg/apis/abac/v0"
)
type
policyLoadError
struct
{
path
string
line
int
data
[]
byte
err
error
}
func
(
p
policyLoadError
)
Error
()
string
{
if
p
.
line
>=
0
{
return
fmt
.
Sprintf
(
"error reading policy file %s, line %d: %s: %v"
,
p
.
path
,
p
.
line
,
string
(
p
.
data
),
p
.
err
)
}
return
fmt
.
Sprintf
(
"error reading policy file %s: %v"
,
p
.
path
,
p
.
err
)
}
type
policyList
[]
*
abac
.
Policy
// TODO: Have policies be created via an API call and stored in REST storage.
func
NewFromFile
(
path
string
)
(
policyList
,
error
)
{
// File format is one map per line. This allows easy concatenation of files,
// comments in files, and identification of errors by line number.
file
,
err
:=
os
.
Open
(
path
)
if
err
!=
nil
{
return
nil
,
err
}
defer
file
.
Close
()
scanner
:=
bufio
.
NewScanner
(
file
)
pl
:=
make
(
policyList
,
0
)
decoder
:=
abac
.
Codecs
.
UniversalDecoder
()
i
:=
0
unversionedLines
:=
0
for
scanner
.
Scan
()
{
i
++
p
:=
&
abac
.
Policy
{}
b
:=
scanner
.
Bytes
()
// skip comment lines and blank lines
trimmed
:=
strings
.
TrimSpace
(
string
(
b
))
if
len
(
trimmed
)
==
0
||
strings
.
HasPrefix
(
trimmed
,
"#"
)
{
continue
}
decodedObj
,
_
,
err
:=
decoder
.
Decode
(
b
,
nil
,
nil
)
if
err
!=
nil
{
if
!
(
runtime
.
IsMissingVersion
(
err
)
||
runtime
.
IsMissingKind
(
err
)
||
runtime
.
IsNotRegisteredError
(
err
))
{
return
nil
,
policyLoadError
{
path
,
i
,
b
,
err
}
}
unversionedLines
++
// Migrate unversioned policy object
oldPolicy
:=
&
v0
.
Policy
{}
if
err
:=
runtime
.
DecodeInto
(
decoder
,
b
,
oldPolicy
);
err
!=
nil
{
return
nil
,
policyLoadError
{
path
,
i
,
b
,
err
}
}
if
err
:=
abac
.
Scheme
.
Convert
(
oldPolicy
,
p
,
nil
);
err
!=
nil
{
return
nil
,
policyLoadError
{
path
,
i
,
b
,
err
}
}
pl
=
append
(
pl
,
p
)
continue
}
decodedPolicy
,
ok
:=
decodedObj
.
(
*
abac
.
Policy
)
if
!
ok
{
return
nil
,
policyLoadError
{
path
,
i
,
b
,
fmt
.
Errorf
(
"unrecognized object: %#v"
,
decodedObj
)}
}
pl
=
append
(
pl
,
decodedPolicy
)
}
if
unversionedLines
>
0
{
klog
.
Warningf
(
"Policy file %s contained unversioned rules. See docs/admin/authorization.md#abac-mode for ABAC file format details."
,
path
)
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
return
nil
,
policyLoadError
{
path
,
-
1
,
nil
,
err
}
}
return
pl
,
nil
}
func
matches
(
p
abac
.
Policy
,
a
authorizer
.
Attributes
)
bool
{
if
subjectMatches
(
p
,
a
.
GetUser
())
{
if
verbMatches
(
p
,
a
)
{
// Resource and non-resource requests are mutually exclusive, at most one will match a policy
if
resourceMatches
(
p
,
a
)
{
return
true
}
if
nonResourceMatches
(
p
,
a
)
{
return
true
}
}
}
return
false
}
// subjectMatches returns true if specified user and group properties in the policy match the attributes
func
subjectMatches
(
p
abac
.
Policy
,
user
user
.
Info
)
bool
{
matched
:=
false
if
user
==
nil
{
return
false
}
username
:=
user
.
GetName
()
groups
:=
user
.
GetGroups
()
// If the policy specified a user, ensure it matches
if
len
(
p
.
Spec
.
User
)
>
0
{
if
p
.
Spec
.
User
==
"*"
{
matched
=
true
}
else
{
matched
=
p
.
Spec
.
User
==
username
if
!
matched
{
return
false
}
}
}
// If the policy specified a group, ensure it matches
if
len
(
p
.
Spec
.
Group
)
>
0
{
if
p
.
Spec
.
Group
==
"*"
{
matched
=
true
}
else
{
matched
=
false
for
_
,
group
:=
range
groups
{
if
p
.
Spec
.
Group
==
group
{
matched
=
true
}
}
if
!
matched
{
return
false
}
}
}
return
matched
}
func
verbMatches
(
p
abac
.
Policy
,
a
authorizer
.
Attributes
)
bool
{
// TODO: match on verb
// All policies allow read only requests
if
a
.
IsReadOnly
()
{
return
true
}
// Allow if policy is not readonly
if
!
p
.
Spec
.
Readonly
{
return
true
}
return
false
}
func
nonResourceMatches
(
p
abac
.
Policy
,
a
authorizer
.
Attributes
)
bool
{
// A non-resource policy cannot match a resource request
if
!
a
.
IsResourceRequest
()
{
// Allow wildcard match
if
p
.
Spec
.
NonResourcePath
==
"*"
{
return
true
}
// Allow exact match
if
p
.
Spec
.
NonResourcePath
==
a
.
GetPath
()
{
return
true
}
// Allow a trailing * subpath match
if
strings
.
HasSuffix
(
p
.
Spec
.
NonResourcePath
,
"*"
)
&&
strings
.
HasPrefix
(
a
.
GetPath
(),
strings
.
TrimRight
(
p
.
Spec
.
NonResourcePath
,
"*"
))
{
return
true
}
}
return
false
}
func
resourceMatches
(
p
abac
.
Policy
,
a
authorizer
.
Attributes
)
bool
{
// A resource policy cannot match a non-resource request
if
a
.
IsResourceRequest
()
{
if
p
.
Spec
.
Namespace
==
"*"
||
p
.
Spec
.
Namespace
==
a
.
GetNamespace
()
{
if
p
.
Spec
.
Resource
==
"*"
||
p
.
Spec
.
Resource
==
a
.
GetResource
()
{
if
p
.
Spec
.
APIGroup
==
"*"
||
p
.
Spec
.
APIGroup
==
a
.
GetAPIGroup
()
{
return
true
}
}
}
}
return
false
}
// Authorizer implements authorizer.Authorize
func
(
pl
policyList
)
Authorize
(
a
authorizer
.
Attributes
)
(
authorizer
.
Decision
,
string
,
error
)
{
for
_
,
p
:=
range
pl
{
if
matches
(
*
p
,
a
)
{
return
authorizer
.
DecisionAllow
,
""
,
nil
}
}
return
authorizer
.
DecisionNoOpinion
,
"No policy matched."
,
nil
// TODO: Benchmark how much time policy matching takes with a medium size
// policy file, compared to other steps such as encoding/decoding.
// Then, add Caching only if needed.
}
func
(
pl
policyList
)
RulesFor
(
user
user
.
Info
,
namespace
string
)
([]
authorizer
.
ResourceRuleInfo
,
[]
authorizer
.
NonResourceRuleInfo
,
bool
,
error
)
{
var
(
resourceRules
[]
authorizer
.
ResourceRuleInfo
nonResourceRules
[]
authorizer
.
NonResourceRuleInfo
)
for
_
,
p
:=
range
pl
{
if
subjectMatches
(
*
p
,
user
)
{
if
p
.
Spec
.
Namespace
==
"*"
||
p
.
Spec
.
Namespace
==
namespace
{
if
len
(
p
.
Spec
.
Resource
)
>
0
{
r
:=
authorizer
.
DefaultResourceRuleInfo
{
Verbs
:
getVerbs
(
p
.
Spec
.
Readonly
),
APIGroups
:
[]
string
{
p
.
Spec
.
APIGroup
},
Resources
:
[]
string
{
p
.
Spec
.
Resource
},
}
var
resourceRule
authorizer
.
ResourceRuleInfo
=
&
r
resourceRules
=
append
(
resourceRules
,
resourceRule
)
}
if
len
(
p
.
Spec
.
NonResourcePath
)
>
0
{
r
:=
authorizer
.
DefaultNonResourceRuleInfo
{
Verbs
:
getVerbs
(
p
.
Spec
.
Readonly
),
NonResourceURLs
:
[]
string
{
p
.
Spec
.
NonResourcePath
},
}
var
nonResourceRule
authorizer
.
NonResourceRuleInfo
=
&
r
nonResourceRules
=
append
(
nonResourceRules
,
nonResourceRule
)
}
}
}
}
return
resourceRules
,
nonResourceRules
,
false
,
nil
}
func
getVerbs
(
isReadOnly
bool
)
[]
string
{
if
isReadOnly
{
return
[]
string
{
"get"
,
"list"
,
"watch"
}
}
return
[]
string
{
"*"
}
}
pkg/auth/authorizer/abac/abac_test.go
deleted
100644 → 0
View file @
afa0802f
/*
Copyright 2014 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
abac
import
(
"io/ioutil"
"os"
"reflect"
"testing"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/kubernetes/pkg/apis/abac"
"k8s.io/kubernetes/pkg/apis/abac/v0"
"k8s.io/kubernetes/pkg/apis/abac/v1beta1"
)
func
TestEmptyFile
(
t
*
testing
.
T
)
{
_
,
err
:=
newWithContents
(
t
,
""
)
if
err
!=
nil
{
t
.
Errorf
(
"unable to read policy file: %v"
,
err
)
}
}
func
TestOneLineFileNoNewLine
(
t
*
testing
.
T
)
{
_
,
err
:=
newWithContents
(
t
,
`{"user":"scheduler", "readonly": true, "resource": "pods", "namespace":"ns1"}`
)
if
err
!=
nil
{
t
.
Errorf
(
"unable to read policy file: %v"
,
err
)
}
}
func
TestTwoLineFile
(
t
*
testing
.
T
)
{
_
,
err
:=
newWithContents
(
t
,
`{"user":"scheduler", "readonly": true, "resource": "pods"}
{"user":"scheduler", "readonly": true, "resource": "services"}
`
)
if
err
!=
nil
{
t
.
Errorf
(
"unable to read policy file: %v"
,
err
)
}
}
// Test the file that we will point users at as an example.
func
TestExampleFile
(
t
*
testing
.
T
)
{
_
,
err
:=
NewFromFile
(
"./example_policy_file.jsonl"
)
if
err
!=
nil
{
t
.
Errorf
(
"unable to read policy file: %v"
,
err
)
}
}
func
TestAuthorizeV0
(
t
*
testing
.
T
)
{
a
,
err
:=
newWithContents
(
t
,
`{ "readonly": true, "resource": "events" }
{"user":"scheduler", "readonly": true, "resource": "pods" }
{"user":"scheduler", "resource": "bindings" }
{"user":"kubelet", "readonly": true, "resource": "bindings" }
{"user":"kubelet", "resource": "events" }
{"user":"alice", "namespace": "projectCaribou"}
{"user":"bob", "readonly": true, "namespace": "projectCaribou"}
`
)
if
err
!=
nil
{
t
.
Fatalf
(
"unable to read policy file: %v"
,
err
)
}
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
Verb
string
Resource
string
NS
string
APIGroup
string
Path
string
ExpectDecision
authorizer
.
Decision
}{
// Scheduler can read pods
{
User
:
uScheduler
,
Verb
:
"list"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uScheduler
,
Verb
:
"list"
,
Resource
:
"pods"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Scheduler cannot write pods
{
User
:
uScheduler
,
Verb
:
"create"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uScheduler
,
Verb
:
"create"
,
Resource
:
"pods"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Scheduler can write bindings
{
User
:
uScheduler
,
Verb
:
"get"
,
Resource
:
"bindings"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uScheduler
,
Verb
:
"get"
,
Resource
:
"bindings"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Alice can read and write anything in the right namespace.
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"widgets"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
""
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
"pods"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
"widgets"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
""
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
"foo"
,
NS
:
"projectCaribou"
,
APIGroup
:
"bar"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// .. but not the wrong namespace.
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"widgets"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
""
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Chuck can read events, since anyone can.
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"events"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"events"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Chuck can't do other things.
{
User
:
uChuck
,
Verb
:
"update"
,
Resource
:
"events"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"floop"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Chunk can't access things with no kind or namespace
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
}
for
i
,
tc
:=
range
testCases
{
attr
:=
authorizer
.
AttributesRecord
{
User
:
&
tc
.
User
,
Verb
:
tc
.
Verb
,
Resource
:
tc
.
Resource
,
Namespace
:
tc
.
NS
,
APIGroup
:
tc
.
APIGroup
,
Path
:
tc
.
Path
,
ResourceRequest
:
len
(
tc
.
NS
)
>
0
||
len
(
tc
.
Resource
)
>
0
,
}
decision
,
_
,
_
:=
a
.
Authorize
(
attr
)
if
tc
.
ExpectDecision
!=
decision
{
t
.
Logf
(
"tc: %v -> attr %v"
,
tc
,
attr
)
t
.
Errorf
(
"%d: Expected allowed=%v but actually allowed=%v
\n\t
%v"
,
i
,
tc
.
ExpectDecision
,
decision
,
tc
)
}
}
}
func
getResourceRules
(
infos
[]
authorizer
.
ResourceRuleInfo
)
[]
authorizer
.
DefaultResourceRuleInfo
{
rules
:=
make
([]
authorizer
.
DefaultResourceRuleInfo
,
len
(
infos
))
for
i
,
info
:=
range
infos
{
rules
[
i
]
=
authorizer
.
DefaultResourceRuleInfo
{
Verbs
:
info
.
GetVerbs
(),
APIGroups
:
info
.
GetAPIGroups
(),
Resources
:
info
.
GetResources
(),
ResourceNames
:
info
.
GetResourceNames
(),
}
}
return
rules
}
func
getNonResourceRules
(
infos
[]
authorizer
.
NonResourceRuleInfo
)
[]
authorizer
.
DefaultNonResourceRuleInfo
{
rules
:=
make
([]
authorizer
.
DefaultNonResourceRuleInfo
,
len
(
infos
))
for
i
,
info
:=
range
infos
{
rules
[
i
]
=
authorizer
.
DefaultNonResourceRuleInfo
{
Verbs
:
info
.
GetVerbs
(),
NonResourceURLs
:
info
.
GetNonResourceURLs
(),
}
}
return
rules
}
func
TestRulesFor
(
t
*
testing
.
T
)
{
a
,
err
:=
newWithContents
(
t
,
`
{ "readonly": true, "resource": "events" }
{"user":"scheduler", "readonly": true, "resource": "pods" }
{"user":"scheduler", "resource": "bindings" }
{"user":"kubelet", "readonly": true, "resource": "pods" }
{"user":"kubelet", "resource": "events" }
{"user":"alice", "namespace": "projectCaribou"}
{"user":"bob", "readonly": true, "namespace": "projectCaribou"}
{"user":"bob", "readonly": true, "nonResourcePath": "*"}
{"group":"a", "resource": "bindings" }
{"group":"b", "readonly": true, "nonResourcePath": "*"}
`
)
if
err
!=
nil
{
t
.
Fatalf
(
"unable to read policy file: %v"
,
err
)
}
authenticatedGroup
:=
[]
string
{
user
.
AllAuthenticated
}
uScheduler
:=
user
.
DefaultInfo
{
Name
:
"scheduler"
,
UID
:
"uid1"
,
Groups
:
authenticatedGroup
}
uKubelet
:=
user
.
DefaultInfo
{
Name
:
"kubelet"
,
UID
:
"uid2"
,
Groups
:
[]
string
{
"a"
,
"b"
}}
uAlice
:=
user
.
DefaultInfo
{
Name
:
"alice"
,
UID
:
"uid3"
,
Groups
:
authenticatedGroup
}
uBob
:=
user
.
DefaultInfo
{
Name
:
"bob"
,
UID
:
"uid4"
,
Groups
:
authenticatedGroup
}
uChuck
:=
user
.
DefaultInfo
{
Name
:
"chuck"
,
UID
:
"uid5"
,
Groups
:
[]
string
{
"a"
,
"b"
}}
testCases
:=
[]
struct
{
User
user
.
DefaultInfo
Namespace
string
ExpectResourceRules
[]
authorizer
.
DefaultResourceRuleInfo
ExpectNonResourceRules
[]
authorizer
.
DefaultNonResourceRuleInfo
}{
{
User
:
uScheduler
,
Namespace
:
"ns1"
,
ExpectResourceRules
:
[]
authorizer
.
DefaultResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"events"
},
},
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"pods"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"bindings"
},
},
},
ExpectNonResourceRules
:
[]
authorizer
.
DefaultNonResourceRuleInfo
{},
},
{
User
:
uKubelet
,
Namespace
:
"ns1"
,
ExpectResourceRules
:
[]
authorizer
.
DefaultResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"pods"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"events"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"bindings"
},
},
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
},
},
},
ExpectNonResourceRules
:
[]
authorizer
.
DefaultNonResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
NonResourceURLs
:
[]
string
{
"*"
},
},
},
},
{
User
:
uAlice
,
Namespace
:
"projectCaribou"
,
ExpectResourceRules
:
[]
authorizer
.
DefaultResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"events"
},
},
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
},
},
},
ExpectNonResourceRules
:
[]
authorizer
.
DefaultNonResourceRuleInfo
{},
},
{
User
:
uBob
,
Namespace
:
"projectCaribou"
,
ExpectResourceRules
:
[]
authorizer
.
DefaultResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"events"
},
},
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
},
},
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
},
},
},
ExpectNonResourceRules
:
[]
authorizer
.
DefaultNonResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
NonResourceURLs
:
[]
string
{
"*"
},
},
},
},
{
User
:
uChuck
,
Namespace
:
"ns1"
,
ExpectResourceRules
:
[]
authorizer
.
DefaultResourceRuleInfo
{
{
Verbs
:
[]
string
{
"*"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"bindings"
},
},
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
APIGroups
:
[]
string
{
"*"
},
Resources
:
[]
string
{
"*"
},
},
},
ExpectNonResourceRules
:
[]
authorizer
.
DefaultNonResourceRuleInfo
{
{
Verbs
:
[]
string
{
"get"
,
"list"
,
"watch"
},
NonResourceURLs
:
[]
string
{
"*"
},
},
},
},
}
for
i
,
tc
:=
range
testCases
{
attr
:=
authorizer
.
AttributesRecord
{
User
:
&
tc
.
User
,
Namespace
:
tc
.
Namespace
,
}
resourceRules
,
nonResourceRules
,
_
,
_
:=
a
.
RulesFor
(
attr
.
GetUser
(),
attr
.
GetNamespace
())
actualResourceRules
:=
getResourceRules
(
resourceRules
)
if
!
reflect
.
DeepEqual
(
tc
.
ExpectResourceRules
,
actualResourceRules
)
{
t
.
Logf
(
"tc: %v -> attr %v"
,
tc
,
attr
)
t
.
Errorf
(
"%d: Expected:
\n
%#v
\n
but actual:
\n
%#v
\n
"
,
i
,
tc
.
ExpectResourceRules
,
actualResourceRules
)
}
actualNonResourceRules
:=
getNonResourceRules
(
nonResourceRules
)
if
!
reflect
.
DeepEqual
(
tc
.
ExpectNonResourceRules
,
actualNonResourceRules
)
{
t
.
Logf
(
"tc: %v -> attr %v"
,
tc
,
attr
)
t
.
Errorf
(
"%d: Expected:
\n
%#v
\n
but actual:
\n
%#v
\n
"
,
i
,
tc
.
ExpectNonResourceRules
,
actualNonResourceRules
)
}
}
}
func
TestAuthorizeV1beta1
(
t
*
testing
.
T
)
{
a
,
err
:=
newWithContents
(
t
,
`
# Comment line, after a blank line
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "nonResourcePath": "/api"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/custom"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/root/*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"noresource", "nonResourcePath": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "resource": "events", "namespace": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "readonly": true, "resource": "pods", "namespace": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "resource": "bindings", "namespace": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "readonly": true, "resource": "bindings", "namespace": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "resource": "events", "namespace": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"alice", "resource": "*", "namespace": "projectCaribou"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"bob", "readonly": true, "resource": "*", "namespace": "projectCaribou"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"debbie", "resource": "pods", "namespace": "projectCaribou"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectAnyGroup", "apiGroup": "*"}}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectEmptyGroup", "apiGroup": "" }}
{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectXGroup", "apiGroup": "x"}}`
)
if
err
!=
nil
{
t
.
Fatalf
(
"unable to read policy file: %v"
,
err
)
}
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
Verb
string
Resource
string
APIGroup
string
NS
string
Path
string
ExpectDecision
authorizer
.
Decision
}{
// Scheduler can read pods
{
User
:
uScheduler
,
Verb
:
"list"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uScheduler
,
Verb
:
"list"
,
Resource
:
"pods"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Scheduler cannot write pods
{
User
:
uScheduler
,
Verb
:
"create"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uScheduler
,
Verb
:
"create"
,
Resource
:
"pods"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Scheduler can write bindings
{
User
:
uScheduler
,
Verb
:
"get"
,
Resource
:
"bindings"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uScheduler
,
Verb
:
"get"
,
Resource
:
"bindings"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Alice can read and write anything in the right namespace.
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"widgets"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
""
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
"pods"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
"widgets"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAlice
,
Verb
:
"update"
,
Resource
:
""
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// .. but not the wrong namespace.
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
"widgets"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uAlice
,
Verb
:
"get"
,
Resource
:
""
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Debbie can write to pods in the right namespace
{
User
:
uDebbie
,
Verb
:
"update"
,
Resource
:
"pods"
,
NS
:
"projectCaribou"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Chuck can read events, since anyone can.
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"events"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"events"
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// Chuck can't do other things.
{
User
:
uChuck
,
Verb
:
"update"
,
Resource
:
"events"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"pods"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uChuck
,
Verb
:
"get"
,
Resource
:
"floop"
,
NS
:
"ns1"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Chuck can't access things with no resource or namespace
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// but can access /api
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/api"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// though he cannot write to it
{
User
:
uChuck
,
Verb
:
"create"
,
Path
:
"/api"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// while he can write to /custom
{
User
:
uChuck
,
Verb
:
"update"
,
Path
:
"/custom"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// he cannot get "/root"
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/root"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// but can get any subpath
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/root/"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uChuck
,
Verb
:
"get"
,
Path
:
"/root/test/1/2/3"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// the user "noresource" can get any non-resource request
{
User
:
uNoResource
,
Verb
:
"get"
,
Path
:
""
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uNoResource
,
Verb
:
"get"
,
Path
:
"/"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uNoResource
,
Verb
:
"get"
,
Path
:
"/foo/bar/baz"
,
Resource
:
""
,
NS
:
""
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
// but cannot get any request where IsResourceRequest() == true
{
User
:
uNoResource
,
Verb
:
"get"
,
Path
:
"/"
,
Resource
:
""
,
NS
:
"bar"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uNoResource
,
Verb
:
"get"
,
Path
:
"/foo/bar/baz"
,
Resource
:
"foo"
,
NS
:
"bar"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
// Test APIGroup matching
{
User
:
uAPIGroup
,
Verb
:
"get"
,
APIGroup
:
"x"
,
Resource
:
"foo"
,
NS
:
"projectAnyGroup"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
{
User
:
uAPIGroup
,
Verb
:
"get"
,
APIGroup
:
"x"
,
Resource
:
"foo"
,
NS
:
"projectEmptyGroup"
,
ExpectDecision
:
authorizer
.
DecisionNoOpinion
},
{
User
:
uAPIGroup
,
Verb
:
"get"
,
APIGroup
:
"x"
,
Resource
:
"foo"
,
NS
:
"projectXGroup"
,
ExpectDecision
:
authorizer
.
DecisionAllow
},
}
for
i
,
tc
:=
range
testCases
{
attr
:=
authorizer
.
AttributesRecord
{
User
:
&
tc
.
User
,
Verb
:
tc
.
Verb
,
Resource
:
tc
.
Resource
,
APIGroup
:
tc
.
APIGroup
,
Namespace
:
tc
.
NS
,
ResourceRequest
:
len
(
tc
.
NS
)
>
0
||
len
(
tc
.
Resource
)
>
0
,
Path
:
tc
.
Path
,
}
// t.Logf("tc %2v: %v -> attr %v", i, tc, attr)
decision
,
_
,
_
:=
a
.
Authorize
(
attr
)
if
tc
.
ExpectDecision
!=
decision
{
t
.
Errorf
(
"%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v"
,
i
,
tc
.
ExpectDecision
,
decision
,
tc
,
attr
)
}
}
}
func
TestSubjectMatches
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
struct
{
User
user
.
DefaultInfo
Policy
runtime
.
Object
ExpectMatch
bool
}{
"v0 empty policy does not match unauthed user"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"system:anonymous"
,
Groups
:
[]
string
{
"system:unauthenticated"
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
""
,
},
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"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
""
,
},
ExpectMatch
:
true
,
},
"v0 empty policy matches authed user with groups"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"a"
,
"b"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
""
,
},
ExpectMatch
:
true
,
},
"v0 user policy does not match unauthed user"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"system:anonymous"
,
Groups
:
[]
string
{
"system:unauthenticated"
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
""
,
},
ExpectMatch
:
false
,
},
"v0 user policy does not match different user"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Bar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
""
,
},
ExpectMatch
:
false
,
},
"v0 user policy is case-sensitive"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
""
,
},
ExpectMatch
:
false
,
},
"v0 user policy does not match substring"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"FooBar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
""
,
},
ExpectMatch
:
false
,
},
"v0 user policy matches username"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
""
,
},
ExpectMatch
:
true
,
},
"v0 group policy does not match unauthed user"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"system:anonymous"
,
Groups
:
[]
string
{
"system:unauthenticated"
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
"Foo"
,
},
ExpectMatch
:
false
,
},
"v0 group policy does not match user in different group"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"FooBar"
,
Groups
:
[]
string
{
"B"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
"A"
,
},
ExpectMatch
:
false
,
},
"v0 group policy is case-sensitive"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
"b"
,
},
ExpectMatch
:
false
,
},
"v0 group policy does not match substring"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"BBB"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
"B"
,
},
ExpectMatch
:
false
,
},
"v0 group policy matches user in group"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
""
,
Group
:
"B"
,
},
ExpectMatch
:
true
,
},
"v0 user and group policy requires user match"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Bar"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
"B"
,
},
ExpectMatch
:
false
,
},
"v0 user and group policy requires group match"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
"D"
,
},
ExpectMatch
:
false
,
},
"v0 user and group policy matches"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v0
.
Policy
{
User
:
"Foo"
,
Group
:
"B"
,
},
ExpectMatch
:
true
,
},
"v1 empty 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 * 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"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
""
,
},
},
ExpectMatch
:
false
,
},
"v1 empty policy does not match authed user with groups"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"a"
,
"b"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
""
,
},
},
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
:
"Foo"
,
Group
:
""
,
},
},
ExpectMatch
:
false
,
},
"v1 user policy does not match different user"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Bar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
""
,
},
},
ExpectMatch
:
false
,
},
"v1 user policy is case-sensitive"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
""
,
},
},
ExpectMatch
:
false
,
},
"v1 user policy does not match substring"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"FooBar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
""
,
},
},
ExpectMatch
:
false
,
},
"v1 user policy matches username"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
""
,
},
},
ExpectMatch
:
true
,
},
"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
:
"Foo"
,
},
},
ExpectMatch
:
false
,
},
"v1 group policy does not match user in different group"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"FooBar"
,
Groups
:
[]
string
{
"B"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
"A"
,
},
},
ExpectMatch
:
false
,
},
"v1 group policy is case-sensitive"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
"b"
,
},
},
ExpectMatch
:
false
,
},
"v1 group policy does not match substring"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"BBB"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
"B"
,
},
},
ExpectMatch
:
false
,
},
"v1 group policy matches user in group"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
""
,
Group
:
"B"
,
},
},
ExpectMatch
:
true
,
},
"v1 user and group policy requires user match"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Bar"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
"B"
,
},
},
ExpectMatch
:
false
,
},
"v1 user and group policy requires group match"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
"D"
,
},
},
ExpectMatch
:
false
,
},
"v1 user and group policy matches"
:
{
User
:
user
.
DefaultInfo
{
Name
:
"Foo"
,
Groups
:
[]
string
{
"A"
,
"B"
,
"C"
,
user
.
AllAuthenticated
}},
Policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"Foo"
,
Group
:
"B"
,
},
},
ExpectMatch
:
true
,
},
}
for
k
,
tc
:=
range
testCases
{
policy
:=
&
abac
.
Policy
{}
if
err
:=
abac
.
Scheme
.
Convert
(
tc
.
Policy
,
policy
,
nil
);
err
!=
nil
{
t
.
Errorf
(
"%s: error converting: %v"
,
k
,
err
)
continue
}
attr
:=
authorizer
.
AttributesRecord
{
User
:
&
tc
.
User
,
}
actualMatch
:=
subjectMatches
(
*
policy
,
attr
.
GetUser
())
if
tc
.
ExpectMatch
!=
actualMatch
{
t
.
Errorf
(
"%v: Expected actorMatches=%v but actually got=%v"
,
k
,
tc
.
ExpectMatch
,
actualMatch
)
}
}
}
func
newWithContents
(
t
*
testing
.
T
,
contents
string
)
(
policyList
,
error
)
{
f
,
err
:=
ioutil
.
TempFile
(
""
,
"abac_test"
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error creating policyfile: %v"
,
err
)
}
f
.
Close
()
defer
os
.
Remove
(
f
.
Name
())
if
err
:=
ioutil
.
WriteFile
(
f
.
Name
(),
[]
byte
(
contents
),
0700
);
err
!=
nil
{
t
.
Fatalf
(
"unexpected error writing policyfile: %v"
,
err
)
}
pl
,
err
:=
NewFromFile
(
f
.
Name
())
return
pl
,
err
}
func
TestPolicy
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
policy
runtime
.
Object
attr
authorizer
.
Attributes
matches
bool
name
string
}{
// v0 mismatches
{
policy
:
&
v0
.
Policy
{
Readonly
:
true
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Verb
:
"create"
,
},
matches
:
false
,
name
:
"v0 read-only mismatch"
,
},
{
policy
:
&
v0
.
Policy
{
User
:
"foo"
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"bar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
},
matches
:
false
,
name
:
"v0 user name mis-match"
,
},
{
policy
:
&
v0
.
Policy
{
Resource
:
"foo"
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Resource
:
"bar"
,
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v0 resource mis-match"
,
},
{
policy
:
&
v0
.
Policy
{
User
:
"foo"
,
Resource
:
"foo"
,
Namespace
:
"foo"
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Resource
:
"foo"
,
Namespace
:
"foo"
,
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v0 namespace mis-match"
,
},
// v0 matches
{
policy
:
&
v0
.
Policy
{},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v0 null resource"
,
},
{
policy
:
&
v0
.
Policy
{
Readonly
:
true
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Verb
:
"get"
,
},
matches
:
true
,
name
:
"v0 read-only match"
,
},
{
policy
:
&
v0
.
Policy
{
User
:
"foo"
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
},
matches
:
true
,
name
:
"v0 user name match"
,
},
{
policy
:
&
v0
.
Policy
{
Resource
:
"foo"
,
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Resource
:
"foo"
,
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v0 resource match"
,
},
// v1 mismatches
{
policy
:
&
v1beta1
.
Policy
{},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v1 null"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"foo"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"bar"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v1 user name mis-match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
Readonly
:
true
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v1 read-only mismatch"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
Resource
:
"foo"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Resource
:
"bar"
,
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v1 resource mis-match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"foo"
,
Namespace
:
"barr"
,
Resource
:
"baz"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Namespace
:
"bar"
,
Resource
:
"baz"
,
ResourceRequest
:
true
,
},
matches
:
false
,
name
:
"v1 namespace mis-match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
NonResourcePath
:
"/api"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Path
:
"/api2"
,
ResourceRequest
:
false
,
},
matches
:
false
,
name
:
"v1 non-resource mis-match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
NonResourcePath
:
"/api/*"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Path
:
"/api2/foo"
,
ResourceRequest
:
false
,
},
matches
:
false
,
name
:
"v1 non-resource wildcard subpath mis-match"
,
},
// v1 matches
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"foo"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 user match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 user wildcard match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
Group
:
"bar"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
"bar"
,
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 group match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
Group
:
"*"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
"bar"
,
user
.
AllAuthenticated
},
},
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 group wildcard match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
Readonly
:
true
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Verb
:
"get"
,
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 read-only match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
Resource
:
"foo"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Resource
:
"foo"
,
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 resource match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"foo"
,
Namespace
:
"bar"
,
Resource
:
"baz"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Namespace
:
"bar"
,
Resource
:
"baz"
,
ResourceRequest
:
true
,
},
matches
:
true
,
name
:
"v1 namespace match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
NonResourcePath
:
"/api"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Path
:
"/api"
,
ResourceRequest
:
false
,
},
matches
:
true
,
name
:
"v1 non-resource match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
NonResourcePath
:
"*"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Path
:
"/api"
,
ResourceRequest
:
false
,
},
matches
:
true
,
name
:
"v1 non-resource wildcard match"
,
},
{
policy
:
&
v1beta1
.
Policy
{
Spec
:
v1beta1
.
PolicySpec
{
User
:
"*"
,
NonResourcePath
:
"/api/*"
,
},
},
attr
:
authorizer
.
AttributesRecord
{
User
:
&
user
.
DefaultInfo
{
Name
:
"foo"
,
Groups
:
[]
string
{
user
.
AllAuthenticated
},
},
Path
:
"/api/foo"
,
ResourceRequest
:
false
,
},
matches
:
true
,
name
:
"v1 non-resource wildcard subpath match"
,
},
}
for
_
,
test
:=
range
tests
{
policy
:=
&
abac
.
Policy
{}
if
err
:=
abac
.
Scheme
.
Convert
(
test
.
policy
,
policy
,
nil
);
err
!=
nil
{
t
.
Errorf
(
"%s: error converting: %v"
,
test
.
name
,
err
)
continue
}
matches
:=
matches
(
*
policy
,
test
.
attr
)
if
test
.
matches
!=
matches
{
t
.
Errorf
(
"%s: expected: %t, saw: %t"
,
test
.
name
,
test
.
matches
,
matches
)
continue
}
}
}
pkg/auth/authorizer/abac/example_policy_file.jsonl
deleted
100644 → 0
View file @
afa0802f
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group":"system:authenticated", "nonResourcePath": "*", "readonly": true}}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group":"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" }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"kubelet", "namespace": "*", "resource": "pods", "readonly": true }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"kubelet", "namespace": "*", "resource": "services", "readonly": true }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"kubelet", "namespace": "*", "resource": "endpoints", "readonly": true }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"kubelet", "namespace": "*", "resource": "events" }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"alice", "namespace": "projectCaribou", "resource": "*", "apiGroup": "*" }}
{"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user":"bob", "namespace": "projectCaribou", "resource": "*", "apiGroup": "*", "readonly": true }}
\ No newline at end of file
pkg/kubeapiserver/authorizer/config.go
View file @
6014ace9
...
...
@@ -25,7 +25,6 @@ import (
"k8s.io/apiserver/pkg/authorization/union"
"k8s.io/apiserver/plugin/pkg/authorizer/webhook"
versionedinformers
"k8s.io/client-go/informers"
"k8s.io/kubernetes/pkg/auth/authorizer/abac"
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/node"
...
...
@@ -39,9 +38,6 @@ type Config struct {
// Options for ModeABAC
// Path to an ABAC policy file.
PolicyFile
string
// Options for ModeWebhook
// Kubeconfig file for Webhook authorization plugin.
...
...
@@ -89,13 +85,6 @@ func (config Config) New() (authorizer.Authorizer, authorizer.RuleResolver, erro
alwaysDenyAuthorizer
:=
authorizerfactory
.
NewAlwaysDenyAuthorizer
()
authorizers
=
append
(
authorizers
,
alwaysDenyAuthorizer
)
ruleResolvers
=
append
(
ruleResolvers
,
alwaysDenyAuthorizer
)
case
modes
.
ModeABAC
:
abacAuthorizer
,
err
:=
abac
.
NewFromFile
(
config
.
PolicyFile
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
authorizers
=
append
(
authorizers
,
abacAuthorizer
)
ruleResolvers
=
append
(
ruleResolvers
,
abacAuthorizer
)
case
modes
.
ModeWebhook
:
webhookAuthorizer
,
err
:=
webhook
.
New
(
config
.
WebhookConfigFile
,
config
.
WebhookCacheAuthorizedTTL
,
...
...
pkg/kubeapiserver/authorizer/modes/modes.go
View file @
6014ace9
...
...
@@ -23,8 +23,6 @@ const (
ModeAlwaysAllow
string
=
"AlwaysAllow"
// ModeAlwaysDeny is the mode to set no requests as authorized
ModeAlwaysDeny
string
=
"AlwaysDeny"
// ModeABAC is the mode to use Attribute Based Access Control to authorize
ModeABAC
string
=
"ABAC"
// ModeWebhook is the mode to make an external webhook call to authorize
ModeWebhook
string
=
"Webhook"
// ModeRBAC is the mode to use Role Based Access Control to authorize
...
...
@@ -34,7 +32,7 @@ const (
)
// AuthorizationModeChoices is the list of supported authorization modes
var
AuthorizationModeChoices
=
[]
string
{
ModeAlwaysAllow
,
ModeAlwaysDeny
,
Mode
ABAC
,
Mode
Webhook
,
ModeRBAC
,
ModeNode
}
var
AuthorizationModeChoices
=
[]
string
{
ModeAlwaysAllow
,
ModeAlwaysDeny
,
ModeWebhook
,
ModeRBAC
,
ModeNode
}
// IsValidAuthorizationMode returns true if the given authorization mode is a valid one for the apiserver
func
IsValidAuthorizationMode
(
authzMode
string
)
bool
{
...
...
pkg/kubeapiserver/options/authorization.go
View file @
6014ace9
...
...
@@ -31,7 +31,6 @@ import (
type
BuiltInAuthorizationOptions
struct
{
Modes
[]
string
PolicyFile
string
WebhookConfigFile
string
WebhookCacheAuthorizedTTL
time
.
Duration
WebhookCacheUnauthorizedTTL
time
.
Duration
...
...
@@ -61,11 +60,6 @@ func (s *BuiltInAuthorizationOptions) Validate() []error {
if
!
allowedModes
.
Has
(
mode
)
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode %q is not a valid mode"
,
mode
))
}
if
mode
==
authzmodes
.
ModeABAC
{
if
s
.
PolicyFile
==
""
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode ABAC's authorization policy file not passed"
))
}
}
if
mode
==
authzmodes
.
ModeWebhook
{
if
s
.
WebhookConfigFile
==
""
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"authorization-mode Webhook's authorization config file not passed"
))
...
...
@@ -73,10 +67,6 @@ func (s *BuiltInAuthorizationOptions) Validate() []error {
}
}
if
s
.
PolicyFile
!=
""
&&
!
modes
.
Has
(
authzmodes
.
ModeABAC
)
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"cannot specify --authorization-policy-file without mode ABAC"
))
}
if
s
.
WebhookConfigFile
!=
""
&&
!
modes
.
Has
(
authzmodes
.
ModeWebhook
)
{
allErrors
=
append
(
allErrors
,
fmt
.
Errorf
(
"cannot specify --authorization-webhook-config-file without mode Webhook"
))
}
...
...
@@ -93,9 +83,6 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
"Ordered list of plug-ins to do authorization on secure port. Comma-delimited list of: "
+
strings
.
Join
(
authzmodes
.
AuthorizationModeChoices
,
","
)
+
"."
)
fs
.
StringVar
(
&
s
.
PolicyFile
,
"authorization-policy-file"
,
s
.
PolicyFile
,
""
+
"File with authorization policy in json line by line format, used with --authorization-mode=ABAC, on the secure port."
)
fs
.
StringVar
(
&
s
.
WebhookConfigFile
,
"authorization-webhook-config-file"
,
s
.
WebhookConfigFile
,
""
+
"File with webhook configuration in kubeconfig format, used with --authorization-mode=Webhook. "
+
"The API server will query the remote service to determine access on the API server's secure port."
)
...
...
@@ -112,7 +99,6 @@ func (s *BuiltInAuthorizationOptions) AddFlags(fs *pflag.FlagSet) {
func
(
s
*
BuiltInAuthorizationOptions
)
ToAuthorizationConfig
(
versionedInformerFactory
versionedinformers
.
SharedInformerFactory
)
authorizer
.
Config
{
return
authorizer
.
Config
{
AuthorizationModes
:
s
.
Modes
,
PolicyFile
:
s
.
PolicyFile
,
WebhookConfigFile
:
s
.
WebhookConfigFile
,
WebhookCacheAuthorizedTTL
:
s
.
WebhookCacheAuthorizedTTL
,
WebhookCacheUnauthorizedTTL
:
s
.
WebhookCacheUnauthorizedTTL
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment