Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions authz/providers/azure/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Options struct {
ARMCallLimit int
SkipAuthzCheck []string
SkipAuthzForNonAADUsers bool
SkipAuthzNamespace bool
AllowNonResDiscoveryPathAccess bool
UseNamespaceResourceScopeFormat bool
DiscoverResources bool
Expand All @@ -56,6 +57,7 @@ func NewOptions() Options {
ARMCallLimit: defaultArmCallLimit,
SkipAuthzCheck: []string{""},
SkipAuthzForNonAADUsers: true,
SkipAuthzNamespace: false,
AllowNonResDiscoveryPathAccess: true,
UseNamespaceResourceScopeFormat: false,
DiscoverResources: false,
Expand All @@ -70,6 +72,7 @@ func (o *Options) AddFlags(fs *pflag.FlagSet) {
fs.IntVar(&o.ARMCallLimit, "azure.arm-call-limit", o.ARMCallLimit, "No of calls before which webhook switch to new ARM instance to avoid throttling")
fs.StringSliceVar(&o.SkipAuthzCheck, "azure.skip-authz-check", o.SkipAuthzCheck, "name of usernames/email for which authz check will be skipped")
fs.BoolVar(&o.SkipAuthzForNonAADUsers, "azure.skip-authz-for-non-aad-users", o.SkipAuthzForNonAADUsers, "skip authz for non AAD users")
fs.BoolVar(&o.SkipAuthzNamespace, "azure.skip-authz-namespace", o.SkipAuthzNamespace, "skip authz namespace information")
fs.BoolVar(&o.AllowNonResDiscoveryPathAccess, "azure.allow-nonres-discovery-path-access", o.AllowNonResDiscoveryPathAccess, "allow access on Non Resource paths required for discovery, setting it false will require explicit non resource path role assignment for all users in Azure RBAC")
fs.BoolVar(&o.UseNamespaceResourceScopeFormat, "azure.use-ns-resource-scope-format", o.UseNamespaceResourceScopeFormat, "use namespace as resource scope format for making rbac checkaccess calls at namespace scope")
fs.StringVar(&o.KubeConfigFile, "azure.kubeconfig-file", "", "path to the kubeconfig of cluster.")
Expand Down
8 changes: 6 additions & 2 deletions authz/providers/azure/rbac/checkaccessreqhelper.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ func getResultCacheKey(subRevReq *authzv1.SubjectAccessReviewSpec) string {
return cacheKey
}

func prepareCheckAccessRequestBody(req *authzv1.SubjectAccessReviewSpec, clusterType string, resourceId string, useNamespaceResourceScopeFormat bool) ([]*CheckAccessRequest, error) {
func prepareCheckAccessRequestBody(req *authzv1.SubjectAccessReviewSpec, clusterType string, resourceId string, skipNamespace, useNamespaceResourceScopeFormat bool) ([]*CheckAccessRequest, error) {
/* This is how sample SubjectAccessReview request will look like
{
"kind": "SubjectAccessReview",
Expand Down Expand Up @@ -522,7 +522,11 @@ func prepareCheckAccessRequestBody(req *authzv1.SubjectAccessReviewSpec, cluster
checkaccessreq.Subject.Attributes.Groups = groups
checkaccessreq.Subject.Attributes.ObjectId = userOid
checkaccessreq.Actions = actions[i:j]
checkaccessreq.Resource.Id = getScope(resourceId, req.ResourceAttributes, useNamespaceResourceScopeFormat)
if skipNamespace {
checkaccessreq.Resource.Id = resourceId
} else {
checkaccessreq.Resource.Id = getScope(resourceId, req.ResourceAttributes, useNamespaceResourceScopeFormat)
}
checkAccessReqs = append(checkAccessReqs, &checkaccessreq)
}

Expand Down
20 changes: 16 additions & 4 deletions authz/providers/azure/rbac/checkaccessreqhelper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ func Test_prepareCheckAccessRequestBody(t *testing.T) {
createOperationsMap(clusterType)
wantErr := errors.New("oid info not sent from authenticatoin module")

got, gotErr := prepareCheckAccessRequestBody(req, clusterType, resourceId, false)
got, gotErr := prepareCheckAccessRequestBody(req, clusterType, resourceId, false, false)

if got != nil && gotErr != wantErr {
t.Errorf("Want:%v WantErr:%v, got:%v, gotErr:%v", nil, wantErr, got, gotErr)
Expand All @@ -584,7 +584,7 @@ func Test_prepareCheckAccessRequestBody(t *testing.T) {
clusterType = "arc"
wantErr = errors.New("oid info sent from authenticatoin module is not valid")

got, gotErr = prepareCheckAccessRequestBody(req, clusterType, resourceId, false)
got, gotErr = prepareCheckAccessRequestBody(req, clusterType, resourceId, false, false)

if got != nil && gotErr != wantErr {
t.Errorf("Want:%v WantErr:%v, got:%v, gotErr:%v", nil, wantErr, got, gotErr)
Expand All @@ -600,7 +600,7 @@ func Test_prepareCheckAccessRequestBodyWithNamespace(t *testing.T) {
// testing with new ns scope format
var want string = "resourceId/providers/Microsoft.KubernetesConfiguration/namespaces/dev"

got, gotErr := prepareCheckAccessRequestBody(req, clusterType, resourceId, true)
got, gotErr := prepareCheckAccessRequestBody(req, clusterType, resourceId, false, true)

if got == nil {
t.Errorf("Want: not nil Got: nil, gotErr:%v", gotErr)
Expand All @@ -613,7 +613,19 @@ func Test_prepareCheckAccessRequestBodyWithNamespace(t *testing.T) {
// testing with the old namespace format
want = "resourceId/namespaces/dev"

got, gotErr = prepareCheckAccessRequestBody(req, clusterType, resourceId, false)
got, gotErr = prepareCheckAccessRequestBody(req, clusterType, resourceId, false, false)
if got == nil {
t.Errorf("Want: not nil Got: nil, gotErr:%v", gotErr)
}

if got != nil && got[0].Resource.Id != want {
t.Errorf("Want:%v, got:%v", want, got)
}

// testing without namespace
want = "resourceId"

got, gotErr = prepareCheckAccessRequestBody(req, clusterType, resourceId, true, false)
if got == nil {
t.Errorf("Want: not nil Got: nil, gotErr:%v", gotErr)
}
Expand Down
12 changes: 8 additions & 4 deletions authz/providers/azure/rbac/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type AccessInfo struct {
armCallLimit int
skipCheck map[string]void
skipAuthzForNonAADUsers bool
skipAuthzNamespace bool
allowNonResDiscoveryPathAccess bool
useNamespaceResourceScopeFormat bool
lock sync.RWMutex
Expand Down Expand Up @@ -167,6 +168,7 @@ func newAccessInfo(tokenProvider graph.TokenProvider, rbacURL *url.URL, opts aut
azureResourceId: opts.ResourceId,
armCallLimit: opts.ARMCallLimit,
skipAuthzForNonAADUsers: opts.SkipAuthzForNonAADUsers,
skipAuthzNamespace: opts.SkipAuthzNamespace,
allowNonResDiscoveryPathAccess: opts.AllowNonResDiscoveryPathAccess,
useNamespaceResourceScopeFormat: opts.UseNamespaceResourceScopeFormat,
}
Expand Down Expand Up @@ -293,17 +295,19 @@ func (a *AccessInfo) setReqHeaders(req *http.Request) {
}

func (a *AccessInfo) CheckAccess(request *authzv1.SubjectAccessReviewSpec) (*authzv1.SubjectAccessReviewStatus, error) {
checkAccessBodies, err := prepareCheckAccessRequestBody(request, a.clusterType, a.azureResourceId, a.useNamespaceResourceScopeFormat)
checkAccessBodies, err := prepareCheckAccessRequestBody(request, a.clusterType, a.azureResourceId, a.skipAuthzNamespace, a.useNamespaceResourceScopeFormat)
if err != nil {
return nil, errors.Wrap(err, "error in preparing check access request")
}

checkAccessURL := *a.apiURL
// Append the path for azure cluster resource id
checkAccessURL.Path = path.Join(checkAccessURL.Path, a.azureResourceId)
exist, nameSpaceString := getNameSpaceScope(request, a.useNamespaceResourceScopeFormat)
if exist {
checkAccessURL.Path = path.Join(checkAccessURL.Path, nameSpaceString)
if !a.skipAuthzNamespace {
exist, nameSpaceString := getNameSpaceScope(request, a.useNamespaceResourceScopeFormat)
if exist {
checkAccessURL.Path = path.Join(checkAccessURL.Path, nameSpaceString)
}
}

checkAccessURL.Path = path.Join(checkAccessURL.Path, checkAccessPath)
Expand Down