Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Azure role definitions and assignments clients #48632

Closed
wants to merge 5 commits into from

Conversation

mvbrock
Copy link
Contributor

@mvbrock mvbrock commented Nov 7, 2024

Part of of https://github.com/gravitational/access-graph/issues/640 to provide visibility of Azure resource in the Access Graph, and originating from the Azure integration POC branch master...mvbrock/azure-integration-poc. This PR adds the Azure role definitions and assignments clients to the cloud library, in order to build access graph relationships for Azure identities.

@mvbrock mvbrock requested a review from tigrato November 7, 2024 20:56
@github-actions github-actions bot requested review from nklaassen and rudream November 7, 2024 20:56
@mvbrock mvbrock requested review from r0mant and ryanclark and removed request for nklaassen and rudream November 7, 2024 20:56
Copy link

This pull request is automatically being deployed by Amplify Hosting (learn more).

Access this pull request here: https://pr-48632.d3pp5qlev8mo18.amplifyapp.com

@mvbrock mvbrock added the no-changelog Indicates that a PR does not require a changelog entry label Nov 7, 2024
Comment on lines 12 to 33
type RoleAssignmentsClient interface {
ListRoleAssignments(ctx context.Context, scope string) ([]*armauthorization.RoleAssignment, error)
}

type roleAssignmentsClient struct {
cli *armauthorization.RoleAssignmentsClient
}

func (c *roleAssignmentsClient) ListRoleAssignments(ctx context.Context, scope string) ([]*armauthorization.RoleAssignment, error) {
pager := c.cli.NewListForScopePager(scope, nil)
roleDefs := make([]*armauthorization.RoleAssignment, 0, 128)
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
roleDefs = append(roleDefs, page.Value...)
}
return roleDefs, nil
}

func NewRoleAssignmentsClient(subscription string, cred azcore.TokenCredential, options *arm.ClientOptions) (RoleAssignmentsClient, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of interfaces is a bit of an anti-pattern. It's generally recommended to define the interface at the consumer, and not the producer. See https://go.dev/wiki/CodeReviewComments#interfaces.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I can remove the interface entirely, rename roleAssignmentsClient to the be the concrete type, and (eventually) create the interface at the consumer. This kind of makes the PR an anti-pattern, in that I'm defining an interface and an implementation without a consumer, aka not driven by business logic. I might actually just close this PR and incorporate the new clients into a PR with the consumer of the functionality (and define the interface in the consumer).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me. I think we've come to realize that these cloud clients interfaces cause problems and result in bloating dependency trees. As we've started to migrate things to use aws-sdk-go-v2, previous consumers of the aws cloud client interface have opted to forgo that and define a smaller local interface instead.

Comment on lines 12 to 33
type RoleDefinitionsClient interface {
ListRoleDefinitions(ctx context.Context, scope string) ([]*armauthorization.RoleDefinition, error)
}

type roleDefinitionsClient struct {
cli *armauthorization.RoleDefinitionsClient
}

func (c *roleDefinitionsClient) ListRoleDefinitions(ctx context.Context, scope string) ([]*armauthorization.RoleDefinition, error) {
pager := c.cli.NewListPager(scope, nil)
roleDefs := make([]*armauthorization.RoleDefinition, 0, 128)
for pager.More() {
page, err := pager.NextPage(ctx)
if err != nil {
return nil, trace.Wrap(err)
}
roleDefs = append(roleDefs, page.Value...)
}
return roleDefs, nil
}

func NewRoleDefinitionsClient(subscription string, cred azcore.TokenCredential, options *arm.ClientOptions) (RoleDefinitionsClient, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This use of interfaces is a bit of an anti-pattern. It's generally recommended to define the interface at the consumer, and not the producer. See https://go.dev/wiki/CodeReviewComments#interfaces.

@mvbrock
Copy link
Contributor Author

mvbrock commented Nov 11, 2024

Closing per convo with @rosstimothy about defining interfaces from the consumer and adding functionality based on both business requirements and interface specs.

@mvbrock mvbrock closed this Nov 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-changelog Indicates that a PR does not require a changelog entry size/md
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants