diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json
index f2656f98b4d..248939bea17 100644
--- a/api/openapi-spec/swagger.json
+++ b/api/openapi-spec/swagger.json
@@ -69539,7 +69539,11 @@
],
"properties": {
"allowed": {
- "description": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "description": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "type": "boolean"
+ },
+ "denied": {
+ "description": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true.",
"type": "boolean"
},
"evaluationError": {
@@ -69890,7 +69894,11 @@
],
"properties": {
"allowed": {
- "description": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "description": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "type": "boolean"
+ },
+ "denied": {
+ "description": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true.",
"type": "boolean"
},
"evaluationError": {
diff --git a/api/swagger-spec/authorization.k8s.io_v1.json b/api/swagger-spec/authorization.k8s.io_v1.json
index 41a18f708a9..56f1720c4f2 100644
--- a/api/swagger-spec/authorization.k8s.io_v1.json
+++ b/api/swagger-spec/authorization.k8s.io_v1.json
@@ -635,7 +635,11 @@
"properties": {
"allowed": {
"type": "boolean",
- "description": "Allowed is required. True if the action would be allowed, false otherwise."
+ "description": "Allowed is required. True if the action would be allowed, false otherwise."
+ },
+ "denied": {
+ "type": "boolean",
+ "description": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true."
},
"reason": {
"type": "string",
diff --git a/api/swagger-spec/authorization.k8s.io_v1beta1.json b/api/swagger-spec/authorization.k8s.io_v1beta1.json
index 2b2a3ecf6af..e2c8f923a4c 100644
--- a/api/swagger-spec/authorization.k8s.io_v1beta1.json
+++ b/api/swagger-spec/authorization.k8s.io_v1beta1.json
@@ -635,7 +635,11 @@
"properties": {
"allowed": {
"type": "boolean",
- "description": "Allowed is required. True if the action would be allowed, false otherwise."
+ "description": "Allowed is required. True if the action would be allowed, false otherwise."
+ },
+ "denied": {
+ "type": "boolean",
+ "description": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true."
},
"reason": {
"type": "string",
diff --git a/docs/api-reference/authorization.k8s.io/v1/definitions.html b/docs/api-reference/authorization.k8s.io/v1/definitions.html
index b1f11b445d3..a71abf874ab 100755
--- a/docs/api-reference/authorization.k8s.io/v1/definitions.html
+++ b/docs/api-reference/authorization.k8s.io/v1/definitions.html
@@ -850,12 +850,19 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
allowed |
-Allowed is required. True if the action would be allowed, false otherwise. |
+Allowed is required. True if the action would be allowed, false otherwise. |
true |
boolean |
false |
+denied |
+Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true. |
+false |
+boolean |
+false |
+
+
reason |
Reason is optional. It indicates why a request was allowed or denied. |
false |
diff --git a/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html b/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html
index d6c0a2ed3c5..6113f09dfdc 100755
--- a/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html
+++ b/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html
@@ -1094,12 +1094,19 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
allowed |
-Allowed is required. True if the action would be allowed, false otherwise. |
+Allowed is required. True if the action would be allowed, false otherwise. |
true |
boolean |
false |
+denied |
+Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true. |
+false |
+boolean |
+false |
+
+
reason |
Reason is optional. It indicates why a request was allowed or denied. |
false |
diff --git a/pkg/apis/authorization/types.go b/pkg/apis/authorization/types.go
index c4140b6d1cc..e798ec2123e 100644
--- a/pkg/apis/authorization/types.go
+++ b/pkg/apis/authorization/types.go
@@ -140,8 +140,13 @@ type SelfSubjectAccessReviewSpec struct {
// SubjectAccessReviewStatus
type SubjectAccessReviewStatus struct {
- // Allowed is required. True if the action would be allowed, false otherwise.
+ // Allowed is required. True if the action would be allowed, false otherwise.
Allowed bool
+ // Denied is optional. True if the action would be denied, otherwise
+ // false. If both allowed is false and denied is false, then the
+ // authorizer has no opinion on whether to authorize the action. Denied
+ // may not be true if Allowed is true.
+ Denied bool
// Reason is optional. It indicates why a request was allowed or denied.
Reason string
// EvaluationError is an indication that some error occurred during the authorization check.
diff --git a/pkg/apis/authorization/v1/zz_generated.conversion.go b/pkg/apis/authorization/v1/zz_generated.conversion.go
index 1c06171c6fc..00caf7872a0 100644
--- a/pkg/apis/authorization/v1/zz_generated.conversion.go
+++ b/pkg/apis/authorization/v1/zz_generated.conversion.go
@@ -369,6 +369,7 @@ func Convert_authorization_SubjectAccessReviewSpec_To_v1_SubjectAccessReviewSpec
func autoConvert_v1_SubjectAccessReviewStatus_To_authorization_SubjectAccessReviewStatus(in *v1.SubjectAccessReviewStatus, out *authorization.SubjectAccessReviewStatus, s conversion.Scope) error {
out.Allowed = in.Allowed
+ out.Denied = in.Denied
out.Reason = in.Reason
out.EvaluationError = in.EvaluationError
return nil
@@ -381,6 +382,7 @@ func Convert_v1_SubjectAccessReviewStatus_To_authorization_SubjectAccessReviewSt
func autoConvert_authorization_SubjectAccessReviewStatus_To_v1_SubjectAccessReviewStatus(in *authorization.SubjectAccessReviewStatus, out *v1.SubjectAccessReviewStatus, s conversion.Scope) error {
out.Allowed = in.Allowed
+ out.Denied = in.Denied
out.Reason = in.Reason
out.EvaluationError = in.EvaluationError
return nil
diff --git a/pkg/apis/authorization/v1beta1/zz_generated.conversion.go b/pkg/apis/authorization/v1beta1/zz_generated.conversion.go
index 4ba9417a61f..234b4ff0261 100644
--- a/pkg/apis/authorization/v1beta1/zz_generated.conversion.go
+++ b/pkg/apis/authorization/v1beta1/zz_generated.conversion.go
@@ -369,6 +369,7 @@ func Convert_authorization_SubjectAccessReviewSpec_To_v1beta1_SubjectAccessRevie
func autoConvert_v1beta1_SubjectAccessReviewStatus_To_authorization_SubjectAccessReviewStatus(in *v1beta1.SubjectAccessReviewStatus, out *authorization.SubjectAccessReviewStatus, s conversion.Scope) error {
out.Allowed = in.Allowed
+ out.Denied = in.Denied
out.Reason = in.Reason
out.EvaluationError = in.EvaluationError
return nil
@@ -381,6 +382,7 @@ func Convert_v1beta1_SubjectAccessReviewStatus_To_authorization_SubjectAccessRev
func autoConvert_authorization_SubjectAccessReviewStatus_To_v1beta1_SubjectAccessReviewStatus(in *authorization.SubjectAccessReviewStatus, out *v1beta1.SubjectAccessReviewStatus, s conversion.Scope) error {
out.Allowed = in.Allowed
+ out.Denied = in.Denied
out.Reason = in.Reason
out.EvaluationError = in.EvaluationError
return nil
diff --git a/pkg/auth/authorizer/abac/abac.go b/pkg/auth/authorizer/abac/abac.go
index 956c1f70866..f3132740d2d 100644
--- a/pkg/auth/authorizer/abac/abac.go
+++ b/pkg/auth/authorizer/abac/abac.go
@@ -221,13 +221,13 @@ func resourceMatches(p abac.Policy, a authorizer.Attributes) bool {
}
// Authorizer implements authorizer.Authorize
-func (pl policyList) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (pl policyList) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
for _, p := range pl {
if matches(*p, a) {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
}
- return false, "No policy matched.", 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.
diff --git a/pkg/auth/authorizer/abac/abac_test.go b/pkg/auth/authorizer/abac/abac_test.go
index 027943a8a3c..6d732399201 100644
--- a/pkg/auth/authorizer/abac/abac_test.go
+++ b/pkg/auth/authorizer/abac/abac_test.go
@@ -81,46 +81,46 @@ func TestAuthorizeV0(t *testing.T) {
uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup}
testCases := []struct {
- User user.DefaultInfo
- Verb string
- Resource string
- NS string
- APIGroup string
- Path string
- ExpectAllow bool
+ 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", ExpectAllow: true},
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectAllow: false},
+ {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", ExpectAllow: true},
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: true},
- {User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "foo", NS: "projectCaribou", APIGroup: "bar", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectAllow: false},
- {User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectAllow: false},
+ {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", ExpectAllow: true},
- {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectAllow: false},
- {User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectAllow: false},
+ {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: "", ExpectAllow: false},
+ {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
}
for i, tc := range testCases {
attr := authorizer.AttributesRecord{
@@ -133,11 +133,11 @@ func TestAuthorizeV0(t *testing.T) {
ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0,
}
- authorized, _, _ := a.Authorize(attr)
- if tc.ExpectAllow != authorized {
+ 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.ExpectAllow, authorized, tc)
+ i, tc.ExpectDecision, decision, tc)
}
}
}
@@ -373,72 +373,72 @@ func TestAuthorizeV1beta1(t *testing.T) {
uAPIGroup := user.DefaultInfo{Name: "apigroupuser", UID: "uid8", Groups: authenticatedGroup}
testCases := []struct {
- User user.DefaultInfo
- Verb string
- Resource string
- APIGroup string
- NS string
- Path string
- ExpectAllow bool
+ 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", ExpectAllow: true},
- {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectAllow: false},
+ {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", ExpectAllow: true},
- {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: true},
- {User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectAllow: true},
- {User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectAllow: false},
- {User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectAllow: false},
+ {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", ExpectAllow: true},
+ {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", ExpectAllow: true},
- {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectAllow: false},
- {User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectAllow: false},
+ {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: "", ExpectAllow: false},
+ {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
// but can access /api
- {User: uChuck, Verb: "get", Path: "/api", Resource: "", NS: "", ExpectAllow: true},
+ {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: "", ExpectAllow: false},
+ {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: "", ExpectAllow: true},
+ {User: uChuck, Verb: "update", Path: "/custom", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow},
// he cannot get "/root"
- {User: uChuck, Verb: "get", Path: "/root", Resource: "", NS: "", ExpectAllow: false},
+ {User: uChuck, Verb: "get", Path: "/root", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion},
// but can get any subpath
- {User: uChuck, Verb: "get", Path: "/root/", Resource: "", NS: "", ExpectAllow: true},
- {User: uChuck, Verb: "get", Path: "/root/test/1/2/3", Resource: "", NS: "", ExpectAllow: true},
+ {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: "", ExpectAllow: true},
- {User: uNoResource, Verb: "get", Path: "/", Resource: "", NS: "", ExpectAllow: true},
- {User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "", NS: "", ExpectAllow: true},
+ {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", ExpectAllow: false},
- {User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "foo", NS: "bar", ExpectAllow: false},
+ {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", ExpectAllow: true},
- {User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectEmptyGroup", ExpectAllow: false},
- {User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectXGroup", ExpectAllow: true},
+ {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{
@@ -451,10 +451,10 @@ func TestAuthorizeV1beta1(t *testing.T) {
Path: tc.Path,
}
// t.Logf("tc %2v: %v -> attr %v", i, tc, attr)
- authorized, _, _ := a.Authorize(attr)
- if tc.ExpectAllow != authorized {
+ decision, _, _ := a.Authorize(attr)
+ if tc.ExpectDecision != decision {
t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v",
- i, tc.ExpectAllow, authorized, tc, attr)
+ i, tc.ExpectDecision, decision, tc, attr)
}
}
}
diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go
index 72049afd17c..aed6ecb1171 100644
--- a/pkg/kubelet/server/server.go
+++ b/pkg/kubelet/server/server.go
@@ -236,14 +236,14 @@ func (s *Server) InstallAuthFilter() {
attrs := s.auth.GetRequestAttributes(u, req.Request)
// Authorize
- authorized, _, err := s.auth.Authorize(attrs)
+ decision, _, err := s.auth.Authorize(attrs)
if err != nil {
msg := fmt.Sprintf("Authorization error (user=%s, verb=%s, resource=%s, subresource=%s)", u.GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource())
glog.Errorf(msg, err)
resp.WriteErrorString(http.StatusInternalServerError, msg)
return
}
- if !authorized {
+ if decision != authorizer.DecisionAllow {
msg := fmt.Sprintf("Forbidden (user=%s, verb=%s, resource=%s, subresource=%s)", u.GetName(), attrs.GetVerb(), attrs.GetResource(), attrs.GetSubresource())
glog.V(2).Info(msg)
resp.WriteErrorString(http.StatusForbidden, msg)
diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go
index 7fa1753db2e..daa1a916000 100644
--- a/pkg/kubelet/server/server_test.go
+++ b/pkg/kubelet/server/server_test.go
@@ -183,7 +183,7 @@ func (_ *fakeKubelet) GetCgroupStats(cgroupName string) (*statsapi.ContainerStat
type fakeAuth struct {
authenticateFunc func(*http.Request) (user.Info, bool, error)
attributesFunc func(user.Info, *http.Request) authorizer.Attributes
- authorizeFunc func(authorizer.Attributes) (authorized bool, reason string, err error)
+ authorizeFunc func(authorizer.Attributes) (authorized authorizer.Decision, reason string, err error)
}
func (f *fakeAuth) AuthenticateRequest(req *http.Request) (user.Info, bool, error) {
@@ -192,7 +192,7 @@ func (f *fakeAuth) AuthenticateRequest(req *http.Request) (user.Info, bool, erro
func (f *fakeAuth) GetRequestAttributes(u user.Info, req *http.Request) authorizer.Attributes {
return f.attributesFunc(u, req)
}
-func (f *fakeAuth) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
+func (f *fakeAuth) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
return f.authorizeFunc(a)
}
@@ -232,8 +232,8 @@ func newServerTestWithDebug(enableDebugging bool) *serverTestFramework {
attributesFunc: func(u user.Info, req *http.Request) authorizer.Attributes {
return &authorizer.AttributesRecord{User: u}
},
- authorizeFunc: func(a authorizer.Attributes) (authorized bool, reason string, err error) {
- return true, "", nil
+ authorizeFunc: func(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
+ return authorizer.DecisionAllow, "", nil
},
}
fw.criHandler = &utiltesting.FakeHandler{
@@ -688,12 +688,12 @@ Otherwise, add it to the expected list of paths that map to the "proxy" subresou
}
return attributesGetter.GetRequestAttributes(u, req)
}
- fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (authorized bool, reason string, err error) {
+ fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
calledAuthorize = true
if a != expectedAttributes {
t.Fatalf("%s: expected attributes\n\t%#v\ngot\n\t%#v", tc.Path, expectedAttributes, a)
}
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
req, err := http.NewRequest(tc.Method, fw.testHTTPServer.URL+tc.Path, nil)
@@ -747,9 +747,9 @@ func TestAuthenticationError(t *testing.T) {
calledAttributes = true
return expectedAttributes
}
- fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (authorized bool, reason string, err error) {
+ fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
calledAuthorize = true
- return false, "", errors.New("Failed")
+ return authorizer.DecisionNoOpinion, "", errors.New("Failed")
}
assertHealthFails(t, fw.testHTTPServer.URL+"/healthz", http.StatusInternalServerError)
@@ -785,9 +785,9 @@ func TestAuthenticationFailure(t *testing.T) {
calledAttributes = true
return expectedAttributes
}
- fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (authorized bool, reason string, err error) {
+ fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
calledAuthorize = true
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
assertHealthFails(t, fw.testHTTPServer.URL+"/healthz", http.StatusUnauthorized)
@@ -823,9 +823,9 @@ func TestAuthorizationSuccess(t *testing.T) {
calledAttributes = true
return expectedAttributes
}
- fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (authorized bool, reason string, err error) {
+ fw.fakeAuth.authorizeFunc = func(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
calledAuthorize = true
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
assertHealthIsOk(t, fw.testHTTPServer.URL+"/healthz")
diff --git a/pkg/registry/authorization/localsubjectaccessreview/rest.go b/pkg/registry/authorization/localsubjectaccessreview/rest.go
index 53487b310aa..af49b6bd4d9 100644
--- a/pkg/registry/authorization/localsubjectaccessreview/rest.go
+++ b/pkg/registry/authorization/localsubjectaccessreview/rest.go
@@ -58,10 +58,11 @@ func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createV
}
authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(localSubjectAccessReview.Spec)
- allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
+ decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
localSubjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{
- Allowed: allowed,
+ Allowed: (decision == authorizer.DecisionAllow),
+ Denied: (decision == authorizer.DecisionDeny),
Reason: reason,
}
if evaluationErr != nil {
diff --git a/pkg/registry/authorization/selfsubjectaccessreview/rest.go b/pkg/registry/authorization/selfsubjectaccessreview/rest.go
index 5041dddb7cc..38900a877f4 100644
--- a/pkg/registry/authorization/selfsubjectaccessreview/rest.go
+++ b/pkg/registry/authorization/selfsubjectaccessreview/rest.go
@@ -61,10 +61,11 @@ func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createV
authorizationAttributes = authorizationutil.NonResourceAttributesFrom(userToCheck, *selfSAR.Spec.NonResourceAttributes)
}
- allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
+ decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
selfSAR.Status = authorizationapi.SubjectAccessReviewStatus{
- Allowed: allowed,
+ Allowed: (decision == authorizer.DecisionAllow),
+ Denied: (decision == authorizer.DecisionDeny),
Reason: reason,
}
if evaluationErr != nil {
diff --git a/pkg/registry/authorization/subjectaccessreview/rest.go b/pkg/registry/authorization/subjectaccessreview/rest.go
index 1252a41ca48..92da3d34244 100644
--- a/pkg/registry/authorization/subjectaccessreview/rest.go
+++ b/pkg/registry/authorization/subjectaccessreview/rest.go
@@ -51,10 +51,11 @@ func (r *REST) Create(ctx genericapirequest.Context, obj runtime.Object, createV
}
authorizationAttributes := authorizationutil.AuthorizationAttributesFrom(subjectAccessReview.Spec)
- allowed, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
+ decision, reason, evaluationErr := r.authorizer.Authorize(authorizationAttributes)
subjectAccessReview.Status = authorizationapi.SubjectAccessReviewStatus{
- Allowed: allowed,
+ Allowed: (decision == authorizer.DecisionAllow),
+ Denied: (decision == authorizer.DecisionDeny),
Reason: reason,
}
if evaluationErr != nil {
diff --git a/pkg/registry/authorization/subjectaccessreview/rest_test.go b/pkg/registry/authorization/subjectaccessreview/rest_test.go
index 697441f42fd..ce882a8b4bf 100644
--- a/pkg/registry/authorization/subjectaccessreview/rest_test.go
+++ b/pkg/registry/authorization/subjectaccessreview/rest_test.go
@@ -33,22 +33,22 @@ import (
type fakeAuthorizer struct {
attrs authorizer.Attributes
- ok bool
- reason string
- err error
+ decision authorizer.Decision
+ reason string
+ err error
}
-func (f *fakeAuthorizer) Authorize(attrs authorizer.Attributes) (bool, string, error) {
+func (f *fakeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
f.attrs = attrs
- return f.ok, f.reason, f.err
+ return f.decision, f.reason, f.err
}
func TestCreate(t *testing.T) {
testcases := map[string]struct {
- spec authorizationapi.SubjectAccessReviewSpec
- ok bool
- reason string
- err error
+ spec authorizationapi.SubjectAccessReviewSpec
+ decision authorizer.Decision
+ reason string
+ err error
expectedErr string
expectedAttrs authorizer.Attributes
@@ -63,9 +63,9 @@ func TestCreate(t *testing.T) {
User: "bob",
NonResourceAttributes: &authorizationapi.NonResourceAttributes{Verb: "get", Path: "/mypath"},
},
- ok: false,
- reason: "myreason",
- err: errors.New("myerror"),
+ decision: authorizer.DecisionNoOpinion,
+ reason: "myreason",
+ err: errors.New("myerror"),
expectedAttrs: authorizer.AttributesRecord{
User: &user.DefaultInfo{Name: "bob"},
Verb: "get",
@@ -84,9 +84,9 @@ func TestCreate(t *testing.T) {
User: "bob",
NonResourceAttributes: &authorizationapi.NonResourceAttributes{Verb: "get", Path: "/mypath"},
},
- ok: true,
- reason: "allowed",
- err: nil,
+ decision: authorizer.DecisionAllow,
+ reason: "allowed",
+ err: nil,
expectedAttrs: authorizer.AttributesRecord{
User: &user.DefaultInfo{Name: "bob"},
Verb: "get",
@@ -113,9 +113,9 @@ func TestCreate(t *testing.T) {
Name: "mydeployment",
},
},
- ok: false,
- reason: "myreason",
- err: errors.New("myerror"),
+ decision: authorizer.DecisionNoOpinion,
+ reason: "myreason",
+ err: errors.New("myerror"),
expectedAttrs: authorizer.AttributesRecord{
User: &user.DefaultInfo{Name: "bob"},
Namespace: "myns",
@@ -129,6 +129,7 @@ func TestCreate(t *testing.T) {
},
expectedStatus: authorizationapi.SubjectAccessReviewStatus{
Allowed: false,
+ Denied: false,
Reason: "myreason",
EvaluationError: "myerror",
},
@@ -147,9 +148,9 @@ func TestCreate(t *testing.T) {
Name: "mydeployment",
},
},
- ok: true,
- reason: "allowed",
- err: nil,
+ decision: authorizer.DecisionAllow,
+ reason: "allowed",
+ err: nil,
expectedAttrs: authorizer.AttributesRecord{
User: &user.DefaultInfo{Name: "bob"},
Namespace: "myns",
@@ -163,17 +164,34 @@ func TestCreate(t *testing.T) {
},
expectedStatus: authorizationapi.SubjectAccessReviewStatus{
Allowed: true,
+ Denied: false,
Reason: "allowed",
EvaluationError: "",
},
},
+
+ "resource denied": {
+ spec: authorizationapi.SubjectAccessReviewSpec{
+ User: "bob",
+ ResourceAttributes: &authorizationapi.ResourceAttributes{},
+ },
+ decision: authorizer.DecisionDeny,
+ expectedAttrs: authorizer.AttributesRecord{
+ User: &user.DefaultInfo{Name: "bob"},
+ ResourceRequest: true,
+ },
+ expectedStatus: authorizationapi.SubjectAccessReviewStatus{
+ Allowed: false,
+ Denied: true,
+ },
+ },
}
for k, tc := range testcases {
auth := &fakeAuthorizer{
- ok: tc.ok,
- reason: tc.reason,
- err: tc.err,
+ decision: tc.decision,
+ reason: tc.reason,
+ err: tc.err,
}
storage := NewREST(auth)
diff --git a/pkg/registry/rbac/escalation_check.go b/pkg/registry/rbac/escalation_check.go
index 4fa0d59ceaf..4ac1392fbbd 100644
--- a/pkg/registry/rbac/escalation_check.go
+++ b/pkg/registry/rbac/escalation_check.go
@@ -79,12 +79,12 @@ func BindingAuthorized(ctx genericapirequest.Context, roleRef rbac.RoleRef, bind
return false
}
- ok, _, err := a.Authorize(attrs)
+ decision, _, err := a.Authorize(attrs)
if err != nil {
utilruntime.HandleError(fmt.Errorf(
"error authorizing user %#v to bind %#v in namespace %s: %v",
user, roleRef, bindingNamespace, err,
))
}
- return ok
+ return decision == authorizer.DecisionAllow
}
diff --git a/plugin/pkg/admission/gc/gc_admission.go b/plugin/pkg/admission/gc/gc_admission.go
index 2e1a53306c1..7acd5cf48fd 100644
--- a/plugin/pkg/admission/gc/gc_admission.go
+++ b/plugin/pkg/admission/gc/gc_admission.go
@@ -104,8 +104,8 @@ func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes) (er
ResourceRequest: true,
Path: "",
}
- allowed, reason, err := a.authorizer.Authorize(deleteAttributes)
- if !allowed {
+ decision, reason, err := a.authorizer.Authorize(deleteAttributes)
+ if decision != authorizer.DecisionAllow {
return admission.NewForbidden(attributes, fmt.Errorf("cannot set an ownerRef on a resource you can't delete: %v, %v", reason, err))
}
@@ -122,8 +122,8 @@ func (a *gcPermissionsEnforcement) Validate(attributes admission.Attributes) (er
// resources. User needs to have delete permission on all the
// matched Resources.
for _, record := range records {
- allowed, reason, err := a.authorizer.Authorize(record)
- if !allowed {
+ decision, reason, err := a.authorizer.Authorize(record)
+ if decision != authorizer.DecisionAllow {
return admission.NewForbidden(attributes, fmt.Errorf("cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: %v, %v", reason, err))
}
}
diff --git a/plugin/pkg/admission/gc/gc_admission_test.go b/plugin/pkg/admission/gc/gc_admission_test.go
index 9cc118fba85..52fb665065a 100644
--- a/plugin/pkg/admission/gc/gc_admission_test.go
+++ b/plugin/pkg/admission/gc/gc_admission_test.go
@@ -34,40 +34,40 @@ import (
type fakeAuthorizer struct{}
-func (fakeAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
username := a.GetUser().GetName()
if username == "non-deleter" {
if a.GetVerb() == "delete" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
if a.GetVerb() == "update" && a.GetSubresource() == "finalizers" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if username == "non-pod-deleter" {
if a.GetVerb() == "delete" && a.GetResource() == "pods" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
if a.GetVerb() == "update" && a.GetResource() == "pods" && a.GetSubresource() == "finalizers" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if username == "non-rc-deleter" {
if a.GetVerb() == "delete" && a.GetResource() == "replicationcontrollers" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
if a.GetVerb() == "update" && a.GetResource() == "replicationcontrollers" && a.GetSubresource() == "finalizers" {
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// newGCPermissionsEnforcement returns the admission controller configured for testing.
diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission.go b/plugin/pkg/admission/security/podsecuritypolicy/admission.go
index fbc1cc3761e..b672838a65f 100644
--- a/plugin/pkg/admission/security/podsecuritypolicy/admission.go
+++ b/plugin/pkg/admission/security/podsecuritypolicy/admission.go
@@ -313,11 +313,11 @@ func authorizedForPolicy(info user.Info, namespace string, policy *extensions.Po
return false
}
attr := buildAttributes(info, namespace, policy)
- allowed, reason, err := authz.Authorize(attr)
+ decision, reason, err := authz.Authorize(attr)
if err != nil {
glog.V(5).Infof("cannot authorize for policy: %v,%v", reason, err)
}
- return allowed
+ return (decision == authorizer.DecisionAllow)
}
// buildAttributes builds an attributes record for a SAR based on the user info and policy.
diff --git a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go
index e66e687becc..022a3078514 100644
--- a/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go
+++ b/plugin/pkg/admission/security/podsecuritypolicy/admission_test.go
@@ -66,13 +66,16 @@ type TestAuthorizer struct {
usernameToNamespaceToAllowedPSPs map[string]map[string]map[string]bool
}
-func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
+func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
if t.usernameToNamespaceToAllowedPSPs == nil {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
allowedInNamespace := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][a.GetNamespace()][a.GetName()]
allowedClusterWide := t.usernameToNamespaceToAllowedPSPs[a.GetUser().GetName()][""][a.GetName()]
- return (allowedInNamespace || allowedClusterWide), "", nil
+ if allowedInNamespace || allowedClusterWide {
+ return authorizer.DecisionAllow, "", nil
+ }
+ return authorizer.DecisionNoOpinion, "", nil
}
var _ authorizer.Authorizer = &TestAuthorizer{}
diff --git a/plugin/pkg/auth/authorizer/node/node_authorizer.go b/plugin/pkg/auth/authorizer/node/node_authorizer.go
index 01300801cb4..febe7fbda36 100644
--- a/plugin/pkg/auth/authorizer/node/node_authorizer.go
+++ b/plugin/pkg/auth/authorizer/node/node_authorizer.go
@@ -64,16 +64,16 @@ var (
pvResource = api.Resource("persistentvolumes")
)
-func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (bool, string, error) {
+func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
nodeName, isNode := r.identifier.NodeIdentity(attrs.GetUser())
if !isNode {
// reject requests from non-nodes
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
if len(nodeName) == 0 {
// reject requests from unidentifiable nodes
glog.V(2).Infof("NODE DENY: unknown node for user %q", attrs.GetUser().GetName())
- return false, fmt.Sprintf("unknown node for user %q", attrs.GetUser().GetName()), nil
+ return authorizer.DecisionNoOpinion, fmt.Sprintf("unknown node for user %q", attrs.GetUser().GetName()), nil
}
// subdivide access to specific resources
@@ -92,31 +92,34 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (bool, string, e
}
// Access to other resources is not subdivided, so just evaluate against the statically defined node rules
- return rbac.RulesAllow(attrs, r.nodeRules...), "", nil
+ if rbac.RulesAllow(attrs, r.nodeRules...) {
+ return authorizer.DecisionAllow, "", nil
+ }
+ return authorizer.DecisionNoOpinion, "", nil
}
// authorizeGet authorizes "get" requests to objects of the specified type if they are related to the specified node
-func (r *NodeAuthorizer) authorizeGet(nodeName string, startingType vertexType, attrs authorizer.Attributes) (bool, string, error) {
+func (r *NodeAuthorizer) authorizeGet(nodeName string, startingType vertexType, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
if attrs.GetVerb() != "get" || len(attrs.GetName()) == 0 {
glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
- return false, "can only get individual resources of this type", nil
+ return authorizer.DecisionNoOpinion, "can only get individual resources of this type", nil
}
if len(attrs.GetSubresource()) > 0 {
glog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
- return false, "cannot get subresource", nil
+ return authorizer.DecisionNoOpinion, "cannot get subresource", nil
}
ok, err := r.hasPathFrom(nodeName, startingType, attrs.GetNamespace(), attrs.GetName())
if err != nil {
glog.V(2).Infof("NODE DENY: %v", err)
- return false, "no path found to object", nil
+ return authorizer.DecisionNoOpinion, "no path found to object", nil
}
if !ok {
glog.V(2).Infof("NODE DENY: %q %#v", nodeName, attrs)
- return false, "no path found to object", nil
+ return authorizer.DecisionNoOpinion, "no path found to object", nil
}
- return ok, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// hasPathFrom returns true if there is a directed path from the specified type/namespace/name to the specified Node
diff --git a/plugin/pkg/auth/authorizer/node/node_authorizer_test.go b/plugin/pkg/auth/authorizer/node/node_authorizer_test.go
index 39f10b62ee5..b4cf82d6a14 100644
--- a/plugin/pkg/auth/authorizer/node/node_authorizer_test.go
+++ b/plugin/pkg/auth/authorizer/node/node_authorizer_test.go
@@ -57,71 +57,71 @@ func TestAuthorizer(t *testing.T) {
tests := []struct {
name string
attrs authorizer.AttributesRecord
- expect bool
+ expect authorizer.Decision
}{
{
name: "allowed configmap",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed shared secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed shared secret via pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret-pv0-pod0-node0-ns0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumeclaims", Name: "pvc0-pod0-node0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed pv",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node0-ns0", Namespace: ""},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "disallowed configmap",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed shared secret via pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret-pv0-pod0-node1-ns0", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumeclaims", Name: "pvc0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed pv",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node1-ns0", Namespace: ""},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
- ok, _, _ := authz.Authorize(tc.attrs)
- if ok != tc.expect {
- t.Errorf("expected %v, got %v", tc.expect, ok)
+ decision, _, _ := authz.Authorize(tc.attrs)
+ if decision != tc.expect {
+ t.Errorf("expected %v, got %v", tc.expect, decision)
}
})
}
@@ -186,13 +186,13 @@ func TestAuthorizerSharedResources(t *testing.T) {
}
for i, tc := range testcases {
- ok, _, err := authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret})
+ decision, _, err := authz.Authorize(authorizer.AttributesRecord{User: tc.User, ResourceRequest: true, Verb: "get", Resource: "secrets", Namespace: "ns1", Name: tc.Secret})
if err != nil {
t.Errorf("%d: unexpected error: %v", i, err)
continue
}
- if ok != tc.ExpectAllowed {
- t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, ok)
+ if (decision == authorizer.DecisionAllow) != tc.ExpectAllowed {
+ t.Errorf("%d: expected %v, got %v", i, tc.ExpectAllowed, decision)
}
}
}
@@ -301,47 +301,47 @@ func BenchmarkAuthorization(b *testing.B) {
tests := []struct {
name string
attrs authorizer.AttributesRecord
- expect bool
+ expect authorizer.Decision
}{
{
name: "allowed configmap",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-pod0-node0", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "allowed shared secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-shared", Namespace: "ns0"},
- expect: true,
+ expect: authorizer.DecisionAllow,
},
{
name: "disallowed configmap",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "configmaps", Name: "configmap0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed secret via pod",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed shared secret via pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "secrets", Name: "secret-pv0-pod0-node1-ns0", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed pvc",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumeclaims", Name: "pvc0-pod0-node1", Namespace: "ns0"},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
{
name: "disallowed pv",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "persistentvolumes", Name: "pv0-pod0-node1-ns0", Namespace: ""},
- expect: false,
+ expect: authorizer.DecisionNoOpinion,
},
}
@@ -349,9 +349,9 @@ func BenchmarkAuthorization(b *testing.B) {
for _, tc := range tests {
b.Run(tc.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
- ok, _, _ := authz.Authorize(tc.attrs)
- if ok != tc.expect {
- b.Errorf("expected %v, got %v", tc.expect, ok)
+ decision, _, _ := authz.Authorize(tc.attrs)
+ if decision != tc.expect {
+ b.Errorf("expected %v, got %v", tc.expect, decision)
}
}
})
diff --git a/plugin/pkg/auth/authorizer/rbac/rbac.go b/plugin/pkg/auth/authorizer/rbac/rbac.go
index 090c11febc4..92094807630 100644
--- a/plugin/pkg/auth/authorizer/rbac/rbac.go
+++ b/plugin/pkg/auth/authorizer/rbac/rbac.go
@@ -69,12 +69,12 @@ func (v *authorizingVisitor) visit(rule *rbac.PolicyRule, err error) bool {
return true
}
-func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (bool, string, error) {
+func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (authorizer.Decision, string, error) {
ruleCheckingVisitor := &authorizingVisitor{requestAttributes: requestAttributes}
r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)
if ruleCheckingVisitor.allowed {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// Build a detailed log of the denial.
@@ -120,7 +120,7 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (boo
if len(ruleCheckingVisitor.errors) > 0 {
reason = fmt.Sprintf("%v", utilerrors.NewAggregate(ruleCheckingVisitor.errors))
}
- return false, reason, nil
+ return authorizer.DecisionNoOpinion, reason, nil
}
func (r *RBACAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
diff --git a/plugin/pkg/auth/authorizer/rbac/rbac_test.go b/plugin/pkg/auth/authorizer/rbac/rbac_test.go
index db8a385f0af..d4425a60476 100644
--- a/plugin/pkg/auth/authorizer/rbac/rbac_test.go
+++ b/plugin/pkg/auth/authorizer/rbac/rbac_test.go
@@ -247,13 +247,13 @@ func TestAuthorizer(t *testing.T) {
ruleResolver, _ := rbacregistryvalidation.NewTestRuleResolver(tt.roles, tt.roleBindings, tt.clusterRoles, tt.clusterRoleBindings)
a := RBACAuthorizer{ruleResolver}
for _, attr := range tt.shouldPass {
- if authorized, _, _ := a.Authorize(attr); !authorized {
+ if decision, _, _ := a.Authorize(attr); decision != authorizer.DecisionAllow {
t.Errorf("case %d: incorrectly restricted %s", i, attr)
}
}
for _, attr := range tt.shouldFail {
- if authorized, _, _ := a.Authorize(attr); authorized {
+ if decision, _, _ := a.Authorize(attr); decision == authorizer.DecisionAllow {
t.Errorf("case %d: incorrectly passed %s", i, attr)
}
}
diff --git a/staging/src/k8s.io/api/authorization/v1/generated.pb.go b/staging/src/k8s.io/api/authorization/v1/generated.pb.go
index 0795a645492..d34d105f4c4 100644
--- a/staging/src/k8s.io/api/authorization/v1/generated.pb.go
+++ b/staging/src/k8s.io/api/authorization/v1/generated.pb.go
@@ -730,6 +730,14 @@ func (m *SubjectAccessReviewStatus) MarshalTo(dAtA []byte) (int, error) {
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.EvaluationError)))
i += copy(dAtA[i:], m.EvaluationError)
+ dAtA[i] = 0x20
+ i++
+ if m.Denied {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
return i, nil
}
@@ -1015,6 +1023,7 @@ func (m *SubjectAccessReviewStatus) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
l = len(m.EvaluationError)
n += 1 + l + sovGenerated(uint64(l))
+ n += 2
return n
}
@@ -1205,6 +1214,7 @@ func (this *SubjectAccessReviewStatus) String() string {
`Allowed:` + fmt.Sprintf("%v", this.Allowed) + `,`,
`Reason:` + fmt.Sprintf("%v", this.Reason) + `,`,
`EvaluationError:` + fmt.Sprintf("%v", this.EvaluationError) + `,`,
+ `Denied:` + fmt.Sprintf("%v", this.Denied) + `,`,
`}`,
}, "")
return s
@@ -3130,6 +3140,26 @@ func (m *SubjectAccessReviewStatus) Unmarshal(dAtA []byte) error {
}
m.EvaluationError = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Denied", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Denied = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -3422,77 +3452,77 @@ func init() {
}
var fileDescriptorGenerated = []byte{
- // 1137 bytes of a gzipped FileDescriptorProto
+ // 1152 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
- 0x14, 0xf7, 0xae, 0xed, 0xc4, 0x1e, 0x37, 0x24, 0x9d, 0x28, 0xcd, 0x36, 0x15, 0x76, 0xb4, 0x48,
- 0x90, 0x8a, 0xb2, 0x4b, 0x4c, 0xdb, 0x44, 0x95, 0x2a, 0x14, 0xab, 0x11, 0x8a, 0xd4, 0x96, 0x6a,
+ 0x14, 0xf7, 0xae, 0xed, 0xd4, 0x1e, 0x37, 0x24, 0x9d, 0x28, 0xcd, 0x36, 0x15, 0x76, 0xb4, 0x48,
+ 0x90, 0x8a, 0xb2, 0x4b, 0x4c, 0xdb, 0x44, 0x95, 0x2a, 0x14, 0x2b, 0x11, 0x8a, 0xd4, 0x96, 0x6a,
0xa2, 0x44, 0xa2, 0x08, 0xc4, 0x78, 0x3d, 0xb1, 0x97, 0xd8, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x38,
- 0x55, 0xe2, 0x0b, 0x70, 0xe4, 0xc0, 0x81, 0x6f, 0x80, 0x90, 0x90, 0xb8, 0x71, 0xe0, 0x80, 0x72,
- 0xec, 0xb1, 0x07, 0x64, 0x91, 0xe5, 0xcc, 0x77, 0x40, 0x33, 0x3b, 0xf6, 0xae, 0x93, 0xb5, 0x9b,
- 0x70, 0xa0, 0x97, 0xde, 0x76, 0xdf, 0xef, 0xf7, 0xfe, 0xcc, 0x7b, 0x6f, 0xde, 0x3c, 0xf0, 0xe0,
- 0x70, 0x93, 0x59, 0xae, 0x6f, 0x1f, 0x86, 0x4d, 0x42, 0x3d, 0xc2, 0x09, 0xb3, 0xfb, 0xc4, 0x6b,
- 0xf9, 0xd4, 0x56, 0x00, 0x0e, 0x5c, 0x1b, 0x87, 0xbc, 0xe3, 0x53, 0xf7, 0x1b, 0xcc, 0x5d, 0xdf,
- 0xb3, 0xfb, 0xeb, 0x76, 0x9b, 0x78, 0x84, 0x62, 0x4e, 0x5a, 0x56, 0x40, 0x7d, 0xee, 0xc3, 0x1b,
- 0x31, 0xd9, 0xc2, 0x81, 0x6b, 0x8d, 0x91, 0xad, 0xfe, 0xfa, 0xca, 0x7b, 0x6d, 0x97, 0x77, 0xc2,
- 0xa6, 0xe5, 0xf8, 0x3d, 0xbb, 0xed, 0xb7, 0x7d, 0x5b, 0xea, 0x34, 0xc3, 0x03, 0xf9, 0x27, 0x7f,
- 0xe4, 0x57, 0x6c, 0x6b, 0xe5, 0x76, 0xe2, 0xb8, 0x87, 0x9d, 0x8e, 0xeb, 0x11, 0x7a, 0x6c, 0x07,
- 0x87, 0x6d, 0x21, 0x60, 0x76, 0x8f, 0x70, 0x9c, 0x11, 0xc1, 0x8a, 0x3d, 0x49, 0x8b, 0x86, 0x1e,
- 0x77, 0x7b, 0xe4, 0x9c, 0xc2, 0xdd, 0x97, 0x29, 0x30, 0xa7, 0x43, 0x7a, 0xf8, 0x9c, 0xde, 0x07,
- 0x93, 0xf4, 0x42, 0xee, 0x76, 0x6d, 0xd7, 0xe3, 0x8c, 0xd3, 0xb3, 0x4a, 0xe6, 0x06, 0x00, 0xdb,
- 0x5f, 0x73, 0x8a, 0xf7, 0x71, 0x37, 0x24, 0xb0, 0x06, 0x8a, 0x2e, 0x27, 0x3d, 0x66, 0x68, 0xab,
- 0xf9, 0xb5, 0x72, 0xa3, 0x1c, 0x0d, 0x6a, 0xc5, 0x1d, 0x21, 0x40, 0xb1, 0xfc, 0x5e, 0xe9, 0xfb,
- 0x1f, 0x6b, 0xb9, 0x67, 0x7f, 0xae, 0xe6, 0xcc, 0x5f, 0x74, 0x60, 0x3c, 0xf4, 0x1d, 0xdc, 0xdd,
- 0x0d, 0x9b, 0x5f, 0x12, 0x87, 0x6f, 0x39, 0x0e, 0x61, 0x0c, 0x91, 0xbe, 0x4b, 0x8e, 0xe0, 0x17,
- 0xa0, 0x24, 0xd2, 0xd1, 0xc2, 0x1c, 0x1b, 0xda, 0xaa, 0xb6, 0x56, 0xa9, 0xbf, 0x6f, 0x25, 0x85,
- 0x18, 0x45, 0x67, 0x05, 0x87, 0x6d, 0x21, 0x60, 0x96, 0x60, 0x5b, 0xfd, 0x75, 0xeb, 0x63, 0x69,
- 0xeb, 0x11, 0xe1, 0xb8, 0x01, 0x4f, 0x06, 0xb5, 0x5c, 0x34, 0xa8, 0x81, 0x44, 0x86, 0x46, 0x56,
- 0xe1, 0x3e, 0x28, 0xb0, 0x80, 0x38, 0x86, 0x2e, 0xad, 0xdf, 0xb6, 0xa6, 0x94, 0xd9, 0xca, 0x88,
- 0x70, 0x37, 0x20, 0x4e, 0xe3, 0x8a, 0xf2, 0x50, 0x10, 0x7f, 0x48, 0xda, 0x83, 0x9f, 0x83, 0x19,
- 0xc6, 0x31, 0x0f, 0x99, 0x91, 0x97, 0x96, 0xef, 0x5e, 0xda, 0xb2, 0xd4, 0x6e, 0xbc, 0xa1, 0x6c,
- 0xcf, 0xc4, 0xff, 0x48, 0x59, 0x35, 0x3f, 0x05, 0x4b, 0x8f, 0x7d, 0x0f, 0x11, 0xe6, 0x87, 0xd4,
- 0x21, 0x5b, 0x9c, 0x53, 0xb7, 0x19, 0x72, 0xc2, 0xe0, 0x2a, 0x28, 0x04, 0x98, 0x77, 0x64, 0xba,
- 0xca, 0x49, 0x68, 0x4f, 0x30, 0xef, 0x20, 0x89, 0x08, 0x46, 0x9f, 0xd0, 0xa6, 0x3c, 0x72, 0x8a,
- 0xb1, 0x4f, 0x68, 0x13, 0x49, 0xc4, 0xfc, 0x0a, 0xcc, 0xa7, 0x8c, 0xa3, 0xb0, 0x2b, 0x2b, 0x2a,
- 0xa0, 0xb1, 0x8a, 0x0a, 0x0d, 0x86, 0x62, 0x39, 0xbc, 0x0f, 0xe6, 0xbd, 0x44, 0x67, 0x0f, 0x3d,
- 0x64, 0x86, 0x2e, 0xa9, 0x8b, 0xd1, 0xa0, 0x96, 0x36, 0x27, 0x20, 0x74, 0x96, 0x6b, 0xfe, 0xa6,
- 0x03, 0x98, 0x71, 0x1a, 0x1b, 0x94, 0x3d, 0xdc, 0x23, 0x2c, 0xc0, 0x0e, 0x51, 0x47, 0xba, 0xaa,
- 0x02, 0x2e, 0x3f, 0x1e, 0x02, 0x28, 0xe1, 0xbc, 0xfc, 0x70, 0xf0, 0x2d, 0x50, 0x6c, 0x53, 0x3f,
- 0x0c, 0x64, 0x61, 0xca, 0x8d, 0x39, 0x45, 0x29, 0x7e, 0x24, 0x84, 0x28, 0xc6, 0xe0, 0x4d, 0x30,
- 0xdb, 0x27, 0x94, 0xb9, 0xbe, 0x67, 0x14, 0x24, 0x6d, 0x5e, 0xd1, 0x66, 0xf7, 0x63, 0x31, 0x1a,
- 0xe2, 0xf0, 0x16, 0x28, 0x51, 0x15, 0xb8, 0x51, 0x94, 0xdc, 0x05, 0xc5, 0x2d, 0x8d, 0x32, 0x38,
- 0x62, 0xc0, 0x3b, 0xa0, 0xc2, 0xc2, 0xe6, 0x48, 0x61, 0x46, 0x2a, 0x2c, 0x2a, 0x85, 0xca, 0x6e,
- 0x02, 0xa1, 0x34, 0x4f, 0x1c, 0x4b, 0x9c, 0xd1, 0x98, 0x1d, 0x3f, 0x96, 0x48, 0x01, 0x92, 0x88,
- 0xf9, 0xbb, 0x06, 0xae, 0x5c, 0xae, 0x62, 0xef, 0x82, 0x32, 0x0e, 0x5c, 0x79, 0xec, 0x61, 0xad,
- 0xe6, 0x44, 0x5e, 0xb7, 0x9e, 0xec, 0xc4, 0x42, 0x94, 0xe0, 0x82, 0x3c, 0x0c, 0x46, 0xb4, 0xf4,
- 0x88, 0x3c, 0x74, 0xc9, 0x50, 0x82, 0xc3, 0x0d, 0x30, 0x37, 0xfc, 0x91, 0x45, 0x32, 0x0a, 0x52,
- 0xe1, 0x6a, 0x34, 0xa8, 0xcd, 0xa1, 0x34, 0x80, 0xc6, 0x79, 0xe6, 0xaf, 0x3a, 0x58, 0xde, 0x25,
- 0xdd, 0x83, 0x57, 0x33, 0x0b, 0x9e, 0x8e, 0xcd, 0x82, 0xcd, 0xe9, 0x37, 0x36, 0x3b, 0xca, 0x57,
- 0x36, 0x0f, 0x7e, 0xd0, 0xc1, 0x8d, 0x29, 0x31, 0xc1, 0x23, 0x00, 0xe9, 0xb9, 0xeb, 0xa5, 0xf2,
- 0x68, 0x4f, 0x8d, 0xe5, 0xfc, 0xad, 0x6c, 0x5c, 0x8b, 0x06, 0xb5, 0x8c, 0xdb, 0x8a, 0x32, 0x5c,
- 0xc0, 0x6f, 0x35, 0xb0, 0xe4, 0x65, 0x4d, 0x2a, 0x95, 0xe6, 0xfa, 0x54, 0xe7, 0x99, 0x33, 0xae,
- 0x71, 0x3d, 0x1a, 0xd4, 0xb2, 0xc7, 0x1f, 0xca, 0xf6, 0x25, 0x5e, 0x99, 0x6b, 0xa9, 0xf4, 0x88,
- 0x0b, 0xf2, 0xff, 0xf5, 0xd5, 0x27, 0x63, 0x7d, 0xb5, 0x71, 0xd1, 0xbe, 0x4a, 0x05, 0x39, 0xb1,
- 0xad, 0x3e, 0x3b, 0xd3, 0x56, 0x77, 0x2e, 0xd2, 0x56, 0x69, 0xc3, 0xd3, 0xbb, 0xea, 0x11, 0x58,
- 0x99, 0x1c, 0xd0, 0xa5, 0x87, 0xb3, 0xf9, 0x93, 0x0e, 0x16, 0x5f, 0x3f, 0xf3, 0x97, 0xb9, 0xd6,
- 0x7f, 0x14, 0xc0, 0xf2, 0xeb, 0x2b, 0x3d, 0x69, 0xd1, 0x09, 0x19, 0xa1, 0xea, 0x19, 0x1f, 0x15,
- 0x67, 0x8f, 0x11, 0x8a, 0x24, 0x02, 0x4d, 0x30, 0xd3, 0x8e, 0x5f, 0xb7, 0xf8, 0xfd, 0x01, 0x22,
- 0xc1, 0xea, 0x69, 0x53, 0x08, 0x6c, 0x81, 0x22, 0x11, 0x7b, 0xab, 0x51, 0x5c, 0xcd, 0xaf, 0x55,
- 0xea, 0x1f, 0xfe, 0x97, 0xce, 0xb0, 0xe4, 0xe6, 0xbb, 0xed, 0x71, 0x7a, 0x9c, 0xac, 0x13, 0x52,
- 0x86, 0x62, 0xe3, 0xf0, 0x4d, 0x90, 0x0f, 0xdd, 0x96, 0x7a, 0xed, 0x2b, 0x8a, 0x92, 0xdf, 0xdb,
- 0x79, 0x80, 0x84, 0x7c, 0x05, 0xab, 0xe5, 0x59, 0x9a, 0x80, 0x0b, 0x20, 0x7f, 0x48, 0x8e, 0xe3,
- 0x0b, 0x85, 0xc4, 0x27, 0xbc, 0x0f, 0x8a, 0x7d, 0xb1, 0x57, 0xab, 0xfc, 0xbe, 0x33, 0x35, 0xc8,
- 0x64, 0x0d, 0x47, 0xb1, 0xd6, 0x3d, 0x7d, 0x53, 0x33, 0x7f, 0xd6, 0xc0, 0xf5, 0x89, 0xed, 0x27,
- 0xd6, 0x1d, 0xdc, 0xed, 0xfa, 0x47, 0xa4, 0x25, 0xdd, 0x96, 0x92, 0x75, 0x67, 0x2b, 0x16, 0xa3,
- 0x21, 0x0e, 0xdf, 0x06, 0x33, 0x94, 0x60, 0xe6, 0x7b, 0x6a, 0xc5, 0x1a, 0x75, 0x2e, 0x92, 0x52,
- 0xa4, 0x50, 0xb8, 0x05, 0xe6, 0x89, 0x70, 0x2f, 0xe3, 0xda, 0xa6, 0xd4, 0x1f, 0x56, 0x6a, 0x59,
- 0x29, 0xcc, 0x6f, 0x8f, 0xc3, 0xe8, 0x2c, 0xdf, 0xfc, 0x47, 0x07, 0xc6, 0xa4, 0x91, 0x05, 0x0f,
- 0x92, 0x1d, 0x43, 0x82, 0x72, 0xcd, 0xa9, 0xd4, 0x6f, 0x5e, 0xa8, 0xf1, 0x85, 0x46, 0x63, 0x49,
- 0x05, 0x32, 0x97, 0x96, 0xa6, 0x56, 0x12, 0xf9, 0x0b, 0x29, 0x58, 0xf0, 0xc6, 0x77, 0xe1, 0x78,
- 0x59, 0xaa, 0xd4, 0x6f, 0x5d, 0xb4, 0xcd, 0xa5, 0x37, 0x43, 0x79, 0x5b, 0x38, 0x03, 0x30, 0x74,
- 0xce, 0x3e, 0xac, 0x03, 0xe0, 0x7a, 0x8e, 0xdf, 0x0b, 0xba, 0x84, 0x13, 0x99, 0xb6, 0x52, 0x32,
- 0xdf, 0x76, 0x46, 0x08, 0x4a, 0xb1, 0xb2, 0xf2, 0x5d, 0xb8, 0x5c, 0xbe, 0x1b, 0x6b, 0x27, 0xa7,
- 0xd5, 0xdc, 0xf3, 0xd3, 0x6a, 0xee, 0xc5, 0x69, 0x35, 0xf7, 0x2c, 0xaa, 0x6a, 0x27, 0x51, 0x55,
- 0x7b, 0x1e, 0x55, 0xb5, 0x17, 0x51, 0x55, 0xfb, 0x2b, 0xaa, 0x6a, 0xdf, 0xfd, 0x5d, 0xcd, 0x3d,
- 0xd5, 0xfb, 0xeb, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xd9, 0x3f, 0xd9, 0x21, 0x54, 0x0f, 0x00,
- 0x00,
+ 0x55, 0xe2, 0x0b, 0x70, 0xe4, 0xc0, 0x81, 0x6f, 0xc0, 0x05, 0x89, 0x1b, 0x07, 0x0e, 0x28, 0xc7,
+ 0x1e, 0x8b, 0x84, 0x2c, 0xb2, 0x9c, 0xf9, 0x0e, 0x68, 0x66, 0xc7, 0xde, 0x75, 0xb2, 0x76, 0x13,
+ 0x0e, 0xf4, 0xd2, 0xdb, 0xee, 0xfb, 0xfd, 0xde, 0x9f, 0x79, 0x7f, 0x66, 0x1e, 0xd8, 0x3a, 0xdc,
+ 0x60, 0x96, 0xeb, 0xdb, 0x87, 0x61, 0x93, 0x50, 0x8f, 0x70, 0xc2, 0xec, 0x3e, 0xf1, 0x5a, 0x3e,
+ 0xb5, 0x15, 0x80, 0x03, 0xd7, 0xc6, 0x21, 0xef, 0xf8, 0xd4, 0xfd, 0x06, 0x73, 0xd7, 0xf7, 0xec,
+ 0xfe, 0x9a, 0xdd, 0x26, 0x1e, 0xa1, 0x98, 0x93, 0x96, 0x15, 0x50, 0x9f, 0xfb, 0xf0, 0x66, 0x4c,
+ 0xb6, 0x70, 0xe0, 0x5a, 0x63, 0x64, 0xab, 0xbf, 0xb6, 0xfc, 0x5e, 0xdb, 0xe5, 0x9d, 0xb0, 0x69,
+ 0x39, 0x7e, 0xcf, 0x6e, 0xfb, 0x6d, 0xdf, 0x96, 0x3a, 0xcd, 0xf0, 0x40, 0xfe, 0xc9, 0x1f, 0xf9,
+ 0x15, 0xdb, 0x5a, 0xbe, 0x93, 0x38, 0xee, 0x61, 0xa7, 0xe3, 0x7a, 0x84, 0x1e, 0xdb, 0xc1, 0x61,
+ 0x5b, 0x08, 0x98, 0xdd, 0x23, 0x1c, 0x67, 0x44, 0xb0, 0x6c, 0x4f, 0xd2, 0xa2, 0xa1, 0xc7, 0xdd,
+ 0x1e, 0x39, 0xa7, 0x70, 0xef, 0x65, 0x0a, 0xcc, 0xe9, 0x90, 0x1e, 0x3e, 0xa7, 0xf7, 0xc1, 0x24,
+ 0xbd, 0x90, 0xbb, 0x5d, 0xdb, 0xf5, 0x38, 0xe3, 0xf4, 0xac, 0x92, 0xb9, 0x0e, 0xc0, 0xf6, 0xd7,
+ 0x9c, 0xe2, 0x7d, 0xdc, 0x0d, 0x09, 0xac, 0x81, 0xa2, 0xcb, 0x49, 0x8f, 0x19, 0xda, 0x4a, 0x7e,
+ 0xb5, 0xdc, 0x28, 0x47, 0x83, 0x5a, 0x71, 0x47, 0x08, 0x50, 0x2c, 0xbf, 0x5f, 0xfa, 0xfe, 0xc7,
+ 0x5a, 0xee, 0xd9, 0x9f, 0x2b, 0x39, 0xf3, 0x67, 0x1d, 0x18, 0x0f, 0x7d, 0x07, 0x77, 0x77, 0xc3,
+ 0xe6, 0x97, 0xc4, 0xe1, 0x9b, 0x8e, 0x43, 0x18, 0x43, 0xa4, 0xef, 0x92, 0x23, 0xf8, 0x05, 0x28,
+ 0x89, 0x74, 0xb4, 0x30, 0xc7, 0x86, 0xb6, 0xa2, 0xad, 0x56, 0xea, 0xef, 0x5b, 0x49, 0x21, 0x46,
+ 0xd1, 0x59, 0xc1, 0x61, 0x5b, 0x08, 0x98, 0x25, 0xd8, 0x56, 0x7f, 0xcd, 0xfa, 0x58, 0xda, 0x7a,
+ 0x44, 0x38, 0x6e, 0xc0, 0x93, 0x41, 0x2d, 0x17, 0x0d, 0x6a, 0x20, 0x91, 0xa1, 0x91, 0x55, 0xb8,
+ 0x0f, 0x0a, 0x2c, 0x20, 0x8e, 0xa1, 0x4b, 0xeb, 0x77, 0xac, 0x29, 0x65, 0xb6, 0x32, 0x22, 0xdc,
+ 0x0d, 0x88, 0xd3, 0xb8, 0xaa, 0x3c, 0x14, 0xc4, 0x1f, 0x92, 0xf6, 0xe0, 0xe7, 0x60, 0x86, 0x71,
+ 0xcc, 0x43, 0x66, 0xe4, 0xa5, 0xe5, 0x7b, 0x97, 0xb6, 0x2c, 0xb5, 0x1b, 0x6f, 0x28, 0xdb, 0x33,
+ 0xf1, 0x3f, 0x52, 0x56, 0xcd, 0x4f, 0xc1, 0xe2, 0x63, 0xdf, 0x43, 0x84, 0xf9, 0x21, 0x75, 0xc8,
+ 0x26, 0xe7, 0xd4, 0x6d, 0x86, 0x9c, 0x30, 0xb8, 0x02, 0x0a, 0x01, 0xe6, 0x1d, 0x99, 0xae, 0x72,
+ 0x12, 0xda, 0x13, 0xcc, 0x3b, 0x48, 0x22, 0x82, 0xd1, 0x27, 0xb4, 0x29, 0x8f, 0x9c, 0x62, 0xec,
+ 0x13, 0xda, 0x44, 0x12, 0x31, 0xbf, 0x02, 0x73, 0x29, 0xe3, 0x28, 0xec, 0xca, 0x8a, 0x0a, 0x68,
+ 0xac, 0xa2, 0x42, 0x83, 0xa1, 0x58, 0x0e, 0x1f, 0x80, 0x39, 0x2f, 0xd1, 0xd9, 0x43, 0x0f, 0x99,
+ 0xa1, 0x4b, 0xea, 0x42, 0x34, 0xa8, 0xa5, 0xcd, 0x09, 0x08, 0x9d, 0xe5, 0x9a, 0xbf, 0xea, 0x00,
+ 0x66, 0x9c, 0xc6, 0x06, 0x65, 0x0f, 0xf7, 0x08, 0x0b, 0xb0, 0x43, 0xd4, 0x91, 0xae, 0xa9, 0x80,
+ 0xcb, 0x8f, 0x87, 0x00, 0x4a, 0x38, 0x2f, 0x3f, 0x1c, 0x7c, 0x0b, 0x14, 0xdb, 0xd4, 0x0f, 0x03,
+ 0x59, 0x98, 0x72, 0x63, 0x56, 0x51, 0x8a, 0x1f, 0x09, 0x21, 0x8a, 0x31, 0x78, 0x0b, 0x5c, 0xe9,
+ 0x13, 0xca, 0x5c, 0xdf, 0x33, 0x0a, 0x92, 0x36, 0xa7, 0x68, 0x57, 0xf6, 0x63, 0x31, 0x1a, 0xe2,
+ 0xf0, 0x36, 0x28, 0x51, 0x15, 0xb8, 0x51, 0x94, 0xdc, 0x79, 0xc5, 0x2d, 0x8d, 0x32, 0x38, 0x62,
+ 0xc0, 0xbb, 0xa0, 0xc2, 0xc2, 0xe6, 0x48, 0x61, 0x46, 0x2a, 0x2c, 0x28, 0x85, 0xca, 0x6e, 0x02,
+ 0xa1, 0x34, 0x4f, 0x1c, 0x4b, 0x9c, 0xd1, 0xb8, 0x32, 0x7e, 0x2c, 0x91, 0x02, 0x24, 0x11, 0xf3,
+ 0x37, 0x0d, 0x5c, 0xbd, 0x5c, 0xc5, 0xde, 0x05, 0x65, 0x1c, 0xb8, 0xf2, 0xd8, 0xc3, 0x5a, 0xcd,
+ 0x8a, 0xbc, 0x6e, 0x3e, 0xd9, 0x89, 0x85, 0x28, 0xc1, 0x05, 0x79, 0x18, 0x8c, 0x68, 0xe9, 0x11,
+ 0x79, 0xe8, 0x92, 0xa1, 0x04, 0x87, 0xeb, 0x60, 0x76, 0xf8, 0x23, 0x8b, 0x64, 0x14, 0xa4, 0xc2,
+ 0xb5, 0x68, 0x50, 0x9b, 0x45, 0x69, 0x00, 0x8d, 0xf3, 0xcc, 0x5f, 0x74, 0xb0, 0xb4, 0x4b, 0xba,
+ 0x07, 0xaf, 0xe6, 0x2e, 0x78, 0x3a, 0x76, 0x17, 0x6c, 0x4c, 0x9f, 0xd8, 0xec, 0x28, 0x5f, 0xd9,
+ 0x7d, 0xf0, 0x83, 0x0e, 0x6e, 0x4e, 0x89, 0x09, 0x1e, 0x01, 0x48, 0xcf, 0x8d, 0x97, 0xca, 0xa3,
+ 0x3d, 0x35, 0x96, 0xf3, 0x53, 0xd9, 0xb8, 0x1e, 0x0d, 0x6a, 0x19, 0xd3, 0x8a, 0x32, 0x5c, 0xc0,
+ 0x6f, 0x35, 0xb0, 0xe8, 0x65, 0xdd, 0x54, 0x2a, 0xcd, 0xf5, 0xa9, 0xce, 0x33, 0xef, 0xb8, 0xc6,
+ 0x8d, 0x68, 0x50, 0xcb, 0xbe, 0xfe, 0x50, 0xb6, 0x2f, 0xf1, 0xca, 0x5c, 0x4f, 0xa5, 0x47, 0x0c,
+ 0xc8, 0xff, 0xd7, 0x57, 0x9f, 0x8c, 0xf5, 0xd5, 0xfa, 0x45, 0xfb, 0x2a, 0x15, 0xe4, 0xc4, 0xb6,
+ 0xfa, 0xec, 0x4c, 0x5b, 0xdd, 0xbd, 0x48, 0x5b, 0xa5, 0x0d, 0x4f, 0xef, 0xaa, 0x47, 0x60, 0x79,
+ 0x72, 0x40, 0x97, 0xbe, 0x9c, 0xcd, 0x9f, 0x74, 0xb0, 0xf0, 0xfa, 0x99, 0xbf, 0xcc, 0x58, 0xff,
+ 0x5e, 0x00, 0x4b, 0xaf, 0x47, 0x7a, 0xd2, 0xa2, 0x13, 0x32, 0x42, 0xd5, 0x33, 0x3e, 0x2a, 0xce,
+ 0x1e, 0x23, 0x14, 0x49, 0x04, 0x9a, 0x60, 0xa6, 0x1d, 0xbf, 0x6e, 0xf1, 0xfb, 0x03, 0x44, 0x82,
+ 0xd5, 0xd3, 0xa6, 0x10, 0xd8, 0x02, 0x45, 0x22, 0xf6, 0x56, 0xa3, 0xb8, 0x92, 0x5f, 0xad, 0xd4,
+ 0x3f, 0xfc, 0x2f, 0x9d, 0x61, 0xc9, 0xcd, 0x77, 0xdb, 0xe3, 0xf4, 0x38, 0x59, 0x27, 0xa4, 0x0c,
+ 0xc5, 0xc6, 0xe1, 0x9b, 0x20, 0x1f, 0xba, 0x2d, 0xf5, 0xda, 0x57, 0x14, 0x25, 0xbf, 0xb7, 0xb3,
+ 0x85, 0x84, 0x7c, 0x19, 0xab, 0xe5, 0x59, 0x9a, 0x80, 0xf3, 0x20, 0x7f, 0x48, 0x8e, 0xe3, 0x81,
+ 0x42, 0xe2, 0x13, 0x3e, 0x00, 0xc5, 0xbe, 0xd8, 0xab, 0x55, 0x7e, 0xdf, 0x99, 0x1a, 0x64, 0xb2,
+ 0x86, 0xa3, 0x58, 0xeb, 0xbe, 0xbe, 0xa1, 0x99, 0x7f, 0x68, 0xe0, 0xc6, 0xc4, 0xf6, 0x13, 0xeb,
+ 0x0e, 0xee, 0x76, 0xfd, 0x23, 0xd2, 0x92, 0x6e, 0x4b, 0xc9, 0xba, 0xb3, 0x19, 0x8b, 0xd1, 0x10,
+ 0x87, 0x6f, 0x83, 0x19, 0x4a, 0x30, 0xf3, 0x3d, 0xb5, 0x62, 0x8d, 0x3a, 0x17, 0x49, 0x29, 0x52,
+ 0x28, 0xdc, 0x04, 0x73, 0x44, 0xb8, 0x97, 0x71, 0x6d, 0x53, 0xea, 0x0f, 0x2b, 0xb5, 0xa4, 0x14,
+ 0xe6, 0xb6, 0xc7, 0x61, 0x74, 0x96, 0x2f, 0x5c, 0xb5, 0x88, 0xe7, 0x92, 0x96, 0xdc, 0xc1, 0x4a,
+ 0x89, 0xab, 0x2d, 0x29, 0x45, 0x0a, 0x35, 0xff, 0xd1, 0x81, 0x31, 0xe9, 0x6a, 0x83, 0x07, 0xc9,
+ 0x2e, 0x22, 0x41, 0xb9, 0x0e, 0x55, 0xea, 0xb7, 0x2e, 0x34, 0x20, 0x42, 0xa3, 0xb1, 0xa8, 0xdc,
+ 0xce, 0xa6, 0xa5, 0xa9, 0xd5, 0x45, 0xfe, 0x42, 0x0a, 0xe6, 0xbd, 0xf1, 0x9d, 0x39, 0x5e, 0xaa,
+ 0x2a, 0xf5, 0xdb, 0x17, 0x1d, 0x07, 0xe9, 0xcd, 0x50, 0xde, 0xe6, 0xcf, 0x00, 0x0c, 0x9d, 0xb3,
+ 0x0f, 0xeb, 0x00, 0xb8, 0x9e, 0xe3, 0xf7, 0x82, 0x2e, 0xe1, 0x44, 0xa6, 0xb7, 0x94, 0xdc, 0x83,
+ 0x3b, 0x23, 0x04, 0xa5, 0x58, 0x59, 0x75, 0x29, 0x5c, 0xae, 0x2e, 0x8d, 0xd5, 0x93, 0xd3, 0x6a,
+ 0xee, 0xf9, 0x69, 0x35, 0xf7, 0xe2, 0xb4, 0x9a, 0x7b, 0x16, 0x55, 0xb5, 0x93, 0xa8, 0xaa, 0x3d,
+ 0x8f, 0xaa, 0xda, 0x8b, 0xa8, 0xaa, 0xfd, 0x15, 0x55, 0xb5, 0xef, 0xfe, 0xae, 0xe6, 0x9e, 0xea,
+ 0xfd, 0xb5, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd6, 0x0e, 0xab, 0x82, 0x7c, 0x0f, 0x00, 0x00,
}
diff --git a/staging/src/k8s.io/api/authorization/v1/generated.proto b/staging/src/k8s.io/api/authorization/v1/generated.proto
index de8323fc14a..28c8d660365 100644
--- a/staging/src/k8s.io/api/authorization/v1/generated.proto
+++ b/staging/src/k8s.io/api/authorization/v1/generated.proto
@@ -226,9 +226,16 @@ message SubjectAccessReviewSpec {
// SubjectAccessReviewStatus
message SubjectAccessReviewStatus {
- // Allowed is required. True if the action would be allowed, false otherwise.
+ // Allowed is required. True if the action would be allowed, false otherwise.
optional bool allowed = 1;
+ // Denied is optional. True if the action would be denied, otherwise
+ // false. If both allowed is false and denied is false, then the
+ // authorizer has no opinion on whether to authorize the action. Denied
+ // may not be true if Allowed is true.
+ // +optional
+ optional bool denied = 4;
+
// Reason is optional. It indicates why a request was allowed or denied.
// +optional
optional string reason = 2;
diff --git a/staging/src/k8s.io/api/authorization/v1/types.go b/staging/src/k8s.io/api/authorization/v1/types.go
index 23b5ae7051c..86b05c54e37 100644
--- a/staging/src/k8s.io/api/authorization/v1/types.go
+++ b/staging/src/k8s.io/api/authorization/v1/types.go
@@ -169,8 +169,14 @@ type SelfSubjectAccessReviewSpec struct {
// SubjectAccessReviewStatus
type SubjectAccessReviewStatus struct {
- // Allowed is required. True if the action would be allowed, false otherwise.
+ // Allowed is required. True if the action would be allowed, false otherwise.
Allowed bool `json:"allowed" protobuf:"varint,1,opt,name=allowed"`
+ // Denied is optional. True if the action would be denied, otherwise
+ // false. If both allowed is false and denied is false, then the
+ // authorizer has no opinion on whether to authorize the action. Denied
+ // may not be true if Allowed is true.
+ // +optional
+ Denied bool `json:"denied,omitempty" protobuf:"varint,4,opt,name=denied"`
// Reason is optional. It indicates why a request was allowed or denied.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,2,opt,name=reason"`
diff --git a/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go
index 1e3f780d908..85503660c58 100644
--- a/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go
+++ b/staging/src/k8s.io/api/authorization/v1/types_swagger_doc_generated.go
@@ -148,7 +148,8 @@ func (SubjectAccessReviewSpec) SwaggerDoc() map[string]string {
var map_SubjectAccessReviewStatus = map[string]string{
"": "SubjectAccessReviewStatus",
- "allowed": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "allowed": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "denied": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true.",
"reason": "Reason is optional. It indicates why a request was allowed or denied.",
"evaluationError": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.",
}
diff --git a/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go b/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go
index e1f49d46467..9b1ad299e2a 100644
--- a/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go
+++ b/staging/src/k8s.io/api/authorization/v1beta1/generated.pb.go
@@ -730,6 +730,14 @@ func (m *SubjectAccessReviewStatus) MarshalTo(dAtA []byte) (int, error) {
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.EvaluationError)))
i += copy(dAtA[i:], m.EvaluationError)
+ dAtA[i] = 0x20
+ i++
+ if m.Denied {
+ dAtA[i] = 1
+ } else {
+ dAtA[i] = 0
+ }
+ i++
return i, nil
}
@@ -1015,6 +1023,7 @@ func (m *SubjectAccessReviewStatus) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
l = len(m.EvaluationError)
n += 1 + l + sovGenerated(uint64(l))
+ n += 2
return n
}
@@ -1205,6 +1214,7 @@ func (this *SubjectAccessReviewStatus) String() string {
`Allowed:` + fmt.Sprintf("%v", this.Allowed) + `,`,
`Reason:` + fmt.Sprintf("%v", this.Reason) + `,`,
`EvaluationError:` + fmt.Sprintf("%v", this.EvaluationError) + `,`,
+ `Denied:` + fmt.Sprintf("%v", this.Denied) + `,`,
`}`,
}, "")
return s
@@ -3130,6 +3140,26 @@ func (m *SubjectAccessReviewStatus) Unmarshal(dAtA []byte) error {
}
m.EvaluationError = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
+ case 4:
+ if wireType != 0 {
+ return fmt.Errorf("proto: wrong wireType = %d for field Denied", wireType)
+ }
+ var v int
+ for shift := uint(0); ; shift += 7 {
+ if shift >= 64 {
+ return ErrIntOverflowGenerated
+ }
+ if iNdEx >= l {
+ return io.ErrUnexpectedEOF
+ }
+ b := dAtA[iNdEx]
+ iNdEx++
+ v |= (int(b) & 0x7F) << shift
+ if b < 0x80 {
+ break
+ }
+ }
+ m.Denied = bool(v != 0)
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -3422,77 +3452,78 @@ func init() {
}
var fileDescriptorGenerated = []byte{
- // 1139 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0xcf, 0x6f, 0x1b, 0x45,
- 0x14, 0xf6, 0xfa, 0x47, 0x62, 0x8f, 0x1b, 0x92, 0x4e, 0x94, 0x66, 0x1b, 0x84, 0x6d, 0x19, 0x09,
- 0x05, 0xd1, 0xee, 0x92, 0x50, 0x48, 0x09, 0xf4, 0x10, 0xab, 0x11, 0x8a, 0xd4, 0x96, 0x6a, 0xa2,
- 0xe4, 0x40, 0x25, 0x60, 0x76, 0x33, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x10, 0x87,
- 0x1e, 0x39, 0x72, 0xe4, 0xc8, 0x89, 0x3b, 0x47, 0x2e, 0x48, 0x70, 0xca, 0xb1, 0xc7, 0x1c, 0x90,
- 0x45, 0x96, 0x3f, 0x82, 0x2b, 0x9a, 0xd9, 0xb1, 0x77, 0x1d, 0xaf, 0xe3, 0x24, 0x87, 0xf6, 0xd2,
- 0xdb, 0xce, 0xfb, 0xde, 0xf7, 0xde, 0x9b, 0x37, 0xef, 0xbd, 0x7d, 0x60, 0xa7, 0x7d, 0x9f, 0x19,
- 0x8e, 0x67, 0xb6, 0x03, 0x8b, 0x50, 0x97, 0x70, 0xc2, 0xcc, 0x1e, 0x71, 0x0f, 0x3c, 0x6a, 0x2a,
- 0x00, 0xfb, 0x8e, 0x89, 0x03, 0xde, 0xf2, 0xa8, 0xf3, 0x3d, 0xe6, 0x8e, 0xe7, 0x9a, 0xbd, 0x35,
- 0x8b, 0x70, 0xbc, 0x66, 0x36, 0x89, 0x4b, 0x28, 0xe6, 0xe4, 0xc0, 0xf0, 0xa9, 0xc7, 0x3d, 0x58,
- 0x8b, 0x18, 0x06, 0xf6, 0x1d, 0x63, 0x84, 0x61, 0x28, 0xc6, 0xca, 0xdd, 0xa6, 0xc3, 0x5b, 0x81,
- 0x65, 0xd8, 0x5e, 0xd7, 0x6c, 0x7a, 0x4d, 0xcf, 0x94, 0x44, 0x2b, 0x38, 0x94, 0x27, 0x79, 0x90,
- 0x5f, 0x91, 0xc1, 0x95, 0x7b, 0x71, 0x08, 0x5d, 0x6c, 0xb7, 0x1c, 0x97, 0xd0, 0x63, 0xd3, 0x6f,
- 0x37, 0x85, 0x80, 0x99, 0x5d, 0xc2, 0xb1, 0xd9, 0x1b, 0x0b, 0x63, 0xc5, 0x9c, 0xc4, 0xa2, 0x81,
- 0xcb, 0x9d, 0x2e, 0x19, 0x23, 0x7c, 0x34, 0x8d, 0xc0, 0xec, 0x16, 0xe9, 0xe2, 0x31, 0xde, 0x07,
- 0x93, 0x78, 0x01, 0x77, 0x3a, 0xa6, 0xe3, 0x72, 0xc6, 0xe9, 0x79, 0x52, 0x7d, 0x03, 0x80, 0xed,
- 0xef, 0x38, 0xc5, 0xfb, 0xb8, 0x13, 0x10, 0x58, 0x05, 0x05, 0x87, 0x93, 0x2e, 0xd3, 0xb5, 0x5a,
- 0x6e, 0xb5, 0xd4, 0x28, 0x85, 0xfd, 0x6a, 0x61, 0x47, 0x08, 0x50, 0x24, 0xdf, 0x2c, 0xfe, 0xfc,
- 0x4b, 0x35, 0xf3, 0xfc, 0xef, 0x5a, 0xa6, 0xfe, 0x47, 0x16, 0xe8, 0x8f, 0x3c, 0x1b, 0x77, 0x76,
- 0x03, 0xeb, 0x1b, 0x62, 0xf3, 0x2d, 0xdb, 0x26, 0x8c, 0x21, 0xd2, 0x73, 0xc8, 0x11, 0xfc, 0x1a,
- 0x14, 0x45, 0x3a, 0x0e, 0x30, 0xc7, 0xba, 0x56, 0xd3, 0x56, 0xcb, 0xeb, 0xef, 0x1b, 0xf1, 0x6b,
- 0x0c, 0xa3, 0x33, 0xfc, 0x76, 0x53, 0x08, 0x98, 0x21, 0xb4, 0x8d, 0xde, 0x9a, 0xf1, 0xb9, 0xb4,
- 0xf5, 0x98, 0x70, 0xdc, 0x80, 0x27, 0xfd, 0x6a, 0x26, 0xec, 0x57, 0x41, 0x2c, 0x43, 0x43, 0xab,
- 0xf0, 0x19, 0xc8, 0x33, 0x9f, 0xd8, 0x7a, 0x56, 0x5a, 0xff, 0xd8, 0x98, 0xf6, 0xd6, 0x46, 0x4a,
- 0x98, 0xbb, 0x3e, 0xb1, 0x1b, 0x37, 0x94, 0x9b, 0xbc, 0x38, 0x21, 0x69, 0x14, 0xda, 0x60, 0x86,
- 0x71, 0xcc, 0x03, 0xa6, 0xe7, 0xa4, 0xf9, 0x4f, 0xae, 0x67, 0x5e, 0x9a, 0x68, 0xbc, 0xa1, 0x1c,
- 0xcc, 0x44, 0x67, 0xa4, 0x4c, 0xd7, 0x9f, 0x81, 0xa5, 0x27, 0x9e, 0x8b, 0x08, 0xf3, 0x02, 0x6a,
- 0x93, 0x2d, 0xce, 0xa9, 0x63, 0x05, 0x9c, 0x30, 0x58, 0x03, 0x79, 0x1f, 0xf3, 0x96, 0x4c, 0x5c,
- 0x29, 0x8e, 0xef, 0x29, 0xe6, 0x2d, 0x24, 0x11, 0xa1, 0xd1, 0x23, 0xd4, 0x92, 0x97, 0x4f, 0x68,
- 0xec, 0x13, 0x6a, 0x21, 0x89, 0xd4, 0xbf, 0x05, 0xf3, 0x09, 0xe3, 0x28, 0xe8, 0xc8, 0xb7, 0x15,
- 0xd0, 0xc8, 0xdb, 0x0a, 0x06, 0x43, 0x91, 0x1c, 0x3e, 0x00, 0xf3, 0x6e, 0xcc, 0xd9, 0x43, 0x8f,
- 0x98, 0x9e, 0x95, 0xaa, 0x8b, 0x61, 0xbf, 0x9a, 0x34, 0x27, 0x20, 0x74, 0x5e, 0x57, 0x14, 0x04,
- 0x4c, 0xb9, 0x8d, 0x09, 0x4a, 0x2e, 0xee, 0x12, 0xe6, 0x63, 0x9b, 0xa8, 0x2b, 0xdd, 0x54, 0x01,
- 0x97, 0x9e, 0x0c, 0x00, 0x14, 0xeb, 0x4c, 0xbf, 0x1c, 0x7c, 0x1b, 0x14, 0x9a, 0xd4, 0x0b, 0x7c,
- 0xf9, 0x3a, 0xa5, 0xc6, 0x9c, 0x52, 0x29, 0x7c, 0x26, 0x84, 0x28, 0xc2, 0xe0, 0xbb, 0x60, 0xb6,
- 0x47, 0x28, 0x73, 0x3c, 0x57, 0xcf, 0x4b, 0xb5, 0x79, 0xa5, 0x36, 0xbb, 0x1f, 0x89, 0xd1, 0x00,
- 0x87, 0x77, 0x40, 0x91, 0xaa, 0xc0, 0xf5, 0x82, 0xd4, 0x5d, 0x50, 0xba, 0xc5, 0x61, 0x06, 0x87,
- 0x1a, 0xf0, 0x43, 0x50, 0x66, 0x81, 0x35, 0x24, 0xcc, 0x48, 0xc2, 0xa2, 0x22, 0x94, 0x77, 0x63,
- 0x08, 0x25, 0xf5, 0xc4, 0xb5, 0xc4, 0x1d, 0xf5, 0xd9, 0xd1, 0x6b, 0x89, 0x14, 0x20, 0x89, 0xd4,
- 0xff, 0xd2, 0xc0, 0x8d, 0xab, 0xbd, 0xd8, 0x7b, 0xa0, 0x84, 0x7d, 0x47, 0x5e, 0x7b, 0xf0, 0x56,
- 0x73, 0x22, 0xaf, 0x5b, 0x4f, 0x77, 0x22, 0x21, 0x8a, 0x71, 0xa1, 0x3c, 0x08, 0x46, 0xd4, 0xf5,
- 0x50, 0x79, 0xe0, 0x92, 0xa1, 0x18, 0x87, 0x1b, 0x60, 0x6e, 0x70, 0x90, 0x8f, 0xa4, 0xe7, 0x25,
- 0xe1, 0x66, 0xd8, 0xaf, 0xce, 0xa1, 0x24, 0x80, 0x46, 0xf5, 0xea, 0x7f, 0x66, 0xc1, 0xf2, 0x2e,
- 0xe9, 0x1c, 0xbe, 0x9a, 0xa9, 0xf0, 0xd5, 0xc8, 0x54, 0x78, 0x70, 0x89, 0xb6, 0x4d, 0x0f, 0xf5,
- 0xd5, 0x4e, 0x86, 0x5f, 0xb3, 0xe0, 0xcd, 0x0b, 0x02, 0x83, 0x3f, 0x00, 0x48, 0xc7, 0x1a, 0x4d,
- 0x65, 0xf4, 0xde, 0xf4, 0x80, 0xc6, 0x9b, 0xb4, 0x71, 0x2b, 0xec, 0x57, 0x53, 0x9a, 0x17, 0xa5,
- 0xf8, 0x81, 0x3f, 0x6a, 0x60, 0xc9, 0x4d, 0x1b, 0x5c, 0x2a, 0xeb, 0x1b, 0xd3, 0x23, 0x48, 0x9d,
- 0x7b, 0x8d, 0xdb, 0x61, 0xbf, 0x9a, 0x3e, 0x12, 0x51, 0xba, 0x43, 0x31, 0x72, 0x6e, 0x25, 0x12,
- 0x25, 0x9a, 0xe6, 0xe5, 0xd5, 0xda, 0x97, 0x23, 0xb5, 0xf6, 0xe9, 0x95, 0x6a, 0x2d, 0x11, 0xe9,
- 0xc4, 0x52, 0xb3, 0xce, 0x95, 0xda, 0xe6, 0xa5, 0x4b, 0x2d, 0x69, 0xfd, 0xe2, 0x4a, 0x7b, 0x0c,
- 0x56, 0x26, 0x47, 0x75, 0xe5, 0xd1, 0x5d, 0xff, 0x3d, 0x0b, 0x16, 0x5f, 0xaf, 0x03, 0xd7, 0x6b,
- 0xfa, 0xd3, 0x3c, 0x58, 0x7e, 0xdd, 0xf0, 0x17, 0x37, 0xbc, 0xf8, 0x89, 0x06, 0x8c, 0x50, 0xf5,
- 0xe3, 0x1f, 0xbe, 0xd5, 0x1e, 0x23, 0x14, 0x49, 0x04, 0xd6, 0x06, 0xbb, 0x41, 0xf4, 0xc3, 0x02,
- 0x22, 0xd3, 0xea, 0x5f, 0xa8, 0x16, 0x03, 0x07, 0x14, 0x88, 0xd8, 0x78, 0xf5, 0x42, 0x2d, 0xb7,
- 0x5a, 0x5e, 0x7f, 0x78, 0xed, 0x5a, 0x31, 0xe4, 0xe2, 0xbc, 0xed, 0x72, 0x7a, 0x1c, 0xef, 0x20,
- 0x52, 0x86, 0x22, 0x0f, 0xf0, 0x2d, 0x90, 0x0b, 0x9c, 0x03, 0xb5, 0x22, 0x94, 0x95, 0x4a, 0x6e,
- 0x6f, 0xe7, 0x21, 0x12, 0xf2, 0x95, 0x43, 0xb5, 0x7b, 0x4b, 0x13, 0x70, 0x01, 0xe4, 0xda, 0xe4,
- 0x38, 0xea, 0x33, 0x24, 0x3e, 0x61, 0x03, 0x14, 0x7a, 0x62, 0x2d, 0x57, 0x79, 0xbe, 0x33, 0x3d,
- 0xd2, 0x78, 0x95, 0x47, 0x11, 0x75, 0x33, 0x7b, 0x5f, 0xab, 0xff, 0xa6, 0x81, 0xdb, 0x13, 0x0b,
- 0x52, 0x2c, 0x4a, 0xb8, 0xd3, 0xf1, 0x8e, 0xc8, 0x81, 0xf4, 0x5d, 0x8c, 0x17, 0xa5, 0xad, 0x48,
- 0x8c, 0x06, 0x38, 0x7c, 0x07, 0xcc, 0x50, 0x82, 0x99, 0xe7, 0xaa, 0xe5, 0x6c, 0x58, 0xcb, 0x48,
- 0x4a, 0x91, 0x42, 0xe1, 0x16, 0x98, 0x27, 0xc2, 0xbd, 0x0c, 0x6e, 0x9b, 0x52, 0x6f, 0xf0, 0x62,
- 0xcb, 0x8a, 0x30, 0xbf, 0x3d, 0x0a, 0xa3, 0xf3, 0xfa, 0xf5, 0xff, 0xb2, 0x40, 0x9f, 0x34, 0xce,
- 0x60, 0x3b, 0xde, 0x4e, 0x24, 0x28, 0x17, 0xa4, 0xf2, 0xba, 0x71, 0xf9, 0x56, 0x10, 0xb4, 0xc6,
- 0x92, 0x8a, 0x66, 0x2e, 0x29, 0x4d, 0x6c, 0x34, 0xf2, 0x08, 0x8f, 0xc0, 0x82, 0x3b, 0xba, 0x4a,
- 0x47, 0xbb, 0x56, 0x79, 0x7d, 0xed, 0x4a, 0x85, 0x2f, 0x5d, 0xea, 0xca, 0xe5, 0xc2, 0x39, 0x80,
- 0xa1, 0x31, 0x27, 0x70, 0x1d, 0x00, 0xc7, 0xb5, 0xbd, 0xae, 0xdf, 0x21, 0x9c, 0xc8, 0x04, 0x16,
- 0xe3, 0x29, 0xb8, 0x33, 0x44, 0x50, 0x42, 0x2b, 0x2d, 0xf3, 0xf9, 0xab, 0x65, 0xbe, 0x71, 0xf7,
- 0xe4, 0xac, 0x92, 0x79, 0x71, 0x56, 0xc9, 0x9c, 0x9e, 0x55, 0x32, 0xcf, 0xc3, 0x8a, 0x76, 0x12,
- 0x56, 0xb4, 0x17, 0x61, 0x45, 0x3b, 0x0d, 0x2b, 0xda, 0x3f, 0x61, 0x45, 0xfb, 0xe9, 0xdf, 0x4a,
- 0xe6, 0x8b, 0x59, 0x75, 0xc3, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x29, 0xa9, 0x9d, 0x7c, 0xb1,
- 0x0f, 0x00, 0x00,
+ // 1154 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x56, 0x4d, 0x6f, 0x1b, 0xc5,
+ 0x1b, 0xf7, 0xfa, 0x25, 0xb1, 0xc7, 0xcd, 0x3f, 0xe9, 0x44, 0x69, 0xb6, 0xf9, 0x0b, 0xdb, 0x32,
+ 0x12, 0x0a, 0xa2, 0xdd, 0x25, 0xa1, 0x90, 0x12, 0xe8, 0x21, 0x56, 0x22, 0x14, 0xa9, 0x2d, 0xd5,
+ 0x44, 0xc9, 0x81, 0x4a, 0xc0, 0x78, 0x3d, 0xb1, 0x17, 0xdb, 0xbb, 0xcb, 0xcc, 0xac, 0x43, 0x10,
+ 0x87, 0x1e, 0x39, 0x72, 0xe4, 0xc8, 0x89, 0xef, 0xc0, 0x05, 0x09, 0x4e, 0x39, 0xf6, 0x18, 0x24,
+ 0x64, 0x91, 0xe5, 0x43, 0x70, 0x45, 0x33, 0x3b, 0xf6, 0xae, 0xe3, 0x75, 0x1c, 0xe7, 0x40, 0x2f,
+ 0xbd, 0xed, 0x3c, 0xbf, 0xe7, 0x6d, 0x9e, 0x97, 0xd9, 0x1f, 0xd8, 0x6f, 0x3f, 0x64, 0x86, 0xed,
+ 0x9a, 0x6d, 0xbf, 0x4e, 0xa8, 0x43, 0x38, 0x61, 0x66, 0x8f, 0x38, 0x0d, 0x97, 0x9a, 0x0a, 0xc0,
+ 0x9e, 0x6d, 0x62, 0x9f, 0xb7, 0x5c, 0x6a, 0x7f, 0x8b, 0xb9, 0xed, 0x3a, 0x66, 0x6f, 0xa3, 0x4e,
+ 0x38, 0xde, 0x30, 0x9b, 0xc4, 0x21, 0x14, 0x73, 0xd2, 0x30, 0x3c, 0xea, 0x72, 0x17, 0x56, 0x42,
+ 0x0b, 0x03, 0x7b, 0xb6, 0x31, 0x62, 0x61, 0x28, 0x8b, 0xb5, 0xfb, 0x4d, 0x9b, 0xb7, 0xfc, 0xba,
+ 0x61, 0xb9, 0x5d, 0xb3, 0xe9, 0x36, 0x5d, 0x53, 0x1a, 0xd6, 0xfd, 0x63, 0x79, 0x92, 0x07, 0xf9,
+ 0x15, 0x3a, 0x5c, 0x7b, 0x10, 0xa5, 0xd0, 0xc5, 0x56, 0xcb, 0x76, 0x08, 0x3d, 0x35, 0xbd, 0x76,
+ 0x53, 0x08, 0x98, 0xd9, 0x25, 0x1c, 0x9b, 0xbd, 0xb1, 0x34, 0xd6, 0xcc, 0x49, 0x56, 0xd4, 0x77,
+ 0xb8, 0xdd, 0x25, 0x63, 0x06, 0x1f, 0x4c, 0x33, 0x60, 0x56, 0x8b, 0x74, 0xf1, 0x98, 0xdd, 0x7b,
+ 0x93, 0xec, 0x7c, 0x6e, 0x77, 0x4c, 0xdb, 0xe1, 0x8c, 0xd3, 0xcb, 0x46, 0xd5, 0x2d, 0x00, 0xf6,
+ 0xbe, 0xe1, 0x14, 0x1f, 0xe1, 0x8e, 0x4f, 0x60, 0x19, 0xe4, 0x6c, 0x4e, 0xba, 0x4c, 0xd7, 0x2a,
+ 0x99, 0xf5, 0x42, 0xad, 0x10, 0xf4, 0xcb, 0xb9, 0x7d, 0x21, 0x40, 0xa1, 0x7c, 0x3b, 0xff, 0xe3,
+ 0x4f, 0xe5, 0xd4, 0x8b, 0x3f, 0x2b, 0xa9, 0xea, 0xaf, 0x69, 0xa0, 0x3f, 0x76, 0x2d, 0xdc, 0x39,
+ 0xf0, 0xeb, 0x5f, 0x11, 0x8b, 0xef, 0x58, 0x16, 0x61, 0x0c, 0x91, 0x9e, 0x4d, 0x4e, 0xe0, 0x97,
+ 0x20, 0x2f, 0xca, 0xd1, 0xc0, 0x1c, 0xeb, 0x5a, 0x45, 0x5b, 0x2f, 0x6e, 0xbe, 0x6b, 0x44, 0xdd,
+ 0x18, 0x66, 0x67, 0x78, 0xed, 0xa6, 0x10, 0x30, 0x43, 0x68, 0x1b, 0xbd, 0x0d, 0xe3, 0x53, 0xe9,
+ 0xeb, 0x09, 0xe1, 0xb8, 0x06, 0xcf, 0xfa, 0xe5, 0x54, 0xd0, 0x2f, 0x83, 0x48, 0x86, 0x86, 0x5e,
+ 0xe1, 0x73, 0x90, 0x65, 0x1e, 0xb1, 0xf4, 0xb4, 0xf4, 0xfe, 0xa1, 0x31, 0xad, 0xd7, 0x46, 0x42,
+ 0x9a, 0x07, 0x1e, 0xb1, 0x6a, 0xb7, 0x54, 0x98, 0xac, 0x38, 0x21, 0xe9, 0x14, 0x5a, 0x60, 0x8e,
+ 0x71, 0xcc, 0x7d, 0xa6, 0x67, 0xa4, 0xfb, 0x8f, 0x6e, 0xe6, 0x5e, 0xba, 0xa8, 0xfd, 0x4f, 0x05,
+ 0x98, 0x0b, 0xcf, 0x48, 0xb9, 0xae, 0x3e, 0x07, 0x2b, 0x4f, 0x5d, 0x07, 0x11, 0xe6, 0xfa, 0xd4,
+ 0x22, 0x3b, 0x9c, 0x53, 0xbb, 0xee, 0x73, 0xc2, 0x60, 0x05, 0x64, 0x3d, 0xcc, 0x5b, 0xb2, 0x70,
+ 0x85, 0x28, 0xbf, 0x67, 0x98, 0xb7, 0x90, 0x44, 0x84, 0x46, 0x8f, 0xd0, 0xba, 0xbc, 0x7c, 0x4c,
+ 0xe3, 0x88, 0xd0, 0x3a, 0x92, 0x48, 0xf5, 0x6b, 0xb0, 0x18, 0x73, 0x8e, 0xfc, 0x8e, 0xec, 0xad,
+ 0x80, 0x46, 0x7a, 0x2b, 0x2c, 0x18, 0x0a, 0xe5, 0xf0, 0x11, 0x58, 0x74, 0x22, 0x9b, 0x43, 0xf4,
+ 0x98, 0xe9, 0x69, 0xa9, 0xba, 0x1c, 0xf4, 0xcb, 0x71, 0x77, 0x02, 0x42, 0x97, 0x75, 0xc5, 0x40,
+ 0xc0, 0x84, 0xdb, 0x98, 0xa0, 0xe0, 0xe0, 0x2e, 0x61, 0x1e, 0xb6, 0x88, 0xba, 0xd2, 0x6d, 0x95,
+ 0x70, 0xe1, 0xe9, 0x00, 0x40, 0x91, 0xce, 0xf4, 0xcb, 0xc1, 0x37, 0x41, 0xae, 0x49, 0x5d, 0xdf,
+ 0x93, 0xdd, 0x29, 0xd4, 0x16, 0x94, 0x4a, 0xee, 0x13, 0x21, 0x44, 0x21, 0x06, 0xdf, 0x06, 0xf3,
+ 0x3d, 0x42, 0x99, 0xed, 0x3a, 0x7a, 0x56, 0xaa, 0x2d, 0x2a, 0xb5, 0xf9, 0xa3, 0x50, 0x8c, 0x06,
+ 0x38, 0xbc, 0x07, 0xf2, 0x54, 0x25, 0xae, 0xe7, 0xa4, 0xee, 0x92, 0xd2, 0xcd, 0x0f, 0x2b, 0x38,
+ 0xd4, 0x80, 0xef, 0x83, 0x22, 0xf3, 0xeb, 0x43, 0x83, 0x39, 0x69, 0xb0, 0xac, 0x0c, 0x8a, 0x07,
+ 0x11, 0x84, 0xe2, 0x7a, 0xe2, 0x5a, 0xe2, 0x8e, 0xfa, 0xfc, 0xe8, 0xb5, 0x44, 0x09, 0x90, 0x44,
+ 0xaa, 0xbf, 0x6b, 0xe0, 0xd6, 0x6c, 0x1d, 0x7b, 0x07, 0x14, 0xb0, 0x67, 0xcb, 0x6b, 0x0f, 0x7a,
+ 0xb5, 0x20, 0xea, 0xba, 0xf3, 0x6c, 0x3f, 0x14, 0xa2, 0x08, 0x17, 0xca, 0x83, 0x64, 0xc4, 0x5c,
+ 0x0f, 0x95, 0x07, 0x21, 0x19, 0x8a, 0x70, 0xb8, 0x05, 0x16, 0x06, 0x07, 0xd9, 0x24, 0x3d, 0x2b,
+ 0x0d, 0x6e, 0x07, 0xfd, 0xf2, 0x02, 0x8a, 0x03, 0x68, 0x54, 0xaf, 0xfa, 0x5b, 0x1a, 0xac, 0x1e,
+ 0x90, 0xce, 0xf1, 0xab, 0x79, 0x15, 0xbe, 0x18, 0x79, 0x15, 0x1e, 0x5d, 0x63, 0x6d, 0x93, 0x53,
+ 0x7d, 0xb5, 0x2f, 0xc3, 0xcf, 0x69, 0xf0, 0xff, 0x2b, 0x12, 0x83, 0xdf, 0x01, 0x48, 0xc7, 0x16,
+ 0x4d, 0x55, 0xf4, 0xc1, 0xf4, 0x84, 0xc6, 0x97, 0xb4, 0x76, 0x27, 0xe8, 0x97, 0x13, 0x96, 0x17,
+ 0x25, 0xc4, 0x81, 0xdf, 0x6b, 0x60, 0xc5, 0x49, 0x7a, 0xb8, 0x54, 0xd5, 0xb7, 0xa6, 0x67, 0x90,
+ 0xf8, 0xee, 0xd5, 0xee, 0x06, 0xfd, 0x72, 0xf2, 0x93, 0x88, 0x92, 0x03, 0x8a, 0x27, 0xe7, 0x4e,
+ 0xac, 0x50, 0x62, 0x69, 0xfe, 0xbb, 0x59, 0xfb, 0x7c, 0x64, 0xd6, 0x3e, 0x9e, 0x69, 0xd6, 0x62,
+ 0x99, 0x4e, 0x1c, 0xb5, 0xfa, 0xa5, 0x51, 0xdb, 0xbe, 0xf6, 0xa8, 0xc5, 0xbd, 0x5f, 0x3d, 0x69,
+ 0x4f, 0xc0, 0xda, 0xe4, 0xac, 0x66, 0x7e, 0xba, 0xab, 0xbf, 0xa4, 0xc1, 0xf2, 0x6b, 0x3a, 0x70,
+ 0xb3, 0xa5, 0x3f, 0xcf, 0x82, 0xd5, 0xd7, 0x0b, 0x7f, 0xf5, 0xc2, 0x8b, 0x9f, 0xa8, 0xcf, 0x08,
+ 0x55, 0x3f, 0xfe, 0x61, 0xaf, 0x0e, 0x19, 0xa1, 0x48, 0x22, 0xb0, 0x32, 0xe0, 0x06, 0xe1, 0x0f,
+ 0x0b, 0x88, 0x4a, 0xab, 0x7f, 0xa1, 0x22, 0x06, 0x36, 0xc8, 0x11, 0xc1, 0x78, 0xf5, 0x5c, 0x25,
+ 0xb3, 0x5e, 0xdc, 0xdc, 0xbd, 0xf1, 0xac, 0x18, 0x92, 0x38, 0xef, 0x39, 0x9c, 0x9e, 0x46, 0x1c,
+ 0x44, 0xca, 0x50, 0x18, 0x01, 0xbe, 0x01, 0x32, 0xbe, 0xdd, 0x50, 0x14, 0xa1, 0xa8, 0x54, 0x32,
+ 0x87, 0xfb, 0xbb, 0x48, 0xc8, 0xd7, 0x8e, 0x15, 0xf7, 0x96, 0x2e, 0xe0, 0x12, 0xc8, 0xb4, 0xc9,
+ 0x69, 0xb8, 0x67, 0x48, 0x7c, 0xc2, 0x1a, 0xc8, 0xf5, 0x04, 0x2d, 0x57, 0x75, 0xbe, 0x37, 0x3d,
+ 0xd3, 0x88, 0xca, 0xa3, 0xd0, 0x74, 0x3b, 0xfd, 0x50, 0xab, 0xfe, 0xa1, 0x81, 0xbb, 0x13, 0x07,
+ 0x52, 0x10, 0x25, 0xdc, 0xe9, 0xb8, 0x27, 0xa4, 0x21, 0x63, 0xe7, 0x23, 0xa2, 0xb4, 0x13, 0x8a,
+ 0xd1, 0x00, 0x87, 0x6f, 0x81, 0x39, 0x4a, 0x30, 0x73, 0x1d, 0x45, 0xce, 0x86, 0xb3, 0x8c, 0xa4,
+ 0x14, 0x29, 0x14, 0xee, 0x80, 0x45, 0x22, 0xc2, 0xcb, 0xe4, 0xf6, 0x28, 0x75, 0x07, 0x1d, 0x5b,
+ 0x55, 0x06, 0x8b, 0x7b, 0xa3, 0x30, 0xba, 0xac, 0x2f, 0x42, 0x35, 0x88, 0x63, 0x93, 0x86, 0x64,
+ 0x6f, 0xf9, 0x28, 0xd4, 0xae, 0x94, 0x22, 0x85, 0x56, 0xff, 0x49, 0x03, 0x7d, 0xd2, 0xb3, 0x07,
+ 0xdb, 0x11, 0x8b, 0x91, 0xa0, 0x24, 0x52, 0xc5, 0x4d, 0xe3, 0xfa, 0x2b, 0x23, 0xcc, 0x6a, 0x2b,
+ 0x2a, 0xf6, 0x42, 0x5c, 0x1a, 0x63, 0x3e, 0xf2, 0x08, 0x4f, 0xc0, 0x92, 0x33, 0x4a, 0xb9, 0x43,
+ 0x4e, 0x56, 0xdc, 0xdc, 0x98, 0x69, 0x41, 0x64, 0x48, 0x5d, 0x85, 0x5c, 0xba, 0x04, 0x30, 0x34,
+ 0x16, 0x04, 0x6e, 0x02, 0x60, 0x3b, 0x96, 0xdb, 0xf5, 0x3a, 0x84, 0x13, 0x59, 0xe8, 0x7c, 0xf4,
+ 0x5a, 0xee, 0x0f, 0x11, 0x14, 0xd3, 0x4a, 0xea, 0x50, 0x76, 0xb6, 0x0e, 0xd5, 0xee, 0x9f, 0x5d,
+ 0x94, 0x52, 0x2f, 0x2f, 0x4a, 0xa9, 0xf3, 0x8b, 0x52, 0xea, 0x45, 0x50, 0xd2, 0xce, 0x82, 0x92,
+ 0xf6, 0x32, 0x28, 0x69, 0xe7, 0x41, 0x49, 0xfb, 0x2b, 0x28, 0x69, 0x3f, 0xfc, 0x5d, 0x4a, 0x7d,
+ 0x36, 0xaf, 0x6e, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xb3, 0x5e, 0x05, 0xd9, 0x0f,
+ 0x00, 0x00,
}
diff --git a/staging/src/k8s.io/api/authorization/v1beta1/generated.proto b/staging/src/k8s.io/api/authorization/v1beta1/generated.proto
index 2c940f27306..59df0b6d44f 100644
--- a/staging/src/k8s.io/api/authorization/v1beta1/generated.proto
+++ b/staging/src/k8s.io/api/authorization/v1beta1/generated.proto
@@ -226,9 +226,16 @@ message SubjectAccessReviewSpec {
// SubjectAccessReviewStatus
message SubjectAccessReviewStatus {
- // Allowed is required. True if the action would be allowed, false otherwise.
+ // Allowed is required. True if the action would be allowed, false otherwise.
optional bool allowed = 1;
+ // Denied is optional. True if the action would be denied, otherwise
+ // false. If both allowed is false and denied is false, then the
+ // authorizer has no opinion on whether to authorize the action. Denied
+ // may not be true if Allowed is true.
+ // +optional
+ optional bool denied = 4;
+
// Reason is optional. It indicates why a request was allowed or denied.
// +optional
optional string reason = 2;
diff --git a/staging/src/k8s.io/api/authorization/v1beta1/types.go b/staging/src/k8s.io/api/authorization/v1beta1/types.go
index f62f59569ca..618ff8c0f1e 100644
--- a/staging/src/k8s.io/api/authorization/v1beta1/types.go
+++ b/staging/src/k8s.io/api/authorization/v1beta1/types.go
@@ -169,8 +169,14 @@ type SelfSubjectAccessReviewSpec struct {
// SubjectAccessReviewStatus
type SubjectAccessReviewStatus struct {
- // Allowed is required. True if the action would be allowed, false otherwise.
+ // Allowed is required. True if the action would be allowed, false otherwise.
Allowed bool `json:"allowed" protobuf:"varint,1,opt,name=allowed"`
+ // Denied is optional. True if the action would be denied, otherwise
+ // false. If both allowed is false and denied is false, then the
+ // authorizer has no opinion on whether to authorize the action. Denied
+ // may not be true if Allowed is true.
+ // +optional
+ Denied bool `json:"denied,omitempty" protobuf:"varint,4,opt,name=denied"`
// Reason is optional. It indicates why a request was allowed or denied.
// +optional
Reason string `json:"reason,omitempty" protobuf:"bytes,2,opt,name=reason"`
diff --git a/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go
index 544c2fa4333..2371b21c676 100644
--- a/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go
+++ b/staging/src/k8s.io/api/authorization/v1beta1/types_swagger_doc_generated.go
@@ -148,7 +148,8 @@ func (SubjectAccessReviewSpec) SwaggerDoc() map[string]string {
var map_SubjectAccessReviewStatus = map[string]string{
"": "SubjectAccessReviewStatus",
- "allowed": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "allowed": "Allowed is required. True if the action would be allowed, false otherwise.",
+ "denied": "Denied is optional. True if the action would be denied, otherwise false. If both allowed is false and denied is false, then the authorizer has no opinion on whether to authorize the action. Denied may not be true if Allowed is true.",
"reason": "Reason is optional. It indicates why a request was allowed or denied.",
"evaluationError": "EvaluationError is an indication that some error occurred during the authorization check. It is entirely possible to get an error and be able to continue determine authorization status in spite of it. For instance, RBAC can be missing a role, but enough roles are still present and bound to reason about the request.",
}
diff --git a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go
index cbf0206a2fe..43153b91c0e 100644
--- a/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/admission/initializer/initializer_test.go
@@ -133,8 +133,8 @@ var _ initializer.WantsAuthorizer = &WantAuthorizerAdmission{}
// TestAuthorizer is a test stub that fulfills the WantsAuthorizer interface.
type TestAuthorizer struct{}
-func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
- return false, "", nil
+func (t *TestAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
+ return authorizer.DecisionNoOpinion, "", nil
}
// wantClientCert is a test stub for testing that fulfulls the WantsClientCert interface.
diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go
index e5adaf25047..bf423ebb468 100644
--- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go
+++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization.go
@@ -260,7 +260,7 @@ func (i *initializer) Admit(a admission.Attributes) (err error) {
func (i *initializer) canInitialize(a admission.Attributes, message string) error {
// caller must have the ability to mutate un-initialized resources
- authorized, reason, err := i.authorizer.Authorize(authorizer.AttributesRecord{
+ decision, reason, err := i.authorizer.Authorize(authorizer.AttributesRecord{
Name: a.GetName(),
ResourceRequest: true,
User: a.GetUserInfo(),
@@ -273,7 +273,7 @@ func (i *initializer) canInitialize(a admission.Attributes, message string) erro
if err != nil {
return err
}
- if !authorized {
+ if decision != authorizer.DecisionAllow {
return errors.NewForbidden(a.GetResource().GroupResource(), a.GetName(), fmt.Errorf("%s: %s", message, reason))
}
return nil
diff --git a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization_test.go b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization_test.go
index 0832fe8d1be..a3bb0991b34 100644
--- a/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/admission/plugin/initialization/initialization_test.go
@@ -109,11 +109,11 @@ type fakeAuthorizer struct {
accept bool
}
-func (f *fakeAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (f *fakeAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
if f.accept {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return false, "denied", nil
+ return authorizer.DecisionNoOpinion, "denied", nil
}
func TestAdmitUpdate(t *testing.T) {
diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go b/staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go
index e94da3e1a44..594109096b0 100644
--- a/staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go
+++ b/staging/src/k8s.io/apiserver/pkg/authorization/authorizer/interfaces.go
@@ -67,12 +67,12 @@ type Attributes interface {
// zero or more calls to methods of the Attributes interface. It returns nil when an action is
// authorized, otherwise it returns an error.
type Authorizer interface {
- Authorize(a Attributes) (authorized bool, reason string, err error)
+ Authorize(a Attributes) (authorized Decision, reason string, err error)
}
-type AuthorizerFunc func(a Attributes) (bool, string, error)
+type AuthorizerFunc func(a Attributes) (Decision, string, error)
-func (f AuthorizerFunc) Authorize(a Attributes) (bool, string, error) {
+func (f AuthorizerFunc) Authorize(a Attributes) (Decision, string, error) {
return f(a)
}
@@ -144,3 +144,15 @@ func (a AttributesRecord) IsResourceRequest() bool {
func (a AttributesRecord) GetPath() string {
return a.Path
}
+
+type Decision int
+
+const (
+ // DecisionDeny means that an authorizer decided to deny the action.
+ DecisionDeny Decision = iota
+ // DecisionAllow means that an authorizer decided to allow the action.
+ DecisionAllow
+ // DecisionNoOpionion means that an authorizer has no opinion on wether
+ // to allow or deny an action.
+ DecisionNoOpinion
+)
diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/authz_test.go b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/authz_test.go
index 73a42834882..d1de3eba70a 100644
--- a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/authz_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/authz_test.go
@@ -27,7 +27,7 @@ import (
// and always return nil.
func TestNewAlwaysAllowAuthorizer(t *testing.T) {
aaa := NewAlwaysAllowAuthorizer()
- if authorized, _, _ := aaa.Authorize(nil); !authorized {
+ if decision, _, _ := aaa.Authorize(nil); decision != authorizer.DecisionAllow {
t.Errorf("AlwaysAllowAuthorizer.Authorize did not authorize successfully.")
}
}
@@ -36,7 +36,7 @@ func TestNewAlwaysAllowAuthorizer(t *testing.T) {
// and always return an error as everything is forbidden.
func TestNewAlwaysDenyAuthorizer(t *testing.T) {
ada := NewAlwaysDenyAuthorizer()
- if authorized, _, _ := ada.Authorize(nil); authorized {
+ if decision, _, _ := ada.Authorize(nil); decision == authorizer.DecisionAllow {
t.Errorf("AlwaysDenyAuthorizer.Authorize returned nil instead of error.")
}
}
@@ -47,10 +47,10 @@ func TestPrivilegedGroupAuthorizer(t *testing.T) {
yes := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "allow-01"}}}
no := authorizer.AttributesRecord{User: &user.DefaultInfo{Groups: []string{"no", "deny-01"}}}
- if authorized, _, _ := auth.Authorize(yes); !authorized {
+ if authorized, _, _ := auth.Authorize(yes); authorized != authorizer.DecisionAllow {
t.Errorf("failed")
}
- if authorized, _, _ := auth.Authorize(no); authorized {
+ if authorized, _, _ := auth.Authorize(no); authorized == authorizer.DecisionAllow {
t.Errorf("failed")
}
}
diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/builtin.go b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/builtin.go
index 8381e83f437..6f67d87b898 100644
--- a/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/builtin.go
+++ b/staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory/builtin.go
@@ -28,8 +28,8 @@ import (
// It is useful in tests and when using kubernetes in an open manner.
type alwaysAllowAuthorizer struct{}
-func (alwaysAllowAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
- return true, "", nil
+func (alwaysAllowAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
+ return authorizer.DecisionAllow, "", nil
}
func (alwaysAllowAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
@@ -56,8 +56,8 @@ func NewAlwaysAllowAuthorizer() *alwaysAllowAuthorizer {
// It is useful in unit tests to force an operation to be forbidden.
type alwaysDenyAuthorizer struct{}
-func (alwaysDenyAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
- return false, "Everything is forbidden.", nil
+func (alwaysDenyAuthorizer) Authorize(a authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
+ return authorizer.DecisionNoOpinion, "Everything is forbidden.", nil
}
func (alwaysDenyAuthorizer) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
@@ -73,8 +73,8 @@ func NewAlwaysDenyAuthorizer() *alwaysDenyAuthorizer {
// It is useful in unit tests to force an operation to fail with error.
type alwaysFailAuthorizer struct{}
-func (alwaysFailAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
- return false, "", errors.New("Authorization failure.")
+func (alwaysFailAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
+ return authorizer.DecisionNoOpinion, "", errors.New("Authorization failure.")
}
func NewAlwaysFailAuthorizer() authorizer.Authorizer {
@@ -85,18 +85,18 @@ type privilegedGroupAuthorizer struct {
groups []string
}
-func (r *privilegedGroupAuthorizer) Authorize(attr authorizer.Attributes) (bool, string, error) {
+func (r *privilegedGroupAuthorizer) Authorize(attr authorizer.Attributes) (authorizer.Decision, string, error) {
if attr.GetUser() == nil {
- return false, "Error", errors.New("no user on request.")
+ return authorizer.DecisionNoOpinion, "Error", errors.New("no user on request.")
}
for _, attr_group := range attr.GetUser().GetGroups() {
for _, priv_group := range r.groups {
if priv_group == attr_group {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
}
}
- return false, "", nil
+ return authorizer.DecisionNoOpinion, "", nil
}
// NewPrivilegedGroups is for use in loopback scenarios
diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/union/union.go b/staging/src/k8s.io/apiserver/pkg/authorization/union/union.go
index 367da59d1be..3246e4c0759 100644
--- a/staging/src/k8s.io/apiserver/pkg/authorization/union/union.go
+++ b/staging/src/k8s.io/apiserver/pkg/authorization/union/union.go
@@ -14,6 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+// Package union implements an authorizer that combines multiple subauthorizer.
+// The union authorizer iterates over each subauthorizer and returns the first
+// decision that is either an Allow decision or a Deny decision. If a
+// subauthorizer returns a NoOpinion, then the union authorizer moves onto the
+// next authorizer or, if the subauthorizer was the last authorizer, returns
+// NoOpinion as the aggregate decision. I.e. union authorizer creates an
+// aggregate decision and supports short-circut allows and denies from
+// subauthorizers.
package union
import (
@@ -33,14 +41,14 @@ func New(authorizationHandlers ...authorizer.Authorizer) authorizer.Authorizer {
}
// Authorizes against a chain of authorizer.Authorizer objects and returns nil if successful and returns error if unsuccessful
-func (authzHandler unionAuthzHandler) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (authzHandler unionAuthzHandler) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
var (
errlist []error
reasonlist []string
)
for _, currAuthzHandler := range authzHandler {
- authorized, reason, err := currAuthzHandler.Authorize(a)
+ decision, reason, err := currAuthzHandler.Authorize(a)
if err != nil {
errlist = append(errlist, err)
@@ -48,13 +56,15 @@ func (authzHandler unionAuthzHandler) Authorize(a authorizer.Attributes) (bool,
if len(reason) != 0 {
reasonlist = append(reasonlist, reason)
}
- if !authorized {
- continue
+ switch decision {
+ case authorizer.DecisionAllow, authorizer.DecisionDeny:
+ return decision, reason, err
+ case authorizer.DecisionNoOpinion:
+ // continue to the next authorizer
}
- return true, reason, nil
}
- return false, strings.Join(reasonlist, "\n"), utilerrors.NewAggregate(errlist)
+ return authorizer.DecisionNoOpinion, strings.Join(reasonlist, "\n"), utilerrors.NewAggregate(errlist)
}
// unionAuthzRulesHandler authorizer against a chain of authorizer.RuleResolver
diff --git a/staging/src/k8s.io/apiserver/pkg/authorization/union/union_test.go b/staging/src/k8s.io/apiserver/pkg/authorization/union/union_test.go
index 96d989fb67b..a6413897915 100644
--- a/staging/src/k8s.io/apiserver/pkg/authorization/union/union_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/authorization/union/union_test.go
@@ -17,6 +17,7 @@ limitations under the License.
package union
import (
+ "errors"
"fmt"
"reflect"
"testing"
@@ -26,49 +27,43 @@ import (
)
type mockAuthzHandler struct {
- isAuthorized bool
- err error
+ decision authorizer.Decision
+ err error
}
-func (mock *mockAuthzHandler) Authorize(a authorizer.Attributes) (bool, string, error) {
- if mock.err != nil {
- return false, "", mock.err
- }
- if !mock.isAuthorized {
- return false, "", nil
- }
- return true, "", nil
+func (mock *mockAuthzHandler) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
+ return mock.decision, "", mock.err
}
func TestAuthorizationSecondPasses(t *testing.T) {
- handler1 := &mockAuthzHandler{isAuthorized: false}
- handler2 := &mockAuthzHandler{isAuthorized: true}
+ handler1 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
+ handler2 := &mockAuthzHandler{decision: authorizer.DecisionAllow}
authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil)
- if !authorized {
+ if authorized != authorizer.DecisionAllow {
t.Errorf("Unexpected authorization failure")
}
}
func TestAuthorizationFirstPasses(t *testing.T) {
- handler1 := &mockAuthzHandler{isAuthorized: true}
- handler2 := &mockAuthzHandler{isAuthorized: false}
+ handler1 := &mockAuthzHandler{decision: authorizer.DecisionAllow}
+ handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil)
- if !authorized {
+ if authorized != authorizer.DecisionAllow {
t.Errorf("Unexpected authorization failure")
}
}
func TestAuthorizationNonePasses(t *testing.T) {
- handler1 := &mockAuthzHandler{isAuthorized: false}
- handler2 := &mockAuthzHandler{isAuthorized: false}
+ handler1 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
+ handler2 := &mockAuthzHandler{decision: authorizer.DecisionNoOpinion}
authzHandler := New(handler1, handler2)
authorized, _, _ := authzHandler.Authorize(nil)
- if authorized {
+ if authorized == authorizer.DecisionAllow {
t.Errorf("Expected failed authorization")
}
}
@@ -223,3 +218,49 @@ func getNonResourceRules(infos []authorizer.NonResourceRuleInfo) []authorizer.De
}
return rules
}
+
+func TestAuthorizationUnequivocalDeny(t *testing.T) {
+ cs := []struct {
+ authorizers []authorizer.Authorizer
+ decision authorizer.Decision
+ }{
+ {
+ authorizers: []authorizer.Authorizer{},
+ decision: authorizer.DecisionNoOpinion,
+ },
+ {
+ authorizers: []authorizer.Authorizer{
+ &mockAuthzHandler{decision: authorizer.DecisionNoOpinion},
+ &mockAuthzHandler{decision: authorizer.DecisionAllow},
+ &mockAuthzHandler{decision: authorizer.DecisionDeny},
+ },
+ decision: authorizer.DecisionAllow,
+ },
+ {
+ authorizers: []authorizer.Authorizer{
+ &mockAuthzHandler{decision: authorizer.DecisionNoOpinion},
+ &mockAuthzHandler{decision: authorizer.DecisionDeny},
+ &mockAuthzHandler{decision: authorizer.DecisionAllow},
+ },
+ decision: authorizer.DecisionDeny,
+ },
+ {
+ authorizers: []authorizer.Authorizer{
+ &mockAuthzHandler{decision: authorizer.DecisionNoOpinion},
+ &mockAuthzHandler{decision: authorizer.DecisionDeny, err: errors.New("webhook failed closed")},
+ &mockAuthzHandler{decision: authorizer.DecisionAllow},
+ },
+ decision: authorizer.DecisionDeny,
+ },
+ }
+ for i, c := range cs {
+ t.Run(fmt.Sprintf("case %v", i), func(t *testing.T) {
+ authzHandler := New(c.authorizers...)
+
+ decision, _, _ := authzHandler.Authorize(nil)
+ if decision != c.decision {
+ t.Errorf("Unexpected authorization failure: %v, expected: %v", decision, c.decision)
+ }
+ })
+ }
+}
diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go
index d244257a04d..f60756b6fd1 100644
--- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go
+++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go
@@ -47,7 +47,7 @@ func WithAuthorization(handler http.Handler, requestContextMapper request.Reques
return
}
authorized, reason, err := a.Authorize(attributes)
- if authorized {
+ if authorized == authorizer.DecisionAllow {
handler.ServeHTTP(w, req)
return
}
diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go
index 8f67caf86fe..9af292e1cef 100644
--- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go
+++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go
@@ -110,8 +110,8 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques
return
}
- allowed, reason, err := a.Authorize(actingAsAttributes)
- if err != nil || !allowed {
+ decision, reason, err := a.Authorize(actingAsAttributes)
+ if err != nil || decision != authorizer.DecisionAllow {
glog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err)
responsewriters.Forbidden(ctx, actingAsAttributes, w, req, reason, s)
return
diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go
index d43776507ed..814de2a26e6 100644
--- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go
@@ -35,50 +35,50 @@ import (
type impersonateAuthorizer struct{}
-func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
+func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
user := a.GetUser()
switch {
case user.GetName() == "system:admin":
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
case user.GetName() == "tester":
- return false, "", fmt.Errorf("works on my machine")
+ return authorizer.DecisionNoOpinion, "", fmt.Errorf("works on my machine")
case user.GetName() == "deny-me":
- return false, "denied", nil
+ return authorizer.DecisionNoOpinion, "denied", nil
}
if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "wheel" && a.GetVerb() == "impersonate" && a.GetResource() == "users" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "sa-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 0 && user.GetGroups()[0] == "regular-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "users" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "group-impersonater" && a.GetVerb() == "impersonate" && a.GetResource() == "groups" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-scopes" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-particular-scopes" &&
a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "scopes" && a.GetName() == "scope-a" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if len(user.GetGroups()) > 1 && user.GetGroups()[1] == "extra-setter-project" && a.GetVerb() == "impersonate" && a.GetResource() == "userextras" && a.GetSubresource() == "project" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return false, "deny by default", nil
+ return authorizer.DecisionNoOpinion, "deny by default", nil
}
func TestImpersonationFilter(t *testing.T) {
diff --git a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go
index 9fc480d49be..16fee408c7b 100644
--- a/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go
+++ b/staging/src/k8s.io/apiserver/pkg/server/genericapiserver_test.go
@@ -437,9 +437,9 @@ type mockAuthorizer struct {
lastURI string
}
-func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized bool, reason string, err error) {
+func (authz *mockAuthorizer) Authorize(a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
authz.lastURI = a.GetPath()
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
type mockAuthenticator struct {
diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go
index 890845caeb9..e9efac307c6 100644
--- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go
+++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook.go
@@ -50,6 +50,7 @@ type WebhookAuthorizer struct {
authorizedTTL time.Duration
unauthorizedTTL time.Duration
initialBackoff time.Duration
+ decisionOnError authorizer.Decision
}
// NewFromInterface creates a WebhookAuthorizer using the given subjectAccessReview client
@@ -93,6 +94,7 @@ func newWithBackoff(subjectAccessReview authorizationclient.SubjectAccessReviewI
authorizedTTL: authorizedTTL,
unauthorizedTTL: unauthorizedTTL,
initialBackoff: initialBackoff,
+ decisionOnError: authorizer.DecisionNoOpinion,
}, nil
}
@@ -140,7 +142,10 @@ func newWithBackoff(subjectAccessReview authorizationclient.SubjectAccessReviewI
// }
// }
//
-func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bool, reason string, err error) {
+// TODO(mikedanese): We should eventually support failing closed when we
+// encounter an error. We are failing open now to preserve backwards compatible
+// behavior.
+func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (decision authorizer.Decision, reason string, err error) {
r := &authorization.SubjectAccessReview{}
if user := attr.GetUser(); user != nil {
r.Spec = authorization.SubjectAccessReviewSpec{
@@ -169,7 +174,7 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bo
}
key, err := json.Marshal(r.Spec)
if err != nil {
- return false, "", err
+ return w.decisionOnError, "", err
}
if entry, ok := w.responseCache.Get(string(key)); ok {
r.Status = entry.(authorization.SubjectAccessReviewStatus)
@@ -185,7 +190,7 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bo
if err != nil {
// An error here indicates bad configuration or an outage. Log for debugging.
glog.Errorf("Failed to make webhook authorizer request: %v", err)
- return false, "", err
+ return w.decisionOnError, "", err
}
r.Status = result.Status
if r.Status.Allowed {
@@ -194,7 +199,17 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bo
w.responseCache.Add(string(key), r.Status, w.unauthorizedTTL)
}
}
- return r.Status.Allowed, r.Status.Reason, nil
+ switch {
+ case r.Status.Denied && r.Status.Allowed:
+ return authorizer.DecisionDeny, r.Status.Reason, fmt.Errorf("webhook subject access review returned both allow and deny response")
+ case r.Status.Denied:
+ return authorizer.DecisionDeny, r.Status.Reason, nil
+ case r.Status.Allowed:
+ return authorizer.DecisionAllow, r.Status.Reason, nil
+ default:
+ return authorizer.DecisionNoOpinion, r.Status.Reason, nil
+ }
+
}
//TODO: need to finish the method to get the rules when using webhook mode
diff --git a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go
index 4f5bd233127..f637af6f209 100644
--- a/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go
+++ b/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/webhook_test.go
@@ -396,13 +396,13 @@ func TestTLSConfig(t *testing.T) {
// Allow all and see if we get an error.
service.Allow()
- authorized, _, err := wh.Authorize(attr)
+ decision, _, err := wh.Authorize(attr)
if tt.wantAuth {
- if !authorized {
+ if decision != authorizer.DecisionAllow {
t.Errorf("expected successful authorization")
}
} else {
- if authorized {
+ if decision == authorizer.DecisionAllow {
t.Errorf("expected failed authorization")
}
}
@@ -418,7 +418,7 @@ func TestTLSConfig(t *testing.T) {
}
service.Deny()
- if authorized, _, _ := wh.Authorize(attr); authorized {
+ if decision, _, _ := wh.Authorize(attr); decision == authorizer.DecisionAllow {
t.Errorf("%s: incorrectly authorized with DenyAll policy", tt.test)
}
}()
@@ -522,11 +522,11 @@ func TestWebhook(t *testing.T) {
}
for i, tt := range tests {
- authorized, _, err := wh.Authorize(tt.attr)
+ decision, _, err := wh.Authorize(tt.attr)
if err != nil {
t.Fatal(err)
}
- if !authorized {
+ if decision != authorizer.DecisionAllow {
t.Errorf("case %d: authorization failed", i)
continue
}
@@ -567,7 +567,7 @@ func testWebhookCacheCases(t *testing.T, serv *mockService, wh *WebhookAuthorize
continue
}
- if test.expectedAuthorized != authorized {
+ if test.expectedAuthorized != (authorized == authorizer.DecisionAllow) {
t.Errorf("%d: expected authorized=%v, got %v", i, test.expectedAuthorized, authorized)
}
diff --git a/test/integration/auth/accessreview_test.go b/test/integration/auth/accessreview_test.go
index f26c5b2af08..3924fd61c81 100644
--- a/test/integration/auth/accessreview_test.go
+++ b/test/integration/auth/accessreview_test.go
@@ -39,12 +39,12 @@ import (
// TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented.
type sarAuthorizer struct{}
-func (sarAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (sarAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser().GetName() == "dave" {
- return false, "no", errors.New("I'm sorry, Dave")
+ return authorizer.DecisionNoOpinion, "no", errors.New("I'm sorry, Dave")
}
- return true, "you're not dave", nil
+ return authorizer.DecisionAllow, "you're not dave", nil
}
func alwaysAlice(req *http.Request) (user.Info, bool, error) {
diff --git a/test/integration/auth/auth_test.go b/test/integration/auth/auth_test.go
index 4408c2a79e0..d28d54e34c1 100644
--- a/test/integration/auth/auth_test.go
+++ b/test/integration/auth/auth_test.go
@@ -535,11 +535,11 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
// TODO(etune): remove this test once a more comprehensive built-in authorizer is implemented.
type allowAliceAuthorizer struct{}
-func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser() != nil && a.GetUser().GetName() == "alice" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return false, "I can't allow that. Go ask alice.", nil
+ return authorizer.DecisionNoOpinion, "I can't allow that. Go ask alice.", nil
}
// TestAliceNotForbiddenOrUnauthorized tests a user who is known to
@@ -702,24 +702,24 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
type impersonateAuthorizer struct{}
// alice can't act as anyone and bob can't do anything but act-as someone
-func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (impersonateAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
// alice can impersonate service accounts and do other actions
if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() == "impersonate" && a.GetResource() == "serviceaccounts" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
if a.GetUser() != nil && a.GetUser().GetName() == "alice" && a.GetVerb() != "impersonate" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// bob can impersonate anyone, but that it
if a.GetUser() != nil && a.GetUser().GetName() == "bob" && a.GetVerb() == "impersonate" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// service accounts can do everything
if a.GetUser() != nil && strings.HasPrefix(a.GetUser().GetName(), serviceaccount.ServiceAccountUsernamePrefix) {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return false, "I can't allow that. Go ask alice.", nil
+ return authorizer.DecisionNoOpinion, "I can't allow that. Go ask alice.", nil
}
func TestImpersonateIsForbidden(t *testing.T) {
@@ -861,9 +861,9 @@ type trackingAuthorizer struct {
requestAttributes []authorizer.Attributes
}
-func (a *trackingAuthorizer) Authorize(attributes authorizer.Attributes) (bool, string, error) {
+func (a *trackingAuthorizer) Authorize(attributes authorizer.Attributes) (authorizer.Decision, string, error) {
a.requestAttributes = append(a.requestAttributes, attributes)
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// TestAuthorizationAttributeDetermination tests that authorization attributes are built correctly
diff --git a/test/integration/framework/master_utils.go b/test/integration/framework/master_utils.go
index beb035578b6..7c787988243 100644
--- a/test/integration/framework/master_utils.go
+++ b/test/integration/framework/master_utils.go
@@ -46,6 +46,7 @@ import (
"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
authenticatorunion "k8s.io/apiserver/pkg/authentication/request/union"
"k8s.io/apiserver/pkg/authentication/user"
+ "k8s.io/apiserver/pkg/authorization/authorizer"
authauthorizer "k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
authorizerunion "k8s.io/apiserver/pkg/authorization/union"
@@ -148,8 +149,8 @@ func NewMasterComponents(c *Config) *MasterComponents {
// alwaysAllow always allows an action
type alwaysAllow struct{}
-func (alwaysAllow) Authorize(requestAttributes authauthorizer.Attributes) (bool, string, error) {
- return true, "always allow", nil
+func (alwaysAllow) Authorize(requestAttributes authauthorizer.Attributes) (authorizer.Decision, string, error) {
+ return authorizer.DecisionAllow, "always allow", nil
}
// alwaysEmpty simulates "no authentication" for old tests
diff --git a/test/integration/master/master_test.go b/test/integration/master/master_test.go
index 6b13ca35abc..61294e746d1 100644
--- a/test/integration/master/master_test.go
+++ b/test/integration/master/master_test.go
@@ -58,11 +58,11 @@ const (
type allowAliceAuthorizer struct{}
-func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (bool, string, error) {
+func (allowAliceAuthorizer) Authorize(a authorizer.Attributes) (authorizer.Decision, string, error) {
if a.GetUser() != nil && a.GetUser().GetName() == "alice" {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
- return false, "I can't allow that. Go ask alice.", nil
+ return authorizer.DecisionNoOpinion, "I can't allow that. Go ask alice.", nil
}
func testPrefix(t *testing.T, prefix string) {
diff --git a/test/integration/serviceaccount/service_account_test.go b/test/integration/serviceaccount/service_account_test.go
index 4181fa05652..9161b472590 100644
--- a/test/integration/serviceaccount/service_account_test.go
+++ b/test/integration/serviceaccount/service_account_test.go
@@ -372,7 +372,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
// 1. The "root" user is allowed to do anything
// 2. ServiceAccounts named "ro" are allowed read-only operations in their namespace
// 3. ServiceAccounts named "rw" are allowed any operation in their namespace
- authorizer := authorizer.AuthorizerFunc(func(attrs authorizer.Attributes) (bool, string, error) {
+ authorizer := authorizer.AuthorizerFunc(func(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
username := ""
if user := attrs.GetUser(); user != nil {
username = user.GetName()
@@ -382,7 +382,7 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
// If the user is "root"...
if username == rootUserName {
// allow them to do anything
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
// If the user is a service account...
@@ -392,15 +392,15 @@ func startServiceAccountTestServer(t *testing.T) (*clientset.Clientset, restclie
switch serviceAccountName {
case readOnlyServiceAccountName:
if attrs.IsReadOnly() {
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
case readWriteServiceAccountName:
- return true, "", nil
+ return authorizer.DecisionAllow, "", nil
}
}
}
- return false, fmt.Sprintf("User %s is denied (ns=%s, readonly=%v, resource=%s)", username, ns, attrs.IsReadOnly(), attrs.GetResource()), nil
+ return authorizer.DecisionNoOpinion, fmt.Sprintf("User %s is denied (ns=%s, readonly=%v, resource=%s)", username, ns, attrs.IsReadOnly(), attrs.GetResource()), nil
})
// Set up admission plugin to auto-assign serviceaccounts to pods