forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
authorizer.go
117 lines (97 loc) · 3.56 KB
/
authorizer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package remote
import (
"github.com/golang/glog"
kapi "k8s.io/kubernetes/pkg/api"
kerrs "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/util/sets"
authzapi "github.com/openshift/origin/pkg/authorization/api"
"github.com/openshift/origin/pkg/authorization/authorizer"
oclient "github.com/openshift/origin/pkg/client"
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
)
// RemoteAuthorizer provides authorization using subject access review and resource access review requests
type RemoteAuthorizer struct {
client RemoteAuthorizerClient
}
type RemoteAuthorizerClient interface {
oclient.SubjectAccessReviews
oclient.ResourceAccessReviews
oclient.LocalSubjectAccessReviewsNamespacer
oclient.LocalResourceAccessReviewsNamespacer
}
func NewAuthorizer(client RemoteAuthorizerClient) (authorizer.Authorizer, error) {
return &RemoteAuthorizer{client}, nil
}
func (r *RemoteAuthorizer) Authorize(ctx kapi.Context, a authorizer.AuthorizationAttributes) (bool, string, error) {
var (
result *authzapi.SubjectAccessReviewResponse
err error
)
// Extract namespace from context
namespace, _ := kapi.NamespaceFrom(ctx)
// Extract user from context
user := ""
groups := sets.NewString()
if userInfo, ok := kapi.UserFrom(ctx); ok {
user = userInfo.GetName()
groups.Insert(userInfo.GetGroups()...)
}
// Make sure we don't run a subject access review on our own permissions
if len(user) == 0 && len(groups) == 0 {
user = bootstrappolicy.UnauthenticatedUsername
groups = sets.NewString(bootstrappolicy.UnauthenticatedGroup)
}
if len(namespace) > 0 {
result, err = r.client.LocalSubjectAccessReviews(namespace).Create(&authzapi.LocalSubjectAccessReview{
User: user,
Groups: groups,
Action: getAction(namespace, a),
})
} else {
result, err = r.client.SubjectAccessReviews().Create(&authzapi.SubjectAccessReview{
User: user,
Groups: groups,
Action: getAction(namespace, a),
})
}
if err != nil {
glog.Errorf("error running subject access review: %v", err)
return false, "", kerrs.NewInternalError(err)
}
glog.V(2).Infof("allowed=%v, reason=%s", result.Allowed, result.Reason)
return result.Allowed, result.Reason, nil
}
func (r *RemoteAuthorizer) GetAllowedSubjects(ctx kapi.Context, attributes authorizer.AuthorizationAttributes) (sets.String, sets.String, error) {
var (
result *authzapi.ResourceAccessReviewResponse
err error
)
// Extract namespace from context
namespace, _ := kapi.NamespaceFrom(ctx)
if len(namespace) > 0 {
result, err = r.client.LocalResourceAccessReviews(namespace).Create(&authzapi.LocalResourceAccessReview{Action: getAction(namespace, attributes)})
} else {
result, err = r.client.ResourceAccessReviews().Create(&authzapi.ResourceAccessReview{Action: getAction(namespace, attributes)})
}
if err != nil {
glog.Errorf("error running resource access review: %v", err)
return nil, nil, kerrs.NewInternalError(err)
}
return result.Users, result.Groups, nil
}
func getAction(namespace string, attributes authorizer.AuthorizationAttributes) authzapi.AuthorizationAttributes {
return authzapi.AuthorizationAttributes{
Namespace: namespace,
Verb: attributes.GetVerb(),
Group: attributes.GetAPIGroup(),
Version: attributes.GetAPIVersion(),
Resource: attributes.GetResource(),
ResourceName: attributes.GetResourceName(),
// TODO: missing from authorizer.AuthorizationAttributes:
// Content
// TODO: missing from authzapi.AuthorizationAttributes
// RequestAttributes (unserializable?)
// IsNonResourceURL
// URL (doesn't make sense for remote authz?)
}
}