diff --git a/docker/go-tf-prepare/pkg/azure/azure.go b/docker/go-tf-prepare/pkg/azure/azure.go index 08507c7..3454e36 100644 --- a/docker/go-tf-prepare/pkg/azure/azure.go +++ b/docker/go-tf-prepare/pkg/azure/azure.go @@ -20,10 +20,10 @@ import ( ) // CreateResourceGroup creates Azure Resource Group (if it doesn't exist) or returns error -func CreateResourceGroup(ctx context.Context, resourceGroupName, resourceGroupLocation, subscriptionID string) error { +func CreateResourceGroup(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, subscriptionID string) error { log := logr.FromContext(ctx) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -53,10 +53,10 @@ func CreateResourceGroup(ctx context.Context, resourceGroupName, resourceGroupLo } // CreateStorageAccount creates Azure Storage Account (if it doesn't exist) or returns error -func CreateStorageAccount(ctx context.Context, resourceGroupName, resourceGroupLocation, storageAccountName, subscriptionID string) error { +func CreateStorageAccount(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, storageAccountName, subscriptionID string) error { log := logr.FromContext(ctx) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -126,10 +126,10 @@ func CreateStorageAccount(ctx context.Context, resourceGroupName, resourceGroupL } // CreateStorageAccountContainer creates Storage Account Container (if it doesn't exist) or returns error -func CreateStorageAccountContainer(ctx context.Context, resourceGroupName, storageAccountName, storageAccountContainer, subscriptionID string) error { +func CreateStorageAccountContainer(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, storageAccountName, storageAccountContainer, subscriptionID string) error { log := logr.FromContext(ctx) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -168,10 +168,10 @@ func CreateStorageAccountContainer(ctx context.Context, resourceGroupName, stora } // CreateKeyVault creates Azure Key Vault (if it doesn't exist) or returns error -func CreateKeyVault(ctx context.Context, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID string) error { +func CreateKeyVault(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID string) error { log := logr.FromContext(ctx) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -229,13 +229,13 @@ func CreateKeyVault(ctx context.Context, resourceGroupName, resourceGroupLocatio } // CreateKeyVaultAccessPolicy creates Azure Key Vault Access Policy (if it doesn't exist) or returns error -func CreateKeyVaultAccessPolicy(ctx context.Context, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID, servicePrincipalObjectID string) error { +func CreateKeyVaultAccessPolicy(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID, servicePrincipalObjectID string) error { log := logr.FromContext(ctx) var currentUserObjectID string if servicePrincipalObjectID == "" { var err error - currentUserObjectID, err = getCurrentUserObjectID(ctx, tenantID) + currentUserObjectID, err = getCurrentUserObjectID(ctx, defaultAzureCredentialOptions, tenantID) if err != nil { log.Error(err, "getCurrentUserObjectID") return err @@ -245,7 +245,7 @@ func CreateKeyVaultAccessPolicy(ctx context.Context, resourceGroupName, resource currentUserObjectID = servicePrincipalObjectID } - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -307,10 +307,10 @@ func CreateKeyVaultAccessPolicy(ctx context.Context, resourceGroupName, resource } // CreateKeyVaultKey creates Azure Key Vault Key (if it doesn't exist) or returns error -func CreateKeyVaultKey(ctx context.Context, resourceGroupName, keyVaultName, keyName, subscriptionID string) error { +func CreateKeyVaultKey(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, keyVaultName, keyName, subscriptionID string) error { log := logr.FromContext(ctx) - cred, err := azidentity.NewDefaultAzureCredential(nil) + cred, err := azidentity.NewDefaultAzureCredential(&defaultAzureCredentialOptions) if err != nil { log.Error(err, "azidentity.NewDefaultAzureCredential") return err @@ -351,12 +351,13 @@ func CreateKeyVaultKey(ctx context.Context, resourceGroupName, keyVaultName, key } // CreateResourceLock creates Azure Resource Lock (if it doesn't exist) or return error -func CreateResourceLock(ctx context.Context, resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, lockName, subscriptionID string) error { +func CreateResourceLock(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, resourceGroupName, resourceProviderNamespace, parentResourcePath, resourceType, resourceName, lockName, subscriptionID string) error { log := logr.FromContext(ctx) client := locks.NewManagementLocksClient(subscriptionID) - authorizer, err := azidext.NewDefaultAzureCredentialAdapter(nil) + credentialOptions := azidext.DefaultAzureCredentialOptions{DefaultCredential: &defaultAzureCredentialOptions} + authorizer, err := azidext.NewDefaultAzureCredentialAdapter(&credentialOptions) if err != nil { log.Error(err, "azidext.NewDefaultAzureCredentialAdapter") return err @@ -385,15 +386,14 @@ func CreateResourceLock(ctx context.Context, resourceGroupName, resourceProvider return err } -func getCurrentUserObjectID(ctx context.Context, tenantID string) (string, error) { +func getCurrentUserObjectID(ctx context.Context, defaultAzureCredentialOptions azidentity.DefaultAzureCredentialOptions, tenantID string) (string, error) { log := logr.FromContext(ctx) client := graphrbac.NewSignedInUserClient(tenantID) - defaultCredential := azidentity.DefaultAzureCredentialOptions{} tokenRequestOptions := azcore.TokenRequestOptions{Scopes: []string{"https://graph.windows.net/.default"}} authenticationPolicy := azcore.AuthenticationPolicyOptions{Options: tokenRequestOptions} - credentialOptions := azidext.DefaultAzureCredentialOptions{DefaultCredential: &defaultCredential, AuthenticationPolicy: &authenticationPolicy} + credentialOptions := azidext.DefaultAzureCredentialOptions{DefaultCredential: &defaultAzureCredentialOptions, AuthenticationPolicy: &authenticationPolicy} authorizer, err := azidext.NewDefaultAzureCredentialAdapter(&credentialOptions) if err != nil { log.Error(err, "azidext.NewDefaultAzureCredentialAdapter") diff --git a/docker/go-tf-prepare/pkg/azure/azure_cli.go b/docker/go-tf-prepare/pkg/azure/azure_cli.go index f170599..cdad8c2 100644 --- a/docker/go-tf-prepare/pkg/azure/azure_cli.go +++ b/docker/go-tf-prepare/pkg/azure/azure_cli.go @@ -3,69 +3,10 @@ package azure import ( "context" + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" "github.com/urfave/cli/v2" ) -// Action executes the Azure action -func Action(ctx context.Context, cli *cli.Context) error { - servicePrincipalObjectID := cli.String("service-principal-object-id") - subscriptionID := cli.String("subscription-id") - tenantID := cli.String("tenant-id") - resourceGroupName := cli.String("resource-group-name") - resourceGroupLocation := cli.String("resource-group-location") - storageAccountName := cli.String("storage-account-name") - storageAccountContainer := cli.String("storage-account-container") - keyVaultName := cli.String("keyvault-name") - keyVaultKeyName := cli.String("keyvault-key-name") - resourceLocks := cli.Bool("resource-locks") - - err := CreateResourceGroup(ctx, resourceGroupName, resourceGroupLocation, subscriptionID) - if err != nil { - return err - } - - err = CreateStorageAccount(ctx, resourceGroupName, resourceGroupLocation, storageAccountName, subscriptionID) - if err != nil { - return err - } - - if resourceLocks { - err = CreateResourceLock(ctx, resourceGroupName, "Microsoft.Storage", "", "storageAccounts", storageAccountName, "DoNotDelete", subscriptionID) - if err != nil { - return err - } - } - - err = CreateStorageAccountContainer(ctx, resourceGroupName, storageAccountName, storageAccountContainer, subscriptionID) - if err != nil { - return err - } - - err = CreateKeyVault(ctx, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID) - if err != nil { - return err - } - - if resourceLocks { - err = CreateResourceLock(ctx, resourceGroupName, "Microsoft.KeyVault", "", "vaults", keyVaultName, "DoNotDelete", subscriptionID) - if err != nil { - return err - } - } - - err = CreateKeyVaultAccessPolicy(ctx, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID, servicePrincipalObjectID) - if err != nil { - return err - } - - err = CreateKeyVaultKey(ctx, resourceGroupName, keyVaultName, keyVaultKeyName, subscriptionID) - if err != nil { - return err - } - - return nil -} - // Flags returns the cli flags for Azure func Flags() []cli.Flag { flags := []cli.Flag{ @@ -129,6 +70,89 @@ func Flags() []cli.Flag { Value: true, EnvVars: []string{"AZURE_RESOURCE_LOCKS"}, }, + &cli.BoolFlag{ + Name: "exclude-cli-credential", + Usage: "Should Azure CLI authentication be excluded from authentication chain?", + Value: false, + EnvVars: []string{"AZURE_EXCLUDE_CLI_CREDENTIAL"}, + }, + &cli.BoolFlag{ + Name: "exclude-environment-credential", + Usage: "Should Azure Environment authentication be excluded from authentication chain?", + Value: true, + EnvVars: []string{"AZURE_EXCLUDE_ENVIRONMENT_CREDENTIAL"}, + }, + &cli.BoolFlag{ + Name: "exclude-msi-credential", + Usage: "Should Azure MSI authentication be excluded from authentication chain?", + Value: true, + EnvVars: []string{"AZURE_EXCLUDE_MSI_CREDENTIAL"}, + }, } return flags } + +// Action executes the Azure action +func Action(ctx context.Context, cli *cli.Context) error { + servicePrincipalObjectID := cli.String("service-principal-object-id") + subscriptionID := cli.String("subscription-id") + tenantID := cli.String("tenant-id") + resourceGroupName := cli.String("resource-group-name") + resourceGroupLocation := cli.String("resource-group-location") + storageAccountName := cli.String("storage-account-name") + storageAccountContainer := cli.String("storage-account-container") + keyVaultName := cli.String("keyvault-name") + keyVaultKeyName := cli.String("keyvault-key-name") + resourceLocks := cli.Bool("resource-locks") + defaultAzureCredentialOptions := azidentity.DefaultAzureCredentialOptions{ + ExcludeAzureCLICredential: cli.Bool("exclude-cli-credential"), + ExcludeEnvironmentCredential: cli.Bool("exclude-environment-credential"), + ExcludeMSICredential: cli.Bool("exclude-msi-credential"), + } + + err := CreateResourceGroup(ctx, defaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, subscriptionID) + if err != nil { + return err + } + + err = CreateStorageAccount(ctx, defaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, storageAccountName, subscriptionID) + if err != nil { + return err + } + + if resourceLocks { + err = CreateResourceLock(ctx, defaultAzureCredentialOptions, resourceGroupName, "Microsoft.Storage", "", "storageAccounts", storageAccountName, "DoNotDelete", subscriptionID) + if err != nil { + return err + } + } + + err = CreateStorageAccountContainer(ctx, defaultAzureCredentialOptions, resourceGroupName, storageAccountName, storageAccountContainer, subscriptionID) + if err != nil { + return err + } + + err = CreateKeyVault(ctx, defaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID) + if err != nil { + return err + } + + if resourceLocks { + err = CreateResourceLock(ctx, defaultAzureCredentialOptions, resourceGroupName, "Microsoft.KeyVault", "", "vaults", keyVaultName, "DoNotDelete", subscriptionID) + if err != nil { + return err + } + } + + err = CreateKeyVaultAccessPolicy(ctx, defaultAzureCredentialOptions, resourceGroupName, resourceGroupLocation, keyVaultName, subscriptionID, tenantID, servicePrincipalObjectID) + if err != nil { + return err + } + + err = CreateKeyVaultKey(ctx, defaultAzureCredentialOptions, resourceGroupName, keyVaultName, keyVaultKeyName, subscriptionID) + if err != nil { + return err + } + + return nil +} diff --git a/docker/terraform.sh b/docker/terraform.sh index 4c7c416..ba4db67 100755 --- a/docker/terraform.sh +++ b/docker/terraform.sh @@ -35,6 +35,9 @@ prepare () { export AZURE_KEYVAULT_NAME="${BACKEND_KV}" export AZURE_KEYVAULT_KEY_NAME="${BACKEND_KV_KEY}" export AZURE_RESOURCE_LOCKS="${AZURE_RESOURCE_LOCKS:-true}" + export AZURE_EXCLUDE_CLI_CREDENTIAL="${AZURE_EXCLUDE_CLI_CREDENTIAL:-false}" + export AZURE_EXCLUDE_ENVIRONMENT_CREDENTIAL="${AZURE_EXCLUDE_ENVIRONMENT_CREDENTIAL:-true}" + export AZURE_EXCLUDE_MSI_CREDENTIAL="${AZURE_EXCLUDE_MSI_CREDENTIAL:-true}" tf-prepare azure }