diff --git a/pkg/api/controller.go b/pkg/api/controller.go index 495630bfaa0..7e9ed0809e2 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -120,11 +120,9 @@ func (c *Controller) Login(w http.ResponseWriter, r *http.Request, body LoginJSO } func (c *Controller) GetPhysicalAddress(w http.ResponseWriter, r *http.Request, repository string, branch string, params GetPhysicalAddressParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -176,11 +174,9 @@ func (c *Controller) GetPhysicalAddress(w http.ResponseWriter, r *http.Request, } func (c *Controller) LinkPhysicalAddress(w http.ResponseWriter, r *http.Request, body LinkPhysicalAddressJSONRequestBody, repository string, branch string, params LinkPhysicalAddressParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -257,11 +253,9 @@ func (c *Controller) LinkPhysicalAddress(w http.ResponseWriter, r *http.Request, } func (c *Controller) ListGroups(w http.ResponseWriter, r *http.Request, params ListGroupsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListGroupsAction, - Resource: permissions.All, - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListGroupsAction, + Resource: permissions.All, }) { return } @@ -296,11 +290,9 @@ func (c *Controller) ListGroups(w http.ResponseWriter, r *http.Request, params L } func (c *Controller) CreateGroup(w http.ResponseWriter, r *http.Request, body CreateGroupJSONRequestBody) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateGroupAction, - Resource: permissions.GroupArn(body.Id), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateGroupAction, + Resource: permissions.GroupArn(body.Id), }) { return } @@ -323,11 +315,9 @@ func (c *Controller) CreateGroup(w http.ResponseWriter, r *http.Request, body Cr } func (c *Controller) DeleteGroup(w http.ResponseWriter, r *http.Request, groupID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteGroupAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteGroupAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -346,11 +336,9 @@ func (c *Controller) DeleteGroup(w http.ResponseWriter, r *http.Request, groupID } func (c *Controller) GetGroup(w http.ResponseWriter, r *http.Request, groupID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadGroupAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadGroupAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -373,11 +361,9 @@ func (c *Controller) GetGroup(w http.ResponseWriter, r *http.Request, groupID st } func (c *Controller) ListGroupMembers(w http.ResponseWriter, r *http.Request, groupID string, params ListGroupMembersParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadGroupAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadGroupAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -410,11 +396,9 @@ func (c *Controller) ListGroupMembers(w http.ResponseWriter, r *http.Request, gr } func (c *Controller) DeleteGroupMembership(w http.ResponseWriter, r *http.Request, groupID string, userID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.RemoveGroupMemberAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.RemoveGroupMemberAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -429,11 +413,9 @@ func (c *Controller) DeleteGroupMembership(w http.ResponseWriter, r *http.Reques } func (c *Controller) AddGroupMembership(w http.ResponseWriter, r *http.Request, groupID string, userID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.AddGroupMemberAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.AddGroupMemberAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -447,11 +429,9 @@ func (c *Controller) AddGroupMembership(w http.ResponseWriter, r *http.Request, } func (c *Controller) ListGroupPolicies(w http.ResponseWriter, r *http.Request, groupID string, params ListGroupPoliciesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadGroupAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadGroupAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -500,11 +480,9 @@ func serializePolicy(p *model.Policy) Policy { } func (c *Controller) DetachPolicyFromGroup(w http.ResponseWriter, r *http.Request, groupID string, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DetachPolicyAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DetachPolicyAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -518,11 +496,9 @@ func (c *Controller) DetachPolicyFromGroup(w http.ResponseWriter, r *http.Reques } func (c *Controller) AttachPolicyToGroup(w http.ResponseWriter, r *http.Request, groupID string, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.AttachPolicyAction, - Resource: permissions.GroupArn(groupID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.AttachPolicyAction, + Resource: permissions.GroupArn(groupID), }) { return } @@ -537,11 +513,9 @@ func (c *Controller) AttachPolicyToGroup(w http.ResponseWriter, r *http.Request, } func (c *Controller) ListPolicies(w http.ResponseWriter, r *http.Request, params ListPoliciesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListPoliciesAction, - Resource: permissions.All, - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListPoliciesAction, + Resource: permissions.All, }) { return } @@ -572,11 +546,9 @@ func (c *Controller) ListPolicies(w http.ResponseWriter, r *http.Request, params } func (c *Controller) CreatePolicy(w http.ResponseWriter, r *http.Request, body CreatePolicyJSONRequestBody) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreatePolicyAction, - Resource: permissions.PolicyArn(body.Id), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreatePolicyAction, + Resource: permissions.PolicyArn(body.Id), }) { return } @@ -607,11 +579,9 @@ func (c *Controller) CreatePolicy(w http.ResponseWriter, r *http.Request, body C } func (c *Controller) DeletePolicy(w http.ResponseWriter, r *http.Request, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeletePolicyAction, - Resource: permissions.PolicyArn(policyID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeletePolicyAction, + Resource: permissions.PolicyArn(policyID), }) { return } @@ -629,11 +599,9 @@ func (c *Controller) DeletePolicy(w http.ResponseWriter, r *http.Request, policy } func (c *Controller) GetPolicy(w http.ResponseWriter, r *http.Request, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadPolicyAction, - Resource: permissions.PolicyArn(policyID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadPolicyAction, + Resource: permissions.PolicyArn(policyID), }) { return } @@ -653,11 +621,9 @@ func (c *Controller) GetPolicy(w http.ResponseWriter, r *http.Request, policyID } func (c *Controller) UpdatePolicy(w http.ResponseWriter, r *http.Request, body UpdatePolicyJSONRequestBody, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.UpdatePolicyAction, - Resource: permissions.PolicyArn(policyID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.UpdatePolicyAction, + Resource: permissions.PolicyArn(policyID), }) { return } @@ -687,11 +653,9 @@ func (c *Controller) UpdatePolicy(w http.ResponseWriter, r *http.Request, body U } func (c *Controller) ListUsers(w http.ResponseWriter, r *http.Request, params ListUsersParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListUsersAction, - Resource: permissions.All, - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListUsersAction, + Resource: permissions.All, }) { return } @@ -724,11 +688,9 @@ func (c *Controller) ListUsers(w http.ResponseWriter, r *http.Request, params Li } func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request, body CreateUserJSONRequestBody) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateUserAction, - Resource: permissions.UserArn(body.Id), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateUserAction, + Resource: permissions.UserArn(body.Id), }) { return } @@ -752,11 +714,9 @@ func (c *Controller) CreateUser(w http.ResponseWriter, r *http.Request, body Cre } func (c *Controller) DeleteUser(w http.ResponseWriter, r *http.Request, userID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteUserAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteUserAction, + Resource: permissions.UserArn(userID), }) { return } @@ -775,11 +735,9 @@ func (c *Controller) DeleteUser(w http.ResponseWriter, r *http.Request, userID s } func (c *Controller) GetUser(w http.ResponseWriter, r *http.Request, userID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadUserAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadUserAction, + Resource: permissions.UserArn(userID), }) { return } @@ -801,11 +759,9 @@ func (c *Controller) GetUser(w http.ResponseWriter, r *http.Request, userID stri } func (c *Controller) ListUserCredentials(w http.ResponseWriter, r *http.Request, userID string, params ListUserCredentialsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListCredentialsAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListCredentialsAction, + Resource: permissions.UserArn(userID), }) { return } @@ -838,11 +794,9 @@ func (c *Controller) ListUserCredentials(w http.ResponseWriter, r *http.Request, } func (c *Controller) CreateCredentials(w http.ResponseWriter, r *http.Request, userID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateCredentialsAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateCredentialsAction, + Resource: permissions.UserArn(userID), }) { return } @@ -861,11 +815,9 @@ func (c *Controller) CreateCredentials(w http.ResponseWriter, r *http.Request, u } func (c *Controller) DeleteCredentials(w http.ResponseWriter, r *http.Request, userID string, accessKeyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteCredentialsAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteCredentialsAction, + Resource: permissions.UserArn(userID), }) { return } @@ -884,11 +836,9 @@ func (c *Controller) DeleteCredentials(w http.ResponseWriter, r *http.Request, u } func (c *Controller) GetCredentials(w http.ResponseWriter, r *http.Request, userID string, accessKeyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadCredentialsAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadCredentialsAction, + Resource: permissions.UserArn(userID), }) { return } @@ -911,11 +861,9 @@ func (c *Controller) GetCredentials(w http.ResponseWriter, r *http.Request, user } func (c *Controller) ListUserGroups(w http.ResponseWriter, r *http.Request, userID string, params ListUserGroupsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadUserAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadUserAction, + Resource: permissions.UserArn(userID), }) { return } @@ -949,11 +897,9 @@ func (c *Controller) ListUserGroups(w http.ResponseWriter, r *http.Request, user } func (c *Controller) ListUserPolicies(w http.ResponseWriter, r *http.Request, userID string, params ListUserPoliciesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadUserAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadUserAction, + Resource: permissions.UserArn(userID), }) { return } @@ -990,11 +936,9 @@ func (c *Controller) ListUserPolicies(w http.ResponseWriter, r *http.Request, us } func (c *Controller) DetachPolicyFromUser(w http.ResponseWriter, r *http.Request, userID string, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DetachPolicyAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DetachPolicyAction, + Resource: permissions.UserArn(userID), }) { return } @@ -1008,11 +952,9 @@ func (c *Controller) DetachPolicyFromUser(w http.ResponseWriter, r *http.Request } func (c *Controller) AttachPolicyToUser(w http.ResponseWriter, r *http.Request, userID string, policyID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.AttachPolicyAction, - Resource: permissions.UserArn(userID), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.AttachPolicyAction, + Resource: permissions.UserArn(userID), }) { return } @@ -1027,11 +969,9 @@ func (c *Controller) AttachPolicyToUser(w http.ResponseWriter, r *http.Request, } func (c *Controller) GetStorageConfig(w http.ResponseWriter, r *http.Request) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadStorageConfiguration, - Resource: permissions.All, - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadStorageConfiguration, + Resource: permissions.All, }) { return } @@ -1049,11 +989,9 @@ func (c *Controller) HealthCheck(w http.ResponseWriter, _ *http.Request) { } func (c *Controller) ListRepositories(w http.ResponseWriter, r *http.Request, params ListRepositoriesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListRepositoriesAction, - Resource: permissions.All, - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListRepositoriesAction, + Resource: permissions.All, }) { return } @@ -1084,17 +1022,15 @@ func (c *Controller) ListRepositories(w http.ResponseWriter, r *http.Request, pa } func (c *Controller) CreateRepository(w http.ResponseWriter, r *http.Request, body CreateRepositoryJSONRequestBody, params CreateRepositoryParams) { - if !c.authorize(w, r, []permissions.Permission{ - { + if !c.authorize(w, r, &auth.AndPermission{ + &auth.OnePermission{ Action: permissions.CreateRepositoryAction, Resource: permissions.RepoArn(body.Name), }, - }) || !c.authorize(w, r, []permissions.Permission{ - { + &auth.OnePermission{ Action: permissions.AttachStorageNamespace, Resource: permissions.StorageNamespace(body.StorageNamespace), - }, - }) { + }}) { return } ctx := r.Context() @@ -1177,11 +1113,9 @@ func ensureStorageNamespace(ctx context.Context, adapter block.Adapter, storageN } func (c *Controller) DeleteRepository(w http.ResponseWriter, r *http.Request, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteRepositoryAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteRepositoryAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1200,11 +1134,9 @@ func (c *Controller) DeleteRepository(w http.ResponseWriter, r *http.Request, re } func (c *Controller) GetRepository(w http.ResponseWriter, r *http.Request, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadRepositoryAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadRepositoryAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1230,11 +1162,9 @@ func (c *Controller) GetRepository(w http.ResponseWriter, r *http.Request, repos } func (c *Controller) ListRepositoryRuns(w http.ResponseWriter, r *http.Request, repository string, params ListRepositoryRunsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadActionsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadActionsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1297,11 +1227,9 @@ func runResultToActionRun(val *actions.RunResult) ActionRun { } func (c *Controller) GetRun(w http.ResponseWriter, r *http.Request, repository string, runID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadActionsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadActionsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1336,11 +1264,9 @@ func (c *Controller) GetRun(w http.ResponseWriter, r *http.Request, repository s } func (c *Controller) ListRunHooks(w http.ResponseWriter, r *http.Request, repository string, runID string, params ListRunHooksParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadActionsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadActionsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1397,11 +1323,9 @@ func (c *Controller) ListRunHooks(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) GetRunHookOutput(w http.ResponseWriter, r *http.Request, repository string, runID string, hookRunID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadActionsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadActionsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1440,11 +1364,9 @@ func (c *Controller) GetRunHookOutput(w http.ResponseWriter, r *http.Request, re } func (c *Controller) ListBranches(w http.ResponseWriter, r *http.Request, repository string, params ListBranchesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListBranchesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListBranchesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1471,11 +1393,9 @@ func (c *Controller) ListBranches(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) CreateBranch(w http.ResponseWriter, r *http.Request, body CreateBranchJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateBranchAction, - Resource: permissions.BranchArn(repository, body.Name), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateBranchAction, + Resource: permissions.BranchArn(repository, body.Name), }) { return } @@ -1490,11 +1410,9 @@ func (c *Controller) CreateBranch(w http.ResponseWriter, r *http.Request, body C } func (c *Controller) DeleteBranch(w http.ResponseWriter, r *http.Request, repository string, branch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteBranchAction, - Resource: permissions.BranchArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteBranchAction, + Resource: permissions.BranchArn(repository, branch), }) { return } @@ -1508,11 +1426,9 @@ func (c *Controller) DeleteBranch(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) GetBranch(w http.ResponseWriter, r *http.Request, repository string, branch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadBranchAction, - Resource: permissions.BranchArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadBranchAction, + Resource: permissions.BranchArn(repository, branch), }) { return } @@ -1564,11 +1480,9 @@ func handleAPIError(w http.ResponseWriter, err error) bool { } func (c *Controller) ResetBranch(w http.ResponseWriter, r *http.Request, body ResetBranchJSONRequestBody, repository string, branch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.RevertBranchAction, - Resource: permissions.BranchArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.RevertBranchAction, + Resource: permissions.BranchArn(repository, branch), }) { return } @@ -1593,11 +1507,9 @@ func (c *Controller) ResetBranch(w http.ResponseWriter, r *http.Request, body Re } func (c *Controller) Commit(w http.ResponseWriter, r *http.Request, body CommitJSONRequestBody, repository string, branch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateCommitAction, - Resource: permissions.BranchArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateCommitAction, + Resource: permissions.BranchArn(repository, branch), }) { return } @@ -1642,11 +1554,9 @@ func (c *Controller) Commit(w http.ResponseWriter, r *http.Request, body CommitJ } func (c *Controller) DiffBranch(w http.ResponseWriter, r *http.Request, repository string, branch string, params DiffBranchParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListObjectsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListObjectsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1690,11 +1600,9 @@ func (c *Controller) DiffBranch(w http.ResponseWriter, r *http.Request, reposito } func (c *Controller) DeleteObject(w http.ResponseWriter, r *http.Request, repository string, branch string, params DeleteObjectParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -1709,11 +1617,9 @@ func (c *Controller) DeleteObject(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) UploadObject(w http.ResponseWriter, r *http.Request, repository string, branch string, params UploadObjectParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -1820,11 +1726,9 @@ func (c *Controller) UploadObject(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) StageObject(w http.ResponseWriter, r *http.Request, body StageObjectJSONRequestBody, repository string, branch string, params StageObjectParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -1888,11 +1792,9 @@ func (c *Controller) StageObject(w http.ResponseWriter, r *http.Request, body St } func (c *Controller) RevertBranch(w http.ResponseWriter, r *http.Request, body RevertBranchJSONRequestBody, repository string, branch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.RevertBranchAction, - Resource: permissions.BranchArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.RevertBranchAction, + Resource: permissions.BranchArn(repository, branch), }) { return } @@ -1916,11 +1818,9 @@ func (c *Controller) RevertBranch(w http.ResponseWriter, r *http.Request, body R } func (c *Controller) GetCommit(w http.ResponseWriter, r *http.Request, repository string, commitID string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadCommitAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadCommitAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1951,11 +1851,9 @@ func (c *Controller) GetCommit(w http.ResponseWriter, r *http.Request, repositor } func (c *Controller) GetGarbageCollectionRules(w http.ResponseWriter, r *http.Request, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.GetGarbageCollectionRulesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.GetGarbageCollectionRulesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1973,11 +1871,9 @@ func (c *Controller) GetGarbageCollectionRules(w http.ResponseWriter, r *http.Re } func (c *Controller) SetGarbageCollectionRules(w http.ResponseWriter, r *http.Request, body SetGarbageCollectionRulesJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.SetGarbageCollectionRulesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.SetGarbageCollectionRulesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -1997,11 +1893,9 @@ func (c *Controller) SetGarbageCollectionRules(w http.ResponseWriter, r *http.Re } func (c *Controller) PrepareGarbageCollectionCommits(w http.ResponseWriter, r *http.Request, body PrepareGarbageCollectionCommitsJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.PrepareGarbageCollectionCommitsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.PrepareGarbageCollectionCommitsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2019,11 +1913,9 @@ func (c *Controller) PrepareGarbageCollectionCommits(w http.ResponseWriter, r *h } func (c *Controller) GetBranchProtectionRules(w http.ResponseWriter, r *http.Request, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.GetBranchProtectionRulesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.GetBranchProtectionRulesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2042,11 +1934,9 @@ func (c *Controller) GetBranchProtectionRules(w http.ResponseWriter, r *http.Req } func (c *Controller) DeleteBranchProtectionRule(w http.ResponseWriter, r *http.Request, body DeleteBranchProtectionRuleJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.SetBranchProtectionRulesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.SetBranchProtectionRulesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2059,11 +1949,9 @@ func (c *Controller) DeleteBranchProtectionRule(w http.ResponseWriter, r *http.R } func (c *Controller) CreateBranchProtectionRule(w http.ResponseWriter, r *http.Request, body CreateBranchProtectionRuleJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.SetBranchProtectionRulesAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.SetBranchProtectionRulesAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2078,16 +1966,15 @@ func (c *Controller) CreateBranchProtectionRule(w http.ResponseWriter, r *http.R } func (c *Controller) GetMetaRange(w http.ResponseWriter, r *http.Request, repository string, metaRange string) { - if !c.authorize(w, r, []permissions.Permission{ - { + if !c.authorize(w, r, &auth.AndPermission{ + &auth.OnePermission{ Action: permissions.ListObjectsAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.ReadRepositoryAction, Resource: permissions.RepoArn(repository), - }, - }) { + }}) { return } ctx := r.Context() @@ -2106,16 +1993,15 @@ func (c *Controller) GetMetaRange(w http.ResponseWriter, r *http.Request, reposi } func (c *Controller) GetRange(w http.ResponseWriter, r *http.Request, repository string, pRange string) { - if !c.authorize(w, r, []permissions.Permission{ - { + if !c.authorize(w, r, &auth.AndPermission{ + &auth.OnePermission{ Action: permissions.ListObjectsAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.ReadRepositoryAction, Resource: permissions.RepoArn(repository), - }, - }) { + }}) { return } ctx := r.Context() @@ -2133,20 +2019,19 @@ func (c *Controller) GetRange(w http.ResponseWriter, r *http.Request, repository } func (c *Controller) DumpRefs(w http.ResponseWriter, r *http.Request, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { + if !c.authorize(w, r, &auth.AndPermission{ + &auth.OnePermission{ Action: permissions.ListTagsAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.ListBranchesAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.ListCommitsAction, Resource: permissions.RepoArn(repository), - }, - }) { + }}) { return } ctx := r.Context() @@ -2196,20 +2081,19 @@ func (c *Controller) DumpRefs(w http.ResponseWriter, r *http.Request, repository } func (c *Controller) RestoreRefs(w http.ResponseWriter, r *http.Request, body RestoreRefsJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { + if !c.authorize(w, r, &auth.AndPermission{ + &auth.OnePermission{ Action: permissions.CreateTagAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.CreateBranchAction, Resource: permissions.RepoArn(repository), }, - { + &auth.OnePermission{ Action: permissions.CreateCommitAction, Resource: permissions.RepoArn(repository), - }, - }) { + }}) { return } ctx := r.Context() @@ -2245,11 +2129,9 @@ func (c *Controller) RestoreRefs(w http.ResponseWriter, r *http.Request, body Re } func (c *Controller) CreateSymlinkFile(w http.ResponseWriter, r *http.Request, repository string, branch string, params CreateSymlinkFileParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repository, branch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repository, branch), }) { return } @@ -2333,11 +2215,9 @@ func writeSymlink(ctx context.Context, repo *catalog.Repository, branch string, } func (c *Controller) DiffRefs(w http.ResponseWriter, r *http.Request, repository string, leftRef string, rightRef string, params DiffRefsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListObjectsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListObjectsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2391,11 +2271,9 @@ func (c *Controller) LogCommits(w http.ResponseWriter, r *http.Request, reposito } func (c *Controller) logCommitsHelper(w http.ResponseWriter, r *http.Request, repository string, ref string, after *PaginationAfter, amount *PaginationAmount) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadBranchAction, - Resource: permissions.BranchArn(repository, ref), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadBranchAction, + Resource: permissions.BranchArn(repository, ref), }) { return } @@ -2432,11 +2310,9 @@ func (c *Controller) logCommitsHelper(w http.ResponseWriter, r *http.Request, re } func (c *Controller) GetObject(w http.ResponseWriter, r *http.Request, repository string, ref string, params GetObjectParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -2488,11 +2364,9 @@ func (c *Controller) GetObject(w http.ResponseWriter, r *http.Request, repositor } func (c *Controller) ListObjects(w http.ResponseWriter, r *http.Request, repository string, ref string, params ListObjectsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListObjectsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListObjectsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2566,11 +2440,9 @@ func (c *Controller) ListObjects(w http.ResponseWriter, r *http.Request, reposit } func (c *Controller) StatObject(w http.ResponseWriter, r *http.Request, repository string, ref string, params StatObjectParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -2612,11 +2484,9 @@ func (c *Controller) StatObject(w http.ResponseWriter, r *http.Request, reposito } func (c *Controller) GetUnderlyingProperties(w http.ResponseWriter, r *http.Request, repository string, ref string, params GetUnderlyingPropertiesParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadObjectAction, - Resource: permissions.ObjectArn(repository, params.Path), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(repository, params.Path), }) { return } @@ -2648,11 +2518,9 @@ func (c *Controller) GetUnderlyingProperties(w http.ResponseWriter, r *http.Requ } func (c *Controller) MergeIntoBranch(w http.ResponseWriter, r *http.Request, body MergeIntoBranchJSONRequestBody, repository string, sourceRef string, destinationBranch string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateCommitAction, - Resource: permissions.BranchArn(repository, destinationBranch), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateCommitAction, + Resource: permissions.BranchArn(repository, destinationBranch), }) { return } @@ -2714,11 +2582,9 @@ func newMergeResultFromCatalog(res *catalog.MergeResult) MergeResult { } func (c *Controller) ListTags(w http.ResponseWriter, r *http.Request, repository string, params ListTagsParams) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ListTagsAction, - Resource: permissions.RepoArn(repository), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ListTagsAction, + Resource: permissions.RepoArn(repository), }) { return } @@ -2745,11 +2611,9 @@ func (c *Controller) ListTags(w http.ResponseWriter, r *http.Request, repository } func (c *Controller) CreateTag(w http.ResponseWriter, r *http.Request, body CreateTagJSONRequestBody, repository string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.CreateTagAction, - Resource: permissions.TagArn(repository, body.Id), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.CreateTagAction, + Resource: permissions.TagArn(repository, body.Id), }) { return } @@ -2768,11 +2632,9 @@ func (c *Controller) CreateTag(w http.ResponseWriter, r *http.Request, body Crea } func (c *Controller) DeleteTag(w http.ResponseWriter, r *http.Request, repository string, tag string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.DeleteTagAction, - Resource: permissions.TagArn(repository, tag), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.DeleteTagAction, + Resource: permissions.TagArn(repository, tag), }) { return } @@ -2786,11 +2648,9 @@ func (c *Controller) DeleteTag(w http.ResponseWriter, r *http.Request, repositor } func (c *Controller) GetTag(w http.ResponseWriter, r *http.Request, repository string, tag string) { - if !c.authorize(w, r, []permissions.Permission{ - { - Action: permissions.ReadTagAction, - Resource: permissions.TagArn(repository, tag), - }, + if !c.authorize(w, r, &auth.OnePermission{ + Action: permissions.ReadTagAction, + Resource: permissions.TagArn(repository, tag), }) { return } @@ -3033,7 +2893,7 @@ func paginationFor(hasMore bool, results interface{}, fieldName string) Paginati return pagination } -func (c *Controller) authorize(w http.ResponseWriter, r *http.Request, perms []permissions.Permission) bool { +func (c *Controller) authorize(w http.ResponseWriter, r *http.Request, perms auth.PermissionNode) bool { ctx := r.Context() user, ok := ctx.Value(UserContextKey).(*model.User) if !ok || user == nil { diff --git a/pkg/auth/service.go b/pkg/auth/service.go index 4358898d158..bbe86d7c2d6 100644 --- a/pkg/auth/service.go +++ b/pkg/auth/service.go @@ -21,7 +21,7 @@ import ( type AuthorizationRequest struct { Username string - RequiredPermissions []permissions.Permission + RequiredPermissions PermissionNode } type AuthorizationResponse struct { @@ -852,6 +852,71 @@ func interpolateUser(resource string, username string) string { return strings.ReplaceAll(resource, "${user}", username) } +type CheckResult int + +const ( + CheckAllow CheckResult = iota // Permission allowed + CheckNeutral // Permission neither allowed nor denied + CheckDeny // Permission denied +) + +type PermissionNode interface { + CheckPermissions(policies []*model.Policy, req *AuthorizationRequest) CheckResult +} + +type OnePermission permissions.Permission +type AndPermission []PermissionNode +type OrPermission []PermissionNode + +func (p OnePermission) CheckPermissions(policies []*model.Policy, req *AuthorizationRequest) CheckResult { + allowed := CheckNeutral + for _, policy := range policies { + for _, stmt := range policy.Statement { + resource := interpolateUser(stmt.Resource, req.Username) + if !ArnMatch(resource, p.Resource) { + continue + } + for _, action := range stmt.Action { + if !wildcard.Match(action, p.Action) { + continue // not a matching action + } + + if stmt.Effect == model.StatementEffectDeny { + // this is a "Deny" and it takes precedence + return CheckDeny + } + + allowed = CheckAllow + } + } + } + return allowed +} + +func (p AndPermission) CheckPermissions(policies []*model.Policy, req *AuthorizationRequest) CheckResult { + for _, perm := range p { + result := perm.CheckPermissions(policies, req) + if result == CheckNeutral || result == CheckDeny { + return result + } + } + return CheckAllow +} + +func (p OrPermission) CheckPermissions(policies []*model.Policy, req *AuthorizationRequest) CheckResult { + allowed := CheckNeutral + for _, perm := range p { + result := perm.CheckPermissions(policies, req) + if result == CheckDeny { + return CheckDeny + } + if allowed != CheckAllow { + allowed = result + } + } + return allowed +} + func (s *DBAuthService) Authorize(ctx context.Context, req *AuthorizationRequest) (*AuthorizationResponse, error) { policies, _, err := s.ListEffectivePolicies(ctx, req.Username, &model.PaginationParams{ After: "", // all @@ -861,34 +926,10 @@ func (s *DBAuthService) Authorize(ctx context.Context, req *AuthorizationRequest if err != nil { return nil, err } - allowed := false - for _, perm := range req.RequiredPermissions { - for _, policy := range policies { - for _, stmt := range policy.Statement { - resource := interpolateUser(stmt.Resource, req.Username) - if !ArnMatch(resource, perm.Resource) { - continue - } - for _, action := range stmt.Action { - if !wildcard.Match(action, perm.Action) { - continue // not a matching action - } - - if stmt.Effect == model.StatementEffectDeny { - // this is a "Deny" and it takes precedence - return &AuthorizationResponse{ - Allowed: false, - Error: ErrInsufficientPermissions, - }, nil - } - - allowed = true - } - } - } - } - if !allowed { + allowed := req.RequiredPermissions.CheckPermissions(policies, req) + + if allowed != CheckAllow { return &AuthorizationResponse{ Allowed: false, Error: ErrInsufficientPermissions, diff --git a/pkg/auth/service_test.go b/pkg/auth/service_test.go index bdc7d9c6a03..2a8bc66a273 100644 --- a/pkg/auth/service_test.go +++ b/pkg/auth/service_test.go @@ -20,7 +20,6 @@ import ( "github.com/treeverse/lakefs/pkg/auth/model" authparams "github.com/treeverse/lakefs/pkg/auth/params" "github.com/treeverse/lakefs/pkg/logging" - "github.com/treeverse/lakefs/pkg/permissions" "github.com/treeverse/lakefs/pkg/testutil" ) @@ -190,11 +189,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "fs:WriteObject", - Resource: "arn:lakefs:fs:::repository/foo/object/bar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "fs:WriteObject", + Resource: "arn:lakefs:fs:::repository/foo/object/bar", }, } }, @@ -217,11 +214,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "fs:WriteObject", - Resource: "arn:lakefs:fs:::repository/foo/object/bar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "fs:WriteObject", + Resource: "arn:lakefs:fs:::repository/foo/object/bar", }, } }, @@ -244,11 +239,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "fs:WriteObject", - Resource: "arn:lakefs:fs:::repository/foo/object/bar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "fs:WriteObject", + Resource: "arn:lakefs:fs:::repository/foo/object/bar", }, } }, @@ -271,11 +264,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:CreateUser", - Resource: "arn:lakefs:auth:::user/foobar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:CreateUser", + Resource: "arn:lakefs:auth:::user/foobar", }, } }, @@ -298,11 +289,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:CreateUser", - Resource: fmt.Sprintf("arn:lakefs:auth:::user/%s", userName), - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:CreateUser", + Resource: fmt.Sprintf("arn:lakefs:auth:::user/%s", userName), }, } }, @@ -325,11 +314,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:CreateUser", - Resource: fmt.Sprintf("arn:lakefs:auth:::user/%sxxxx", userName), - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:CreateUser", + Resource: fmt.Sprintf("arn:lakefs:auth:::user/%sxxxx", userName), }, } }, @@ -352,11 +339,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:CreateUser", - Resource: "arn:lakefs:auth:::user/foobar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:CreateUser", + Resource: "arn:lakefs:auth:::user/foobar", }, } }, @@ -379,11 +364,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:CreateUser", - Resource: "arn:lakefs:auth:::user/foobar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:CreateUser", + Resource: "arn:lakefs:auth:::user/foobar", }, } }, @@ -406,11 +389,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:DeleteUser", - Resource: "arn:lakefs:auth:::user/foobar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:DeleteUser", + Resource: "arn:lakefs:auth:::user/foobar", }, } }, @@ -442,11 +423,9 @@ func TestDBAuthService_Authorize(t *testing.T) { request: func(userName string) *auth.AuthorizationRequest { return &auth.AuthorizationRequest{ Username: userName, - RequiredPermissions: []permissions.Permission{ - { - Action: "auth:DeleteUser", - Resource: "arn:lakefs:auth:::user/foobar", - }, + RequiredPermissions: &auth.OnePermission{ + Action: "auth:DeleteUser", + Resource: "arn:lakefs:auth:::user/foobar", }, } }, diff --git a/pkg/gateway/handler.go b/pkg/gateway/handler.go index 08b8c0ce7e2..20fee4f1594 100644 --- a/pkg/gateway/handler.go +++ b/pkg/gateway/handler.go @@ -1,6 +1,7 @@ package gateway import ( + "errors" "net/http" gohttputil "net/http/httputil" "net/url" @@ -18,7 +19,6 @@ import ( "github.com/treeverse/lakefs/pkg/gateway/simulator" "github.com/treeverse/lakefs/pkg/httputil" "github.com/treeverse/lakefs/pkg/logging" - "github.com/treeverse/lakefs/pkg/permissions" "github.com/treeverse/lakefs/pkg/stats" ) @@ -195,14 +195,21 @@ func PathOperationHandler(sc *ServerContext, handler operations.PathOperationHan matchedHost := ctx.Value(ContextKeyMatchedHost).(bool) o := ctx.Value(ContextKeyOperation).(*operations.Operation) perms, err := handler.RequiredPermissions(req, repo.Name, refID, path) + if err != nil { - _ = o.EncodeError(w, req, gatewayerrors.ErrAccessDenied.ToAPIErr()) + if errors.Is(err, gatewayerrors.ErrInvalidCopySource) { + _ = o.EncodeError(w, req, gatewayerrors.ErrInvalidCopySource.ToAPIErr()) + } else { + _ = o.EncodeError(w, req, gatewayerrors.ErrAccessDenied.ToAPIErr()) + } return } + authOp := authorize(w, req, sc.authService, perms) if authOp == nil { return } + // run callback operation := &operations.PathOperation{ RefOperation: &operations.RefOperation{ @@ -225,14 +232,14 @@ func PathOperationHandler(sc *ServerContext, handler operations.PathOperationHan }) } -func authorize(w http.ResponseWriter, req *http.Request, authService simulator.GatewayAuthService, perms []permissions.Permission) *operations.AuthorizedOperation { +func authorize(w http.ResponseWriter, req *http.Request, authService simulator.GatewayAuthService, perms auth.PermissionNode) *operations.AuthorizedOperation { ctx := req.Context() o := ctx.Value(ContextKeyOperation).(*operations.Operation) username := ctx.Value(ContextKeyUser).(*model.User).Username authContext := ctx.Value(ContextKeyAuthContext).(sig.SigContext) - if len(perms) == 0 { - // Either no permissions are required, or they will be checked later. + if perms == nil { + // has not provided required permissions return &operations.AuthorizedOperation{ Operation: o, Principal: username, diff --git a/pkg/gateway/middleware.go b/pkg/gateway/middleware.go index eb368c62deb..1c4c8df58c9 100644 --- a/pkg/gateway/middleware.go +++ b/pkg/gateway/middleware.go @@ -147,7 +147,7 @@ func EnrichWithRepositoryOrFallback(c catalog.Interface, authService simulator.G if errors.Is(err, catalog.ErrNotFound) { authResp, authErr := authService.Authorize(ctx, &auth.AuthorizationRequest{ Username: username, - RequiredPermissions: []permissions.Permission{{Action: permissions.ListRepositoriesAction, Resource: "*"}}, + RequiredPermissions: &auth.OnePermission{Action: permissions.ListRepositoriesAction, Resource: "*"}, }) if authErr != nil || authResp.Error != nil || !authResp.Allowed { _ = o.EncodeError(w, req, gatewayerrors.ErrAccessDenied.ToAPIErr()) diff --git a/pkg/gateway/operations/base.go b/pkg/gateway/operations/base.go index b237d200813..be9e793099e 100644 --- a/pkg/gateway/operations/base.go +++ b/pkg/gateway/operations/base.go @@ -15,7 +15,6 @@ import ( "github.com/treeverse/lakefs/pkg/gateway/simulator" "github.com/treeverse/lakefs/pkg/httputil" "github.com/treeverse/lakefs/pkg/logging" - "github.com/treeverse/lakefs/pkg/permissions" ) const StorageClassHeader = "x-amz-storage-class" @@ -208,25 +207,26 @@ func (o *PathOperation) EncodeError(w http.ResponseWriter, req *http.Request, er } type OperationHandler interface { - RequiredPermissions(req *http.Request) ([]permissions.Permission, error) + RequiredPermissions(req *http.Request) (auth.PermissionNode, error) Handle(w http.ResponseWriter, req *http.Request, op *Operation) } type AuthenticatedOperationHandler interface { - RequiredPermissions(req *http.Request) ([]permissions.Permission, error) + RequiredPermissions(req *http.Request) (auth.PermissionNode, error) Handle(w http.ResponseWriter, req *http.Request, op *AuthorizedOperation) } type RepoOperationHandler interface { - RequiredPermissions(req *http.Request, repository string) ([]permissions.Permission, error) + RequiredPermissions(req *http.Request, repository string) (auth.PermissionNode, error) Handle(w http.ResponseWriter, req *http.Request, op *RepoOperation) } type BranchOperationHandler interface { - RequiredPermissions(req *http.Request, repository, branch string) ([]permissions.Permission, error) + RequiredPermissions(req *http.Request, repository, branch string) (auth.PermissionNode, error) Handle(w http.ResponseWriter, req *http.Request, op *RefOperation) } + type PathOperationHandler interface { - RequiredPermissions(req *http.Request, repository, branch, path string) ([]permissions.Permission, error) + RequiredPermissions(req *http.Request, repository, branch, path string) (auth.PermissionNode, error) Handle(w http.ResponseWriter, req *http.Request, op *PathOperation) } diff --git a/pkg/gateway/operations/deleteobject.go b/pkg/gateway/operations/deleteobject.go index 3438ae0196e..dfa77a930b3 100644 --- a/pkg/gateway/operations/deleteobject.go +++ b/pkg/gateway/operations/deleteobject.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/block" "github.com/treeverse/lakefs/pkg/catalog" gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" @@ -14,12 +15,10 @@ import ( type DeleteObject struct{} -func (controller *DeleteObject) RequiredPermissions(_ *http.Request, repoID, _, path string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.DeleteObjectAction, - Resource: permissions.ObjectArn(repoID, path), - }, +func (controller *DeleteObject) RequiredPermissions(_ *http.Request, repoID, _, path string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.DeleteObjectAction, + Resource: permissions.ObjectArn(repoID, path), }, nil } diff --git a/pkg/gateway/operations/deleteobjects.go b/pkg/gateway/operations/deleteobjects.go index 578f25680a6..8afaca404e2 100644 --- a/pkg/gateway/operations/deleteobjects.go +++ b/pkg/gateway/operations/deleteobjects.go @@ -16,7 +16,7 @@ import ( type DeleteObjects struct{} -func (controller *DeleteObjects) RequiredPermissions(_ *http.Request, _ string) ([]permissions.Permission, error) { +func (controller *DeleteObjects) RequiredPermissions(_ *http.Request, _ string) (auth.PermissionNode, error) { return nil, nil } @@ -44,11 +44,9 @@ func (controller *DeleteObjects) Handle(w http.ResponseWriter, req *http.Request // authorize this object deletion authResp, err := o.Auth.Authorize(req.Context(), &auth.AuthorizationRequest{ Username: o.Principal, - RequiredPermissions: []permissions.Permission{ - { - Action: permissions.DeleteObjectAction, - Resource: permissions.ObjectArn(o.Repository.Name, resolvedPath.Path), - }, + RequiredPermissions: &auth.OnePermission{ + Action: permissions.DeleteObjectAction, + Resource: permissions.ObjectArn(o.Repository.Name, resolvedPath.Path), }, }) if err != nil || !authResp.Allowed { diff --git a/pkg/gateway/operations/getobject.go b/pkg/gateway/operations/getobject.go index 3195f14a05d..11b54977fea 100644 --- a/pkg/gateway/operations/getobject.go +++ b/pkg/gateway/operations/getobject.go @@ -7,6 +7,7 @@ import ( "net/http" "time" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/block" "github.com/treeverse/lakefs/pkg/catalog" gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" @@ -18,12 +19,10 @@ import ( type GetObject struct{} -func (controller *GetObject) RequiredPermissions(_ *http.Request, repoID, _, path string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.ReadObjectAction, - Resource: permissions.ObjectArn(repoID, path), - }, +func (controller *GetObject) RequiredPermissions(_ *http.Request, repoID, _, path string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(repoID, path), }, nil } diff --git a/pkg/gateway/operations/headbucket.go b/pkg/gateway/operations/headbucket.go index afd129a55e6..e6eecd05821 100644 --- a/pkg/gateway/operations/headbucket.go +++ b/pkg/gateway/operations/headbucket.go @@ -3,17 +3,16 @@ package operations import ( "net/http" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/permissions" ) type HeadBucket struct{} -func (controller *HeadBucket) RequiredPermissions(_ *http.Request, repoID string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.ReadRepositoryAction, - Resource: permissions.RepoArn(repoID), - }, +func (controller *HeadBucket) RequiredPermissions(_ *http.Request, repoID string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.ReadRepositoryAction, + Resource: permissions.RepoArn(repoID), }, nil } diff --git a/pkg/gateway/operations/headobject.go b/pkg/gateway/operations/headobject.go index b9c77c97359..a717c5da60c 100644 --- a/pkg/gateway/operations/headobject.go +++ b/pkg/gateway/operations/headobject.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/catalog" gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" "github.com/treeverse/lakefs/pkg/httputil" @@ -13,12 +14,10 @@ import ( type HeadObject struct{} -func (controller *HeadObject) RequiredPermissions(_ *http.Request, repoID, _, path string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.ReadObjectAction, - Resource: permissions.ObjectArn(repoID, path), - }, +func (controller *HeadObject) RequiredPermissions(_ *http.Request, repoID, _, path string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(repoID, path), }, nil } diff --git a/pkg/gateway/operations/listbuckets.go b/pkg/gateway/operations/listbuckets.go index c0e10f76a10..5032180dc47 100644 --- a/pkg/gateway/operations/listbuckets.go +++ b/pkg/gateway/operations/listbuckets.go @@ -3,6 +3,7 @@ package operations import ( "net/http" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/permissions" "github.com/treeverse/lakefs/pkg/gateway/errors" @@ -11,12 +12,10 @@ import ( type ListBuckets struct{} -func (controller *ListBuckets) RequiredPermissions(_ *http.Request) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.ListRepositoriesAction, - Resource: "*", - }, +func (controller *ListBuckets) RequiredPermissions(_ *http.Request) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.ListRepositoriesAction, + Resource: "*", }, nil } diff --git a/pkg/gateway/operations/listobjects.go b/pkg/gateway/operations/listobjects.go index e352269eb7a..fccb998bffa 100644 --- a/pkg/gateway/operations/listobjects.go +++ b/pkg/gateway/operations/listobjects.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/catalog" gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" "github.com/treeverse/lakefs/pkg/gateway/path" @@ -21,26 +22,22 @@ const ( type ListObjects struct{} -func (controller *ListObjects) RequiredPermissions(req *http.Request, repoID string) ([]permissions.Permission, error) { +func (controller *ListObjects) RequiredPermissions(req *http.Request, repoID string) (auth.PermissionNode, error) { // check if we're listing files in a branch, or listing branches params := req.URL.Query() delimiter := params.Get("delimiter") prefix := params.Get("prefix") if delimiter == "/" && !strings.Contains(prefix, "/") { - return []permissions.Permission{ - { - Action: permissions.ListBranchesAction, - Resource: permissions.RepoArn(repoID), - }, + return &auth.OnePermission{ + Action: permissions.ListBranchesAction, + Resource: permissions.RepoArn(repoID), }, nil } // otherwise, we're listing objects within a branch - return []permissions.Permission{ - { - Action: permissions.ListObjectsAction, - Resource: permissions.RepoArn(repoID), - }, + return &auth.OnePermission{ + Action: permissions.ListObjectsAction, + Resource: permissions.RepoArn(repoID), }, nil } diff --git a/pkg/gateway/operations/postobject.go b/pkg/gateway/operations/postobject.go index 9b223591f76..f97d6538abb 100644 --- a/pkg/gateway/operations/postobject.go +++ b/pkg/gateway/operations/postobject.go @@ -11,6 +11,7 @@ import ( "time" "github.com/google/uuid" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/block" gatewayErrors "github.com/treeverse/lakefs/pkg/gateway/errors" "github.com/treeverse/lakefs/pkg/gateway/multiparts" @@ -29,12 +30,10 @@ const ( type PostObject struct{} -func (controller *PostObject) RequiredPermissions(_ *http.Request, repoID, _, path string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repoID, path), - }, +func (controller *PostObject) RequiredPermissions(_ *http.Request, repoID, _, path string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repoID, path), }, nil } diff --git a/pkg/gateway/operations/putbucket.go b/pkg/gateway/operations/putbucket.go index 4a76db4cf0e..f084d0e377f 100644 --- a/pkg/gateway/operations/putbucket.go +++ b/pkg/gateway/operations/putbucket.go @@ -3,6 +3,7 @@ package operations import ( "net/http" + "github.com/treeverse/lakefs/pkg/auth" gatewayerrors "github.com/treeverse/lakefs/pkg/gateway/errors" "github.com/treeverse/lakefs/pkg/permissions" ) @@ -12,15 +13,13 @@ import ( // create a new repo), but *does* detect whether the repo already exists. type PutBucket struct{} -func (controller *PutBucket) RequiredPermissions(_ *http.Request, repoID string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { - // Mimic S3, which requires s3:CreateBucket to call - // create-bucket, even if we only want to receive - // 409. - Action: permissions.CreateRepositoryAction, - Resource: permissions.RepoArn(repoID), - }, +func (controller *PutBucket) RequiredPermissions(_ *http.Request, repoID string) (auth.PermissionNode, error) { + return &auth.OnePermission{ + // Mimic S3, which requires s3:CreateBucket to call + // create-bucket, even if we only want to receive + // 409. + Action: permissions.CreateRepositoryAction, + Resource: permissions.RepoArn(repoID), }, nil } diff --git a/pkg/gateway/operations/putobject.go b/pkg/gateway/operations/putobject.go index 05f66b5c8e6..8800b06c02a 100644 --- a/pkg/gateway/operations/putobject.go +++ b/pkg/gateway/operations/putobject.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/treeverse/lakefs/pkg/auth" "github.com/treeverse/lakefs/pkg/block" "github.com/treeverse/lakefs/pkg/catalog" gatewayErrors "github.com/treeverse/lakefs/pkg/gateway/errors" @@ -31,11 +32,34 @@ const ( type PutObject struct{} -func (controller *PutObject) RequiredPermissions(_ *http.Request, repoID, _, path string) ([]permissions.Permission, error) { - return []permissions.Permission{ - { +func (controller *PutObject) RequiredPermissions(req *http.Request, repoID, _, destPath string) (auth.PermissionNode, error) { + // TODO(Eden): use the get copy source code and ResolveAbsolutePath function only once (extractEntryFromCopyReq) + copySource := req.Header.Get(CopySourceHeader) + copySourceDecoded, err := url.QueryUnescape(copySource) + if err != nil { + copySourceDecoded = copySource + } + + if len(copySourceDecoded) == 0 { + return &auth.OnePermission{ Action: permissions.WriteObjectAction, - Resource: permissions.ObjectArn(repoID, path), + Resource: permissions.ObjectArn(repoID, destPath), + }, nil + } + // check this is a copy operation + p, err := path.ResolveAbsolutePath(copySourceDecoded) + if err != nil { + logging.Default().WithError(err).Error("could not parse copy source path") + return nil, gatewayErrors.ErrInvalidCopySource + } + return &auth.AndPermission{ + &auth.OnePermission{ + Action: permissions.WriteObjectAction, + Resource: permissions.ObjectArn(repoID, destPath), + }, + &auth.OnePermission{ + Action: permissions.ReadObjectAction, + Resource: permissions.ObjectArn(p.Repo, p.Path), }, }, nil }