Skip to content

Commit

Permalink
api for listing policies attatched to a bucket (#660)
Browse files Browse the repository at this point in the history
api for listing policies attatched to a bucket
  • Loading branch information
adfost committed Mar 19, 2021
1 parent 934e8c9 commit 26f7982
Show file tree
Hide file tree
Showing 9 changed files with 829 additions and 0 deletions.
64 changes: 64 additions & 0 deletions restapi/admin_policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,70 @@ func registersPoliciesHandler(api *operations.ConsoleAPI) {
}
return admin_api.NewSetPolicyMultipleNoContent()
})
api.AdminAPIListPoliciesWithBucketHandler = admin_api.ListPoliciesWithBucketHandlerFunc(func(params admin_api.ListPoliciesWithBucketParams, session *models.Principal) middleware.Responder {
policyResponse, err := getListPoliciesWithBucketResponse(session, params.Bucket)
if err != nil {
return admin_api.NewListPoliciesWithBucketDefault(int(err.Code)).WithPayload(err)
}
return admin_api.NewListPoliciesWithBucketOK().WithPayload(policyResponse)
})
}

func getListPoliciesWithBucketResponse(session *models.Principal, bucket string) (*models.ListPoliciesResponse, *models.Error) {
ctx := context.Background()
mAdmin, err := newMAdminClient(session)
if err != nil {
return nil, prepareError(err)
}
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := adminClient{client: mAdmin}

policies, err := listPoliciesWithBucket(ctx, bucket, adminClient)
if err != nil {
return nil, prepareError(err)
}
// serialize output
listPoliciesResponse := &models.ListPoliciesResponse{
Policies: policies,
Total: int64(len(policies)),
}
return listPoliciesResponse, nil
}

// listPoliciesWithBucket calls MinIO server to list all policy names present on the server that apply to a particular bucket.
// listPoliciesWithBucket() converts the map[string][]byte returned by client.listPolicies()
// to []*models.Policy by iterating over each key in policyRawMap and
// then using Unmarshal on the raw bytes to create a *models.Policy
func listPoliciesWithBucket(ctx context.Context, bucket string, client MinioAdmin) ([]*models.Policy, error) {
policyMap, err := client.listPolicies(ctx)
var policies []*models.Policy
if err != nil {
return nil, err
}
for name, policy := range policyMap {
policy, err := parsePolicy(name, policy)
if err != nil {
return nil, err
}
if policyMatchesBucket(policy, bucket) {
policies = append(policies, policy)
}
}
return policies, nil
}

func policyMatchesBucket(policy *models.Policy, bucket string) bool {
policyData := &iampolicy.Policy{}
json.Unmarshal([]byte(policy.Policy), policyData)
policyStatements := policyData.Statements
for i := 0; i < len(policyStatements); i++ {
resources := policyStatements[i].Resources
if resources.Match(bucket, map[string][]string{}) {
return true
}
}
return false
}

// listPolicies calls MinIO server to list all policy names present on the server.
Expand Down
116 changes: 116 additions & 0 deletions restapi/admin_policies_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,119 @@ func Test_SetPolicyMultiple(t *testing.T) {
})
}
}

func Test_policyMatchesBucket(t *testing.T) {
type args struct {
policy *models.Policy
bucket string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "Test1",
args: args{policy: &models.Policy{Name: "consoleAdmin", Policy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"admin:*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}`}, bucket: "test1"},
want: true,
},
{
name: "Test2",
args: args{policy: &models.Policy{Name: "consoleAdmin", Policy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket1"
]
}
]
}`}, bucket: "test1"},
want: false,
},
{
name: "Test3",
args: args{policy: &models.Policy{Name: "consoleAdmin", Policy: `{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:ListStorageLensConfigurations",
"s3:GetAccessPoint",
"s3:PutAccountPublicAccessBlock",
"s3:GetAccountPublicAccessBlock",
"s3:ListAllMyBuckets",
"s3:ListAccessPoints",
"s3:ListJobs",
"s3:PutStorageLensConfiguration",
"s3:CreateJob"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::test",
"arn:aws:s3:::test/*",
"arn:aws:s3:::lkasdkljasd090901",
"arn:aws:s3:::lkasdkljasd090901/*"
]
}
]
}`}, bucket: "test1"},
want: false,
},
{
name: "Test4",
args: args{policy: &models.Policy{Name: "consoleAdmin", Policy: `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::bucket1"
]
}
]
}`}, bucket: "bucket1"},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := policyMatchesBucket(tt.args.policy, tt.args.bucket); got != tt.want {
t.Errorf("policyMatchesBucket() = %v, want %v", got, tt.want)
}
})
}
}
86 changes: 86 additions & 0 deletions restapi/embedded_spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

90 changes: 90 additions & 0 deletions restapi/operations/admin_api/list_policies_with_bucket.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 26f7982

Please sign in to comment.