forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage.go
116 lines (96 loc) · 3.75 KB
/
storage.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
package subjectrulesreview
import (
"fmt"
"sort"
kapi "k8s.io/kubernetes/pkg/api"
kapierrors "k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/auth/user"
"k8s.io/kubernetes/pkg/runtime"
kutilerrors "k8s.io/kubernetes/pkg/util/errors"
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
"github.com/openshift/origin/pkg/authorization/authorizer/scope"
"github.com/openshift/origin/pkg/authorization/rulevalidation"
"github.com/openshift/origin/pkg/client"
)
type REST struct {
ruleResolver rulevalidation.AuthorizationRuleResolver
clusterPolicyGetter client.ClusterPolicyLister
}
func NewREST(ruleResolver rulevalidation.AuthorizationRuleResolver, clusterPolicyGetter client.ClusterPolicyLister) *REST {
return &REST{ruleResolver: ruleResolver, clusterPolicyGetter: clusterPolicyGetter}
}
func (r *REST) New() runtime.Object {
return &authorizationapi.SubjectRulesReview{}
}
// Create registers a given new ResourceAccessReview instance to r.registry.
func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) {
rulesReview, ok := obj.(*authorizationapi.SubjectRulesReview)
if !ok {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SubjectRulesReview: %#v", obj))
}
namespace := kapi.NamespaceValue(ctx)
if len(namespace) == 0 {
return nil, kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))
}
userToCheck := &user.DefaultInfo{
Name: rulesReview.Spec.User,
Groups: rulesReview.Spec.Groups,
Extra: map[string][]string{},
}
if len(rulesReview.Spec.Scopes) > 0 {
userToCheck.Extra[authorizationapi.ScopesKey] = rulesReview.Spec.Scopes
}
rules, errors := GetEffectivePolicyRules(kapi.WithUser(ctx, userToCheck), r.ruleResolver, r.clusterPolicyGetter)
ret := &authorizationapi.SubjectRulesReview{
Status: authorizationapi.SubjectRulesReviewStatus{
Rules: rules,
},
}
if len(errors) != 0 {
ret.Status.EvaluationError = kutilerrors.NewAggregate(errors).Error()
}
return ret, nil
}
func GetEffectivePolicyRules(ctx kapi.Context, ruleResolver rulevalidation.AuthorizationRuleResolver, clusterPolicyGetter client.ClusterPolicyLister) ([]authorizationapi.PolicyRule, []error) {
namespace := kapi.NamespaceValue(ctx)
if len(namespace) == 0 {
return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))}
}
user, exists := kapi.UserFrom(ctx)
if !exists {
return nil, []error{kapierrors.NewBadRequest(fmt.Sprintf("user missing from context"))}
}
var errors []error
var rules []authorizationapi.PolicyRule
namespaceRules, err := ruleResolver.RulesFor(user, namespace)
if err != nil {
errors = append(errors, err)
}
for _, rule := range namespaceRules {
rules = append(rules, rulevalidation.BreakdownRule(rule)...)
}
if scopes := user.GetExtra()[authorizationapi.ScopesKey]; len(scopes) > 0 {
rules, err = filterRulesByScopes(rules, scopes, namespace, clusterPolicyGetter)
if err != nil {
return nil, []error{kapierrors.NewInternalError(err)}
}
}
if compactedRules, err := rulevalidation.CompactRules(rules); err == nil {
rules = compactedRules
}
sort.Sort(authorizationapi.SortableRuleSlice(rules))
return rules, errors
}
func filterRulesByScopes(rules []authorizationapi.PolicyRule, scopes []string, namespace string, clusterPolicyGetter client.ClusterPolicyLister) ([]authorizationapi.PolicyRule, error) {
scopeRules, err := scope.ScopesToRules(scopes, namespace, clusterPolicyGetter)
if err != nil {
return nil, err
}
filteredRules := []authorizationapi.PolicyRule{}
for _, rule := range rules {
if allowed, _ := rulevalidation.Covers(scopeRules, []authorizationapi.PolicyRule{rule}); allowed {
filteredRules = append(filteredRules, rule)
}
}
return filteredRules, nil
}