move authorizers over to new interface

Kubernetes-commit: 12125455d84c75562e6dd6a183762549adff747f
This commit is contained in:
Mike Danese 2017-09-29 14:21:40 -07:00 committed by Kubernetes Publisher
parent 89a498de40
commit 06a5d25846
11 changed files with 57 additions and 49 deletions

View File

@ -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.

View File

@ -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

View File

@ -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) {

View File

@ -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")
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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) {

View File

@ -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 {

View File

@ -140,7 +140,10 @@ func newWithBackoff(subjectAccessReview authorizationclient.SubjectAccessReviewI
// }
// }
//
func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bool, reason string, err error) {
// TODO(mikedanese): We should eventually fail closed when we encounter and
// error. We are failing open now to preserve backwards compatible behavior.
// Fix this after deprecation.
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 +172,7 @@ func (w *WebhookAuthorizer) Authorize(attr authorizer.Attributes) (authorized bo
}
key, err := json.Marshal(r.Spec)
if err != nil {
return false, "", err
return authorizer.DecisionNoOpinion, "", err
}
if entry, ok := w.responseCache.Get(string(key)); ok {
r.Status = entry.(authorization.SubjectAccessReviewStatus)
@ -185,7 +188,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 authorizer.DecisionNoOpinion, "", err
}
r.Status = result.Status
if r.Status.Allowed {
@ -194,7 +197,12 @@ 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
if r.Status.Allowed {
return authorizer.DecisionAllow, r.Status.Reason, nil
} else {
return authorizer.DecisionNoOpinion, r.Status.Reason, nil
}
}
//TODO: need to finish the method to get the rules when using webhook mode

View File

@ -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)
}