Skip to content

Commit

Permalink
feat: support grant dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
rahmatrhd committed Dec 3, 2024
1 parent d95c75c commit 80ce978
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 29 deletions.
55 changes: 55 additions & 0 deletions core/appeal/mocks/providerService.go

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

40 changes: 36 additions & 4 deletions core/appeal/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type providerService interface {
ValidateAppeal(context.Context, *domain.Appeal, *domain.Provider, *domain.Policy) error
GetPermissions(context.Context, *domain.ProviderConfig, string, string) ([]interface{}, error)
IsExclusiveRoleAssignment(context.Context, string, string) bool
GetDependencyGrants(context.Context, domain.Grant) ([]*domain.Grant, error)
}

//go:generate mockery --name=resourceService --exported --with-expecter
Expand Down Expand Up @@ -1489,15 +1490,46 @@ func (s *Service) GrantAccessToProvider(ctx context.Context, a *domain.Appeal, o
}
}

g := a.Grant
appealCopy := *a
appealCopy.Grant = nil
g.Appeal = &appealCopy
if err := s.providerService.GrantAccess(ctx, *a.Grant); err != nil {
grantWithAppeal := *a.Grant
grantWithAppeal.Appeal = &appealCopy

// grant access dependencies (if any)
dependencyGrants, err := s.providerService.GetDependencyGrants(ctx, grantWithAppeal)
if err != nil {
return fmt.Errorf("getting grant dependencies: %w", err)
}
for _, dg := range dependencyGrants {
activeGrants, err := s.grantService.List(ctx, domain.ListGrantsFilter{
Statuses: []string{string(domain.GrantStatusActive)},
AccountIDs: []string{dg.AccountID},
AccountTypes: []string{dg.AccountType},
ResourceIDs: []string{dg.Resource.ID},
Permissions: dg.Permissions,
Size: 1,
})
if err != nil {
return fmt.Errorf("failed to get existing active grant dependency: %w", err)
}

if len(activeGrants) > 0 {
break
}

dg.Appeal = &appealCopy
if err := s.providerService.GrantAccess(ctx, *dg); err != nil {
return fmt.Errorf("failed to grant an access dependency: %w", err)
}
// TODO: store grant to db
}

// grant main access
if err := s.providerService.GrantAccess(ctx, grantWithAppeal); err != nil {
return fmt.Errorf("granting access: %w", err)
}
g.Appeal = nil

grantWithAppeal.Appeal = nil
return nil
}

Expand Down
47 changes: 47 additions & 0 deletions core/provider/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ type assignmentTyper interface {
IsExclusiveRoleAssignment(context.Context) bool
}

type grantDependenciesResolver interface {
GetDependencyGrants(context.Context, domain.Provider, domain.Grant) ([]*domain.Grant, error)
}

//go:generate mockery --name=resourceService --exported --with-expecter
type resourceService interface {
Find(context.Context, domain.ListResourcesFilter) ([]*domain.Resource, error)
Expand Down Expand Up @@ -569,6 +573,49 @@ func (s *Service) IsExclusiveRoleAssignment(ctx context.Context, providerType, r
return false
}

func (s *Service) GetDependencyGrants(ctx context.Context, g domain.Grant) ([]*domain.Grant, error) {
client := s.getClient(g.Resource.ProviderType)
if client == nil {
return nil, ErrInvalidProviderType
}

c, ok := client.(grantDependenciesResolver)
if !ok {
return nil, nil
}

p, err := s.getProviderConfig(ctx, g.Resource.ProviderType, g.Resource.ProviderURN)
if err != nil {
return nil, err
}

dependencies, err := c.GetDependencyGrants(ctx, *p, g)
if err != nil {
return nil, err
}

for _, d := range dependencies {
resources, err := s.resourceService.Find(ctx, domain.ListResourcesFilter{
ProviderType: d.Resource.ProviderType,
ProviderURN: d.Resource.ProviderURN,
ResourceType: d.Resource.Type,
ResourceURN: d.Resource.URN,
Size: 1,
})
if err != nil {
return nil, fmt.Errorf("unable to resolve resource %q for grant dependency: %w", d.Resource.URN, err)
}
if len(resources) == 0 {
return nil, fmt.Errorf("unable to resolve resource %q for grant dependency: not found", d.Resource.URN)
}

d.ResourceID = resources[0].ID
d.Resource = resources[0]
}

return dependencies, nil
}

func (s *Service) fetchNewResources(ctx context.Context, p *domain.Provider) ([]*domain.Resource, int, error) {
c := s.getClient(p.Type)
if c == nil {
Expand Down
7 changes: 7 additions & 0 deletions domain/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ func (pc ProviderConfig) GetResourceTypes() (resourceTypes []string) {
return
}

func (pc ProviderConfig) GetParameterKeys() (keys []string) {
for _, param := range pc.Parameters {
keys = append(keys, param.Key)
}
return
}

func (pc ProviderConfig) GetFilterForResourceType(resourceType string) string {
for _, resource := range pc.Resources {
if resource.Type == resourceType {
Expand Down
2 changes: 2 additions & 0 deletions plugins/providers/maxcompute/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const (
resourceTypeTable = "table"

parameterRAMRoleKey = "ram_role"

projectPermissionMember = "member"
)

var (
Expand Down
Loading

0 comments on commit 80ce978

Please sign in to comment.