Beispiel #1
0
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
}
Beispiel #2
0
// 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.SelfSubjectRulesReview)
	if !ok {
		return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a SelfSubjectRulesReview: %#v", obj))
	}
	namespace := kapi.NamespaceValue(ctx)
	if len(namespace) == 0 {
		return nil, kapierrors.NewBadRequest(fmt.Sprintf("namespace is required on this type: %v", namespace))
	}
	user, exists := kapi.UserFrom(ctx)
	if !exists {
		return nil, kapierrors.NewBadRequest(fmt.Sprintf("user missing from context"))
	}

	errors := []error{}

	rules := []authorizationapi.PolicyRule{}
	namespaceRules, err := r.ruleResolver.GetEffectivePolicyRules(ctx)
	if err != nil {
		errors = append(errors, err)
	}
	for _, rule := range namespaceRules {
		rules = append(rules, rulevalidation.BreakdownRule(rule)...)
	}
	if len(namespace) != 0 {
		masterContext := kapi.WithNamespace(ctx, kapi.NamespaceNone)
		clusterRules, err := r.ruleResolver.GetEffectivePolicyRules(masterContext)
		if err != nil {
			errors = append(errors, err)
		}
		for _, rule := range clusterRules {
			rules = append(rules, rulevalidation.BreakdownRule(rule)...)
		}
	}

	switch {
	case rulesReview.Spec.Scopes == nil:
		if scopes, _ := user.GetExtra()[authorizationapi.ScopesKey]; len(scopes) > 0 {
			rules, err = r.filterRulesByScopes(rules, scopes, namespace)
			if err != nil {
				return nil, kapierrors.NewInternalError(err)
			}
		}

	case len(rulesReview.Spec.Scopes) > 0:
		rules, err = r.filterRulesByScopes(rules, rulesReview.Spec.Scopes, namespace)
		if err != nil {
			return nil, kapierrors.NewInternalError(err)
		}

	}

	if compactedRules, err := rulevalidation.CompactRules(rules); err == nil {
		rules = compactedRules
	}
	sort.Sort(authorizationapi.SortableRuleSlice(rules))

	ret := &authorizationapi.SelfSubjectRulesReview{
		Status: authorizationapi.SubjectRulesReviewStatus{
			Rules: rules,
		},
	}

	if len(errors) != 0 {
		ret.Status.EvaluationError = kutilerrors.NewAggregate(errors).Error()
	}

	return ret, nil
}
Beispiel #3
0
func TestCompactRules(t *testing.T) {
	testcases := map[string]struct {
		Rules    []api.PolicyRule
		Expected []api.PolicyRule
	}{
		"empty": {
			Rules:    []api.PolicyRule{},
			Expected: []api.PolicyRule{},
		},
		"simple": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds")},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds")},
				{Verbs: sets.NewString("update", "patch"), APIGroups: []string{""}, Resources: sets.NewString("builds")},

				{Verbs: sets.NewString("create"), APIGroups: []string{"extensions"}, Resources: sets.NewString("daemonsets")},
				{Verbs: sets.NewString("delete"), APIGroups: []string{"extensions"}, Resources: sets.NewString("daemonsets")},

				{Verbs: sets.NewString("educate"), APIGroups: []string{""}, Resources: sets.NewString("dolphins")},

				// nil verbs are preserved in non-merge cases.
				// these are the pirates who don't do anything.
				{Verbs: nil, APIGroups: []string{""}, Resources: sets.NewString("pirates")},

				// Test merging into a nil Verbs string set
				{Verbs: nil, APIGroups: []string{""}, Resources: sets.NewString("pods")},
				{Verbs: sets.NewString("create"), APIGroups: []string{""}, Resources: sets.NewString("pods")},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("create", "delete"), APIGroups: []string{"extensions"}, Resources: sets.NewString("daemonsets")},
				{Verbs: sets.NewString("get", "list", "update", "patch"), APIGroups: []string{""}, Resources: sets.NewString("builds")},
				{Verbs: sets.NewString("educate"), APIGroups: []string{""}, Resources: sets.NewString("dolphins")},
				{Verbs: nil, APIGroups: []string{""}, Resources: sets.NewString("pirates")},
				{Verbs: sets.NewString("create"), APIGroups: []string{""}, Resources: sets.NewString("pods")},
			},
		},
		"complex multi-group": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{"", "builds.openshift.io"}, Resources: sets.NewString("builds")},
				{Verbs: sets.NewString("list"), APIGroups: []string{"", "builds.openshift.io"}, Resources: sets.NewString("builds")},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{"", "builds.openshift.io"}, Resources: sets.NewString("builds")},
				{Verbs: sets.NewString("list"), APIGroups: []string{"", "builds.openshift.io"}, Resources: sets.NewString("builds")},
			},
		},

		"complex multi-resource": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds", "images")},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds", "images")},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds", "images")},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds", "images")},
			},
		},

		"complex named-resource": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), ResourceNames: sets.NewString("mybuild")},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds"), ResourceNames: sets.NewString("mybuild2")},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), ResourceNames: sets.NewString("mybuild")},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds"), ResourceNames: sets.NewString("mybuild2")},
			},
		},

		"complex non-resource": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), NonResourceURLs: sets.NewString("/")},
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), NonResourceURLs: sets.NewString("/foo")},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), NonResourceURLs: sets.NewString("/")},
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), NonResourceURLs: sets.NewString("/foo")},
			},
		},

		"complex attributes": {
			Rules: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), AttributeRestrictions: &api.IsPersonalSubjectAccessReview{}},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds"), AttributeRestrictions: &api.IsPersonalSubjectAccessReview{}},
			},
			Expected: []api.PolicyRule{
				{Verbs: sets.NewString("get"), APIGroups: []string{""}, Resources: sets.NewString("builds"), AttributeRestrictions: &api.IsPersonalSubjectAccessReview{}},
				{Verbs: sets.NewString("list"), APIGroups: []string{""}, Resources: sets.NewString("builds"), AttributeRestrictions: &api.IsPersonalSubjectAccessReview{}},
			},
		},
	}

	for k, tc := range testcases {
		rules := tc.Rules
		originalRules, err := kapi.Scheme.DeepCopy(tc.Rules)
		if err != nil {
			t.Errorf("%s: couldn't copy rules: %v", k, err)
			continue
		}
		compacted, err := CompactRules(tc.Rules)
		if err != nil {
			t.Errorf("%s: unexpected error: %v", k, err)
			continue
		}
		if !reflect.DeepEqual(rules, originalRules) {
			t.Errorf("%s: CompactRules mutated rules. Expected\n%#v\ngot\n%#v", k, originalRules, rules)
			continue
		}
		if covers, missing := Covers(compacted, rules); !covers {
			t.Errorf("%s: compacted rules did not cover original rules. missing: %#v", k, missing)
			continue
		}
		if covers, missing := Covers(rules, compacted); !covers {
			t.Errorf("%s: original rules did not cover compacted rules. missing: %#v", k, missing)
			continue
		}

		sort.Stable(api.SortableRuleSlice(compacted))
		sort.Stable(api.SortableRuleSlice(tc.Expected))
		if !reflect.DeepEqual(compacted, tc.Expected) {
			t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted)
			continue
		}
	}
}