From 68ff0afcb755be1611bc376cb0e677c770bafba0 Mon Sep 17 00:00:00 2001 From: Matt Brock Date: Fri, 3 Jan 2025 10:03:56 -0600 Subject: [PATCH] Adding permissions and applying command params --- .../azureoidc/accessgraph_sync.go | 33 ++++++++++++++----- lib/msgraph/client.go | 4 +++ tool/teleport/common/teleport.go | 8 ++--- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/lib/integrations/azureoidc/accessgraph_sync.go b/lib/integrations/azureoidc/accessgraph_sync.go index e4411710ecafc..7959b83f3547d 100644 --- a/lib/integrations/azureoidc/accessgraph_sync.go +++ b/lib/integrations/azureoidc/accessgraph_sync.go @@ -9,12 +9,14 @@ import ( "github.com/google/uuid" "github.com/gravitational/teleport/lib/cloud/provisioning" "github.com/gravitational/teleport/lib/config" + "github.com/gravitational/teleport/lib/msgraph" + "github.com/gravitational/teleport/lib/utils/slices" "github.com/gravitational/trace" "log/slog" "os" ) -func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, name string) (*provisioning.Action, error) { +func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, managedId string, roleName string) (*provisioning.Action, error) { runnerFn := func(ctx context.Context) error { // Create the managed identity userIdCli, err := armmsi.NewUserAssignedIdentitiesClient(subId, cred, nil) @@ -22,6 +24,7 @@ func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, n return trace.Wrap(fmt.Errorf("could not create managed identity client: %v", err)) } id := armmsi.Identity{} + userIdCli.Get(ctx) mgdIdRes, err := userIdCli.CreateOrUpdate(ctx, "", name, id, nil) if err != nil { return trace.Wrap(fmt.Errorf("could not create managed identity: %v", err)) @@ -36,15 +39,23 @@ func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, n } roleDefId := uuid.New().String() customRole := "CustomRole" - // TODO(mbrock): Determine scope - scope := "" + scope := fmt.Sprintf("/subscriptions/%s", subId) roleDefinition := armauthorization.RoleDefinition{ Name: &roleDefId, Properties: &armauthorization.RoleDefinitionProperties{ - RoleName: &name, - RoleType: &customRole, + RoleName: &roleName, + RoleType: &customRole, Permissions: []*armauthorization.Permission{ - // TODO(mbrock): Add permissions + { + Actions: slices.ToPointers([]string{ + "Microsoft.Compute/virtualMachines/read", + "Microsoft.Compute/virtualMachines/list", + "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/read", + "Microsoft.Compute/virtualMachineScaleSets/virtualMachines/list", + "Microsoft.Authorization/roleDefinitions/read", + "Microsoft.Authorization/roleAssignments/read", + }), + }, }, AssignableScopes: []*string{&scope}, // Scope must be provided }, @@ -54,7 +65,7 @@ func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, n return trace.Wrap(fmt.Errorf("failed to create custom role: %v", err)) } - // Assign the role to the managed identity + // Assign the Azure role to the managed identity roleAssignCli, err := armauthorization.NewRoleAssignmentsClient(subId, cred, nil) if err != nil { return fmt.Errorf("failed to create role assignments client: %v", err) @@ -65,7 +76,7 @@ func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, n } roleAssignParams := armauthorization.RoleAssignmentCreateParameters{ Properties: &armauthorization.RoleAssignmentProperties{ - PrincipalID: mgdIdRes.ID, + PrincipalID: &managedId, RoleDefinitionID: roleRes.ID, }, } @@ -74,6 +85,12 @@ func newManagedIdAction(cred *azidentity.DefaultAzureCredential, subId string, n return fmt.Errorf("failed to create role assignment: %v", err) } + // Assign the Graph API permissions to the managed identity + graphCli, err := msgraph.NewClient(msgraph.Config{ + TokenProvider: cred, + }) + graphCli.GetServicePrincipalByAppId() + return nil } cfg := provisioning.ActionConfig{ diff --git a/lib/msgraph/client.go b/lib/msgraph/client.go index 26ea34e1d45c2..9fdffd7eb3bfa 100644 --- a/lib/msgraph/client.go +++ b/lib/msgraph/client.go @@ -45,6 +45,10 @@ const baseURL = "https://graph.microsoft.com/v1.0" // defaultPageSize is the page size used when [Config.PageSize] is not specified. const defaultPageSize = 500 +// graphAppId is the pre-defined application ID of the Graph API +// Ref: [https://learn.microsoft.com/en-us/troubleshoot/entra/entra-id/governance/verify-first-party-apps-sign-in#application-ids-of-commonly-used-microsoft-applications]. +const graphAppId = "00000003-0000-0000-c000-000000000000" + // scopes defines OAuth scopes the client authenticates for. var scopes = []string{"https://graph.microsoft.com/.default"} diff --git a/tool/teleport/common/teleport.go b/tool/teleport/common/teleport.go index bf900ee78cc01..af460e08ddd91 100644 --- a/tool/teleport/common/teleport.go +++ b/tool/teleport/common/teleport.go @@ -514,10 +514,10 @@ func Run(options Options) (app *kingpin.Application, executedCommand string, con integrationConfAccessGraphAWSSyncCmd.Flag("confirm", "Apply changes without confirmation prompt.").BoolVar(&ccf.IntegrationConfAccessGraphAWSSyncArguments.AutoConfirm) integrationConfAccessGraphAzureSyncCmd := integrationConfAccessGraphCmd.Command("azure", "Creates/updates permissions for syncing data into Access Graph service.") - integrationConfAccessGraphAzureSyncCmd.Flag("managed-identity", "The managed identity runs the discovery service.").Required() - integrationConfAccessGraphAzureSyncCmd.Flag("role", "The role attached to the managed identity with the discovery permissions.").Required() - integrationConfAccessGraphAzureSyncCmd.Flag("subscription-id", "The subscription ID in which to discovery resources.") - integrationConfAccessGraphAzureSyncCmd.Flag("confirm", "Apply changes without confirmation prompt.") + integrationConfAccessGraphAzureSyncCmd.Flag("managed-identity", "The managed identity runs the Discovery service.").Required().StringVar(&ccf.IntegrationConfAccessGraphAzureSyncArguments.ManagedIdentity) + integrationConfAccessGraphAzureSyncCmd.Flag("role", "The role attached to the managed identity with the discovery permissions.").Required().StringVar(&ccf.IntegrationConfAccessGraphAzureSyncArguments.Role) + integrationConfAccessGraphAzureSyncCmd.Flag("subscription-id", "The subscription ID in which to discovery resources.").StringVar(&ccf.IntegrationConfAccessGraphAzureSyncArguments.SubscriptionID) + integrationConfAccessGraphAzureSyncCmd.Flag("confirm", "Apply changes without confirmation prompt.").BoolVar(&ccf.IntegrationConfAccessGraphAzureSyncArguments.AutoConfirm) integrationConfAWSOIDCIdPCmd := integrationConfigureCmd.Command("awsoidc-idp", "Creates an IAM IdP (OIDC) in your AWS account to allow the AWS OIDC Integration to access AWS APIs.") integrationConfAWSOIDCIdPCmd.Flag("cluster", "Teleport Cluster name.").Required().StringVar(&ccf.