diff --git a/.github/labeler-issue-triage.yml b/.github/labeler-issue-triage.yml index ba97f5f93250..fe158b051d1f 100644 --- a/.github/labeler-issue-triage.yml +++ b/.github/labeler-issue-triage.yml @@ -351,4 +351,4 @@ service/vmware: - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(vmware_cluster\W+|vmware_express_route_authorization\W+|vmware_netapp_volume_attachment\W+|vmware_private_cloud\W+|voice_services_communications_gateway\W+|voice_services_communications_gateway_test_line\W+)((.|\n)*)###' service/workloads: - - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(chaos_studio_|container_connected_registry\W+|container_registry_cache_rule\W+|container_registry_cache_rule\W+|container_registry_task\W+|container_registry_task_schedule_run_now\W+|container_registry_token_password\W+|kubernetes_cluster_extension\W+|kubernetes_cluster_trusted_access_role_binding\W+|kubernetes_fleet_manager\W+|kubernetes_fleet_member\W+|kubernetes_fleet_update_run\W+|kubernetes_fleet_update_strategy\W+|kubernetes_flux_configuration\W+|kubernetes_node_pool_snapshot\W+|workloads_sap_)((.|\n)*)###' + - '### (|New or )Affected Resource\(s\)\/Data Source\(s\)((.|\n)*)azurerm_(chaos_studio_|container_connected_registry\W+|container_registry_cache_rule\W+|container_registry_cache_rule\W+|container_registry_credential_set\W+|container_registry_task\W+|container_registry_task_schedule_run_now\W+|container_registry_token_password\W+|kubernetes_cluster_extension\W+|kubernetes_cluster_trusted_access_role_binding\W+|kubernetes_fleet_manager\W+|kubernetes_fleet_member\W+|kubernetes_fleet_update_run\W+|kubernetes_fleet_update_strategy\W+|kubernetes_flux_configuration\W+|kubernetes_node_pool_snapshot\W+|workloads_sap_)((.|\n)*)###' diff --git a/internal/services/containers/client/client.go b/internal/services/containers/client/client.go index 764c6a84ab9d..883300b4c161 100644 --- a/internal/services/containers/client/client.go +++ b/internal/services/containers/client/client.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/go-azure-sdk/resource-manager/containerinstance/2023-05-01/containerinstance" containerregistry_v2019_06_01_preview "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2019-06-01-preview" "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-07-01/cacherules" + "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-07-01/credentialsets" containerregistry "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-11-01-preview" "github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2019-08-01/containerservices" "github.com/hashicorp/go-azure-sdk/resource-manager/containerservice/2024-04-01/fleetupdatestrategies" @@ -28,6 +29,7 @@ type Client struct { AgentPoolsClient *agentpools.AgentPoolsClient ContainerInstanceClient *containerinstance.ContainerInstanceClient CacheRulesClient *cacherules.CacheRulesClient + CredentialSetsClient *credentialsets.CredentialSetsClient ContainerRegistryClient *containerregistry.Client // v2019_06_01_preview is needed for container registry agent pools and tasks ContainerRegistryClient_v2019_06_01_preview *containerregistry_v2019_06_01_preview.Client @@ -69,6 +71,12 @@ func NewContainersClient(o *common.ClientOptions) (*Client, error) { } o.Configure(cacheRulesClient.Client, o.Authorizers.ResourceManager) + credentialSetsClient, err := credentialsets.NewCredentialSetsClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("building Credential Sets client: %+v", err) + } + o.Configure(credentialSetsClient.Client, o.Authorizers.ResourceManager) + // AKS fleetUpdateRunsClient, err := updateruns.NewUpdateRunsClientWithBaseURI(o.Environment.ResourceManager) if err != nil { @@ -128,6 +136,7 @@ func NewContainersClient(o *common.ClientOptions) (*Client, error) { AgentPoolsClient: agentPoolsClient, ContainerInstanceClient: containerInstanceClient, CacheRulesClient: cacheRulesClient, + CredentialSetsClient: credentialSetsClient, ContainerRegistryClient: containerRegistryClient, ContainerRegistryClient_v2019_06_01_preview: containerRegistryClient_v2019_06_01_preview, FleetUpdateRunsClient: fleetUpdateRunsClient, diff --git a/internal/services/containers/container_registry_credential_set_resource.go b/internal/services/containers/container_registry_credential_set_resource.go new file mode 100644 index 000000000000..dc035c74cd36 --- /dev/null +++ b/internal/services/containers/container_registry_credential_set_resource.go @@ -0,0 +1,273 @@ +package containers + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" + "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-07-01/credentialsets" + "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-11-01-preview/registries" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +var _ sdk.Resource = ContainerRegistryCredentialSetResource{} + +type ContainerRegistryCredentialSetResource struct{} + +func (ContainerRegistryCredentialSetResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the credential set.", + }, + "container_registry_id": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: registries.ValidateRegistryID, + }, + "login_server": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + "authentication_credentials": { + Type: pluginsdk.TypeList, + Required: true, + MaxItems: 1, + Elem: &pluginsdk.Resource{ + Schema: map[string]*schema.Schema{ + "username_secret_id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: keyVaultValidate.VersionlessNestedItemId, + }, + "password_secret_id": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: keyVaultValidate.VersionlessNestedItemId, + }, + }, + }, + }, + } +} + +func (ContainerRegistryCredentialSetResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "identity": commonschema.SystemOrUserAssignedIdentityComputed(), + } +} + +type AuthenticationCredential struct { + UsernameSecretId string `tfschema:"username_secret_id"` + PasswordSecretId string `tfschema:"password_secret_id"` +} + +type ContainerRegistryCredentialSetModel struct { + Name string `tfschema:"name"` + ContainerRegistryId string `tfschema:"container_registry_id"` + LoginServer string `tfschema:"login_server"` + AuthenticationCredential []AuthenticationCredential `tfschema:"authentication_credentials"` + Identity []identity.ModelSystemAssignedUserAssigned `tfschema:"identity"` +} + +func (ContainerRegistryCredentialSetResource) ModelObject() interface{} { + return &ContainerRegistryCredentialSetModel{} +} + +func (ContainerRegistryCredentialSetResource) ResourceType() string { + return "azurerm_container_registry_credential_set" +} + +func (r ContainerRegistryCredentialSetResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Containers.CredentialSetsClient + subscriptionId := metadata.Client.Account.SubscriptionId + + var config ContainerRegistryCredentialSetModel + if err := metadata.Decode(&config); err != nil { + return err + } + + log.Printf("[INFO] preparing arguments for Container Registry Credential Set creation.") + + registryId, err := registries.ParseRegistryID(config.ContainerRegistryId) + if err != nil { + return err + } + + id := credentialsets.NewCredentialSetID(subscriptionId, + registryId.ResourceGroupName, + registryId.RegistryName, + config.Name, + ) + + existing, err := client.Get(ctx, id) + if err != nil && !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %+v", id, err) + } + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + param := credentialsets.CredentialSet{ + Name: pointer.To(id.CredentialSetName), + Properties: &credentialsets.CredentialSetProperties{ + LoginServer: pointer.To(config.LoginServer), + AuthCredentials: expandAuthCredentials(config.AuthenticationCredential), + }, + Identity: &identity.SystemAndUserAssignedMap{ + Type: identity.TypeSystemAssigned, + }, + } + + if err := client.CreateThenPoll(ctx, id, param); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r ContainerRegistryCredentialSetResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Containers.CredentialSetsClient + id, err := credentialsets.ParseCredentialSetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + param := credentialsets.CredentialSetUpdateParameters{} + + var model ContainerRegistryCredentialSetModel + if err := metadata.Decode(&model); err != nil { + return err + } + + properties := credentialsets.CredentialSetUpdateProperties{} + + if metadata.ResourceData.HasChange("authentication_credentials") { + properties.AuthCredentials = expandAuthCredentials(model.AuthenticationCredential) + } + + param.Properties = &properties + + if err := client.UpdateThenPoll(ctx, *id, param); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + return nil + }, + } +} + +func (ContainerRegistryCredentialSetResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Containers.CredentialSetsClient + id, err := credentialsets.ParseCredentialSetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(id) + } + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + registryId := registries.NewRegistryID(id.SubscriptionId, id.ResourceGroupName, id.RegistryName) + + var config ContainerRegistryCredentialSetModel + if err := metadata.Decode(&config); err != nil { + return err + } + + config.Name = id.CredentialSetName + config.ContainerRegistryId = registryId.ID() + + if model := resp.Model; model != nil { + flattenedIdentity, err := identity.FlattenSystemAndUserAssignedMapToModel(model.Identity) + if err != nil { + return fmt.Errorf("flattening `identity`: %+v", err) + } + config.Identity = pointer.From(flattenedIdentity) + if props := model.Properties; props != nil { + config.LoginServer = pointer.From(props.LoginServer) + config.AuthenticationCredential = flattenAuthCredentials(props.AuthCredentials) + } + } + return metadata.Encode(&config) + }, + } +} + +func (ContainerRegistryCredentialSetResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.Containers.CredentialSetsClient + id, err := credentialsets.ParseCredentialSetID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + return nil + }, + } +} + +func (ContainerRegistryCredentialSetResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return credentialsets.ValidateCredentialSetID +} + +func expandAuthCredentials(input []AuthenticationCredential) *[]credentialsets.AuthCredential { + output := make([]credentialsets.AuthCredential, 0) + if len(input) == 0 { + return &output + } + for _, v := range input { + output = append(output, credentialsets.AuthCredential{ + Name: pointer.To(credentialsets.CredentialNameCredentialOne), + UsernameSecretIdentifier: pointer.To(v.UsernameSecretId), + PasswordSecretIdentifier: pointer.To(v.PasswordSecretId), + }) + } + return &output +} + +func flattenAuthCredentials(input *[]credentialsets.AuthCredential) []AuthenticationCredential { + output := make([]AuthenticationCredential, 0) + if input == nil { + return output + } + for _, v := range *input { + output = append(output, AuthenticationCredential{ + UsernameSecretId: pointer.From(v.UsernameSecretIdentifier), + PasswordSecretId: pointer.From(v.PasswordSecretIdentifier), + }) + } + return output +} diff --git a/internal/services/containers/container_registry_credential_set_resource_test.go b/internal/services/containers/container_registry_credential_set_resource_test.go new file mode 100644 index 000000000000..e950ca7c0dc4 --- /dev/null +++ b/internal/services/containers/container_registry_credential_set_resource_test.go @@ -0,0 +1,164 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package containers_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/containerregistry/2023-07-01/credentialsets" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" +) + +type ContainerRegistryCredentialSetResource struct{} + +func TestAccContainerRegistryCredentialSet_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_registry_credential_set", "test") + r := ContainerRegistryCredentialSetResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccContainerRegistryCredentialSet_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_registry_credential_set", "test") + r := ContainerRegistryCredentialSetResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + { + Config: r.requiresImport(data), + ExpectError: acceptance.RequiresImportError("azurerm_container_registry_credential_set"), + }, + }) +} + +func TestAccContainerRegistryCredentialSet_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_container_registry_credential_set", "test") + r := ContainerRegistryCredentialSetResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (ContainerRegistryCredentialSetResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := credentialsets.ParseCredentialSetID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.Containers.CredentialSetsClient.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %+v", id, err) + } + + return pointer.To(resp.Model != nil), nil +} + +func (ContainerRegistryCredentialSetResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "accTestRG-acr-credetial-set-%d" + location = "%s" +} + +resource "azurerm_container_registry" "test" { + name = "testacccr%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Basic" +} + +resource "azurerm_container_registry_credential_set" "test" { + name = "testacc-acr-credential-set-%d" + container_registry_id = azurerm_container_registry.test.id + login_server = "docker.io" + authentication_credentials { + username_secret_id = "https://example-keyvault.vault.azure.net/secrets/acr-cs-user-name" + password_secret_id = "https://example-keyvault.vault.azure.net/secrets/acr-cs-user-password" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} + +func (r ContainerRegistryCredentialSetResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_container_registry_credential_set" "import" { + name = azurerm_container_registry_credential_set.test.name + container_registry_id = azurerm_container_registry_credential_set.test.container_registry_id + login_server = azurerm_container_registry_credential_set.test.login_server + authentication_credentials { + username_secret_id = azurerm_container_registry_credential_set.test.authentication_credentials[0].username_secret_id + password_secret_id = azurerm_container_registry_credential_set.test.authentication_credentials[0].password_secret_id + } +} +`, r.basic(data)) +} + +func (ContainerRegistryCredentialSetResource) update(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "accTestRG-acr-credetial-set-%d" + location = "%s" +} + +resource "azurerm_container_registry" "test" { + name = "testacccr%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Basic" +} + +resource "azurerm_container_registry_credential_set" "test" { + name = "testacc-acr-credential-set-%d" + container_registry_id = azurerm_container_registry.test.id + login_server = "docker.io" + authentication_credentials { + username_secret_id = "https://example-keyvault.vault.azure.net/secrets/acr-cs-user-name-changed" + password_secret_id = "https://example-keyvault.vault.azure.net/secrets/acr-cs-user-password" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger) +} diff --git a/internal/services/containers/registration.go b/internal/services/containers/registration.go index 32ff3d85aa5a..4b0f875a5cee 100644 --- a/internal/services/containers/registration.go +++ b/internal/services/containers/registration.go @@ -71,6 +71,7 @@ func (r Registration) Resources() []sdk.Resource { resources := []sdk.Resource{ ContainerRegistryCacheRule{}, ContainerRegistryTaskResource{}, + ContainerRegistryCredentialSetResource{}, ContainerRegistryTaskScheduleResource{}, ContainerRegistryTokenPasswordResource{}, ContainerConnectedRegistryResource{}, diff --git a/website/docs/r/container_registry_credential_set.html.markdown b/website/docs/r/container_registry_credential_set.html.markdown new file mode 100644 index 000000000000..8654676962b4 --- /dev/null +++ b/website/docs/r/container_registry_credential_set.html.markdown @@ -0,0 +1,159 @@ +--- +subcategory: "Container" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_container_registry_credential_set" +description: |- + Manages a Container Registry Credential Set. +--- + +# azurerm_container_registry_credential_set + +Manages a Container Registry Credential Set. + +## Example Usage (minimal) + +~> NOTE: Be aware that you will need to permit the Identity that is created for the Container Registry to have `get` on secrets to the Key Vault, e.g. using the `azurerm_key_vault_access_policy` resource. + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_container_registry" "example" { + name = "exampleContainerRegistry" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku = "Basic" +} + +resource "azurerm_container_registry_credential_set" "example" { + name = "exampleCredentialSet" + container_registry_id = "azurerm_container_registry.example.id" + login_server = "docker.io" + authentication_credentials { + username_secret_id = "https://example-keyvault.vault.azure.net/secrets/example-user-name" + password_secret_id = "https://example-keyvault.vault.azure.net/secrets/example-user-password" + } +} +``` + +## Example Usage (full) + +This example provisions a key vault with two secrets, a container registry, a container registry credential set, and an access policy to allow the container registry to read the secrets from the key vault. + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_key_vault" "example" { + name = "examplekeyvault" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" +} + +resource "azurerm_key_vault_secret" "example_user" { + key_vault_id = azurerm_key_vault.example.id + name = "example-user-name" + value = "name" +} + +resource "azurerm_key_vault_secret" "example_password" { + key_vault_id = azurerm_key_vault.example.id + name = "example-user-password" + value = "password" +} + +resource "azurerm_container_registry" "example" { + name = "exampleContainerRegistry" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku = "Basic" +} + +resource "azurerm_container_registry_credential_set" "example" { + name = "exampleCredentialSet" + container_registry_id = "azurerm_container_registry.example.id" + login_server = "docker.io" + authentication_credentials { + username_secret_id = azurerm_key_vault_secret.example_user.resource_versionless_id + password_secret_id = azurerm_key_vault_secret.example_password.resource_versionless_id + } +} + +resource "azurerm_key_vault_access_policy" "read_secrets" { + key_vault_id = azurerm_key_vault.example.id + tenant_id = azurerm_container_registry_credential_set.example.identity[0].tenant_id + object_id = azurerm_container_registry_credential_set.example.identity[0].principal_id + secret_permissions = ["Get"] +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) The name which should be used for this Container Registry Credential Set. Changing this forces a new Container Registry Credential Set to be created. + +* `container_registry_id` - (Required) The ID of the Container Registry. Changing this forces a new Container Registry Credential Set to be created. + +* `login_server` - (Required) The login server for the Credential Set. Changing this forces a new Container Registry Credential Set to be created. + +* `authentication_credentials` - (Required) A `authentication_credentials` block as defined below. + +--- + +A `authentication_credentials` block supports the following: + +* `username_secret_id` - (Required) The URI of the secret containing the username in a Key Vault. + +* `password_secret_id` - (Required) The URI of the secret containing the password in a Key Vault. + +~> NOTE: Be aware that you will need to permit the Identity that is created for the Container Registry to have `get` on secrets to the Key Vault, e.g. using the `azurerm_key_vault_access_policy` resource. + + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Container Registry Credential Set. + +* `identity` - A `identity` block as defined below. + +--- + +A `identity` block exports the following: + +* `principal_id` - The principal ID of the Identity. + +* `tenant_id` - The tenant ID of the Identity. + +* `type` - The type of the Identity. + +* `identity_ids` - A list of User Managed Identity IDs. + +~> **Note:** Currently only SystemAssigned Identities are supported. + + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Container Registry Credential Set. +* `read` - (Defaults to 5 minutes) Used when retrieving the Container Registry Credential Set. +* `update` - (Defaults to 30 minutes) Used when updating the Container Registry Credential Set. +* `delete` - (Defaults to 30 minutes) Used when deleting the Container Registry Credential Set. + +## Import + +Container Registry Credential Sets can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_container_registry_credential_set.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.ContainerRegistry/registries/registry1/credentialSets/credentialSet1 +```