Skip to content

Commit

Permalink
Merge pull request #34 from ConductorOne/ggreer/more-permissions
Browse files Browse the repository at this point in the history
Fix grant/revoke errors for some kinds of grants.
  • Loading branch information
ggreer authored Sep 27, 2024
2 parents 7c0ccb1 + d27d86b commit 17a0e0a
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 98 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ jobs:
BATON_BITBUCKETDC_USERNAME: ${{ secrets.BATON_BITBUCKETDC_USERNAME }}
BATON_BITBUCKETDC_PASSWORD: ${{ secrets.BATON_BITBUCKETDC_PASSWORD }}
# The following parameters are passed to grant/revoke commands
CONNECTOR_GRANT: 'group:local-group:member:user:62'
CONNECTOR_GRANT: 'group:local-group:member:user:f1'
CONNECTOR_ENTITLEMENT: 'group:local-group:member'
CONNECTOR_PRINCIPAL_TYPE: 'user'
CONNECTOR_PRINCIPAL: '62'
CONNECTOR_PRINCIPAL: 'f1'
steps:
- name: Install Go
uses: actions/setup-go@v4
Expand Down
20 changes: 5 additions & 15 deletions pkg/connector/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"slices"
"strconv"

"github.com/conductorone/baton-bitbucket-datacenter/pkg/client"
v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
Expand Down Expand Up @@ -130,11 +129,7 @@ func (g *groupBuilder) Grant(ctx context.Context, principal *v2.Resource, entitl
groupName := entitlement.Resource.Id.Resource
switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userName := principal.DisplayName
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}
userName := principal.Id.Resource

// Check if user is already a member of the group
listGroups, err := listGroupMembers(ctx, g.client, groupName)
Expand All @@ -143,7 +138,7 @@ func (g *groupBuilder) Grant(ctx context.Context, principal *v2.Resource, entitl
}

groupPos := slices.IndexFunc(listGroups, func(c client.Members) bool {
return c.ID == userId
return c.Name == userName
})
if groupPos >= 0 {
l.Info(
Expand All @@ -161,7 +156,6 @@ func (g *groupBuilder) Grant(ctx context.Context, principal *v2.Resource, entitl
}

l.Info("Group membership granted.",
zap.Int64("UserID", int64(userId)),
zap.String("User", userName),
zap.String("Group", groupName),
)
Expand Down Expand Up @@ -194,19 +188,16 @@ func (g *groupBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotations
groupName := groupResourceId.Resource
switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userName := principal.DisplayName
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}
userName := principal.Id.Resource

// Check if user is member of the group
groupMembers, err := listGroupMembers(ctx, g.client, groupName)
if err != nil {
return nil, fmt.Errorf("bitbucket(dc)-connector: failed to get group members: %w", err)
}

groupPos := slices.IndexFunc(groupMembers, func(c client.Members) bool {
return c.ID == userId
return c.Name == userName
})
if groupPos < 0 {
l.Info(
Expand All @@ -224,7 +215,6 @@ func (g *groupBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotations
}

l.Info("Group membership revoked.",
zap.Int64("UserID", int64(userId)),
zap.String("User", userName),
zap.String("Group", groupName),
)
Expand Down
20 changes: 5 additions & 15 deletions pkg/connector/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"slices"
"strconv"
"strings"

"github.com/conductorone/baton-bitbucket-datacenter/pkg/client"
Expand Down Expand Up @@ -202,18 +201,14 @@ func (o *orgBuilder) Grant(ctx context.Context, principal *v2.Resource, entitlem

switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userName := principal.DisplayName
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}
userName := principal.Id.Resource

globalUserPermissions, err := listGlobalUserPermissions(ctx, o.client)
if err != nil {
return nil, err
}
idx := slices.IndexFunc(globalUserPermissions, func(c client.UsersPermissions) bool {
return c.User.ID == userId
return c.User.Name == userName
})
if idx > -1 {
userPermission := globalUserPermissions[idx]
Expand All @@ -228,7 +223,6 @@ func (o *orgBuilder) Grant(ctx context.Context, principal *v2.Resource, entitlem
}

l.Info("User global permission granted.",
zap.Int64("UserID", int64(userId)),
zap.String("User", userName),
zap.String("Permission", permission),
)
Expand Down Expand Up @@ -294,17 +288,14 @@ func (o *orgBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotations.A

switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userName := principal.DisplayName
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}
userName := principal.Id.Resource

globalUserPermissions, err := listGlobalUserPermissions(ctx, o.client)
if err != nil {
return nil, err
}
idx := slices.IndexFunc(globalUserPermissions, func(c client.UsersPermissions) bool {
return c.User.ID == userId
return c.User.Name == userName
})
if idx == -1 {
return annotations.New(&v2.GrantAlreadyRevoked{}), nil
Expand All @@ -326,7 +317,6 @@ func (o *orgBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotations.A
}

l.Info("User global permission revoked.",
zap.Int64("UserID", int64(userId)),
zap.String("User", userName),
zap.String("Permission", permission),
)
Expand Down
54 changes: 21 additions & 33 deletions pkg/connector/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"slices"
"strconv"

"github.com/conductorone/baton-bitbucket-datacenter/pkg/client"
v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
Expand Down Expand Up @@ -177,7 +176,7 @@ func (p *projectBuilder) Grants(ctx context.Context, resource *v2.Resource, pTok
func (p *projectBuilder) Grant(ctx context.Context, principal *v2.Resource, entitlement *v2.Entitlement) (annotations.Annotations, error) {
l := ctxzap.Extract(ctx)
if principal.Id.ResourceType != resourceTypeUser.Id && principal.Id.ResourceType != resourceTypeGroup.Id {
l.Warn(
l.Error(
"bitbucket(dc)-connector: only users or groups can be granted project membership",
zap.String("principal_type", principal.Id.ResourceType),
zap.String("principal_id", principal.Id.Resource),
Expand All @@ -200,36 +199,30 @@ func (p *projectBuilder) Grant(ctx context.Context, principal *v2.Resource, enti

switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}

listUser, err := listUserProjectsPermissions(ctx, p.client, projectKey)
if err != nil {
return nil, err
}

userPos := slices.IndexFunc(listUser, func(c client.UsersPermissions) bool {
return c.User.Name == principal.DisplayName && c.Permission == permission
return c.User.Name == principal.Id.Resource && c.Permission == permission
})
if userPos >= 0 {
l.Warn(
l.Info(
"bitbucket(dc)-connector: user already has this project permission",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)
return nil, fmt.Errorf("bitbucket(dc)-connector: user %s already has this project permission", principal.DisplayName)
return annotations.New(&v2.GrantAlreadyExists{}), nil
}

err = p.client.UpdateUserProjectPermission(ctx, projectKey, principal.DisplayName, permission)
err = p.client.UpdateUserProjectPermission(ctx, projectKey, principal.Id.Resource, permission)
if err != nil {
return nil, err
}

l.Warn("Project Membership has been created.",
zap.Int64("UserID", int64(userId)),
zap.String("UserName", principal.DisplayName),
l.Info("Project Membership has been created.",
zap.String("UserName", principal.Id.Resource),
zap.String("ProjectKey", projectKey),
zap.String("Permission", permission),
)
Expand All @@ -240,23 +233,23 @@ func (p *projectBuilder) Grant(ctx context.Context, principal *v2.Resource, enti
}

groupPos := slices.IndexFunc(listGroup, func(c client.GroupsPermissions) bool {
return c.Group.Name == principal.DisplayName && c.Permission == permission
return c.Group.Name == principal.Id.Resource && c.Permission == permission
})
if groupPos >= 0 {
l.Warn(
l.Info(
"bitbucket(dc)-connector: group already has this project permission",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)
return nil, fmt.Errorf("bitbucket(dc)-connector: group %s already has this project permission", principal.DisplayName)
return annotations.New(&v2.GrantAlreadyRevoked{}), nil
}

err = p.client.UpdateGroupProjectPermission(ctx, projectKey, principal.DisplayName, permission)
err = p.client.UpdateGroupProjectPermission(ctx, projectKey, principal.Id.Resource, permission)
if err != nil {
return nil, err
}

l.Warn("Project Membership has been created.",
l.Info("Project Membership has been created.",
zap.String("GroupName", principal.DisplayName),
zap.String("ProjectKey", projectKey),
zap.String("Permission", permission),
Expand All @@ -275,7 +268,7 @@ func (p *projectBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotatio
principalIsUser := principal.Id.ResourceType == resourceTypeUser.Id
principalIsGroup := principal.Id.ResourceType == resourceTypeGroup.Id
if !principalIsUser && !principalIsGroup {
l.Warn(
l.Error(
"bitbucket(bk)-connector: only users and groups can have project permissions revoked",
zap.String("principal_id", principal.Id.Resource),
zap.String("principal_type", principal.Id.ResourceType),
Expand All @@ -299,11 +292,7 @@ func (p *projectBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotatio

switch principal.Id.ResourceType {
case resourceTypeUser.Id:
userName := principal.DisplayName
userId, err := strconv.Atoi(principal.Id.Resource)
if err != nil {
return nil, err
}
userName := principal.Id.Resource

listUser, err := listUserProjectsPermissions(ctx, p.client, projectKey)
if err != nil {
Expand All @@ -314,26 +303,25 @@ func (p *projectBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotatio
return c.User.Name == userName && c.Permission == permission
})
if userPos < 0 {
l.Warn(
l.Info(
"bitbucket(dc)-connector: user doesn't have this project permission",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)
return nil, fmt.Errorf("bitbucket(dc)-connector: user %s doesn't have this project permission", userName)
return annotations.New(&v2.GrantAlreadyRevoked{}), nil
}

err = p.client.RevokeUserProjectPermission(ctx, projectKey, userName)
if err != nil {
return nil, fmt.Errorf("bitbucket(dc)-connector: failed to remove project user permission: %w", err)
}

l.Warn("Project Membership has been revoked.",
zap.Int64("UserID", int64(userId)),
l.Info("Project Membership has been revoked.",
zap.String("UserName", userName),
zap.String("ProjectKey", projectKey),
)
case resourceTypeGroup.Id:
groupName := principal.DisplayName
groupName := principal.Id.Resource
listGroup, err := listGroupProjectsPermissions(ctx, p.client, projectKey)
if err != nil {
return nil, err
Expand All @@ -343,20 +331,20 @@ func (p *projectBuilder) Revoke(ctx context.Context, grant *v2.Grant) (annotatio
return c.Group.Name == groupName && c.Permission == permission
})
if groupPos < 0 {
l.Warn(
l.Info(
"bitbucket(dc)-connector: group doesn't have this project permission",
zap.String("principal_id", principal.Id.String()),
zap.String("principal_type", principal.Id.ResourceType),
)
return nil, fmt.Errorf("bitbucket(dc)-connector: group %s doesn't have this project permission", groupName)
return annotations.New(&v2.GrantAlreadyRevoked{}), nil
}

err = p.client.RevokeGroupProjectPermission(ctx, projectKey, groupName)
if err != nil {
return nil, fmt.Errorf("bitbucket(dc)-connector: failed to remove project group permission: %w", err)
}

l.Warn("Project Membership has been revoked.",
l.Info("Project Membership has been revoked.",
zap.String("GroupName", groupName),
zap.String("ProjectKey", projectKey),
)
Expand Down
Loading

0 comments on commit 17a0e0a

Please sign in to comment.