Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 69 additions & 31 deletions internal/services/containers/container_registry_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-helpers/lang/response"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonids"
"github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema"
"github.com/hashicorp/go-azure-helpers/resourcemanager/identity"
"github.com/hashicorp/go-azure-helpers/resourcemanager/location"
Expand Down Expand Up @@ -225,6 +224,12 @@ func resourceContainerRegistry() *pluginsdk.Resource {
Default: true,
},

"azuread_authentication_as_arm_policy_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: true,
},

"zone_redundancy_enabled": {
Type: pluginsdk.TypeBool,
ForceNew: true,
Expand Down Expand Up @@ -260,6 +265,19 @@ func resourceContainerRegistry() *pluginsdk.Resource {
Default: string(registries.NetworkRuleBypassOptionsAzureServices),
},

"network_rule_bypass_for_tasks_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Default: false,
},

"role_assignment_mode": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(registries.PossibleValuesForRoleAssignmentMode(), false),
Default: registries.RoleAssignmentModeLegacyRegistryPermissions,
},

"tags": commonschema.Tags(),
},

Expand Down Expand Up @@ -351,7 +369,6 @@ func resourceContainerRegistry() *pluginsdk.Resource {

func resourceContainerRegistryCreate(d *pluginsdk.ResourceData, meta interface{}) error {
client := meta.(*clients.Client).Containers.ContainerRegistryClient.Registries
registriesClient := meta.(*clients.Client).Containers.ContainerRegistryClient.Registries
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()
Expand All @@ -372,29 +389,11 @@ func resourceContainerRegistryCreate(d *pluginsdk.ResourceData, meta interface{}
}
}

sId := commonids.NewSubscriptionID(subscriptionId)
availabilityRequest := registries.RegistryNameCheckRequest{
Name: id.RegistryName,
Type: "Microsoft.ContainerRegistry/registries",
}
resp, err := registriesClient.CheckNameAvailability(ctx, sId, availabilityRequest)
if err != nil {
return fmt.Errorf("checking if the name %q was available: %+v", id.RegistryName, err)
}

if resp.Model == nil && resp.Model.NameAvailable == nil {
return fmt.Errorf("checking name availability for %s: model was nil", id)
}

if available := *resp.Model.NameAvailable; !available {
return fmt.Errorf("the name %q used for the Container Registry needs to be globally unique and isn't available: %s", id.RegistryName, *resp.Model.Message)
}

sku := d.Get("sku").(string)

networkRuleSet := expandNetworkRuleSet(d.Get("network_rule_set").([]interface{}))
if networkRuleSet != nil && !strings.EqualFold(sku, string(registries.SkuNamePremium)) {
return fmt.Errorf("`network_rule_set_set` can only be specified for a Premium Sku. If you are reverting from a Premium to Basic SKU please set network_rule_set = []")
return fmt.Errorf("`network_rule_set` can only be specified for a Premium Sku. If you are reverting from a Premium to Basic SKU please set network_rule_set = []")
}

identity, err := identity.ExpandSystemAndUserAssignedMap(d.Get("identity").([]interface{}))
Expand Down Expand Up @@ -439,16 +438,19 @@ func resourceContainerRegistryCreate(d *pluginsdk.ResourceData, meta interface{}
Encryption: expandEncryption(d.Get("encryption").([]interface{})),
NetworkRuleSet: networkRuleSet,
Policies: &registries.Policies{
QuarantinePolicy: expandQuarantinePolicy(d.Get("quarantine_policy_enabled").(bool)),
RetentionPolicy: retentionPolicy,
TrustPolicy: trustPolicy,
ExportPolicy: expandExportPolicy(d.Get("export_policy_enabled").(bool)),
QuarantinePolicy: expandQuarantinePolicy(d.Get("quarantine_policy_enabled").(bool)),
RetentionPolicy: retentionPolicy,
TrustPolicy: trustPolicy,
ExportPolicy: expandExportPolicy(d.Get("export_policy_enabled").(bool)),
AzureADAuthenticationAsArmPolicy: expandAadAuthAsArmPolicy(d.Get("azuread_authentication_as_arm_policy_enabled").(bool)),
},
PublicNetworkAccess: &publicNetworkAccess,
ZoneRedundancy: &zoneRedundancy,
AnonymousPullEnabled: pointer.To(d.Get("anonymous_pull_enabled").(bool)),
DataEndpointEnabled: pointer.To(d.Get("data_endpoint_enabled").(bool)),
NetworkRuleBypassOptions: pointer.To(registries.NetworkRuleBypassOptions(d.Get("network_rule_bypass_option").(string))),
PublicNetworkAccess: &publicNetworkAccess,
ZoneRedundancy: &zoneRedundancy,
AnonymousPullEnabled: pointer.To(d.Get("anonymous_pull_enabled").(bool)),
DataEndpointEnabled: pointer.To(d.Get("data_endpoint_enabled").(bool)),
NetworkRuleBypassOptions: pointer.To(registries.NetworkRuleBypassOptions(d.Get("network_rule_bypass_option").(string))),
RoleAssignmentMode: pointer.ToEnum[registries.RoleAssignmentMode](d.Get("role_assignment_mode").(string)),
NetworkRuleBypassAllowedForTasks: pointer.To(d.Get("network_rule_bypass_for_tasks_enabled").(bool)),
},

Tags: tags.Expand(d.Get("tags").(map[string]interface{})),
Expand Down Expand Up @@ -509,7 +511,7 @@ func resourceContainerRegistryUpdate(d *pluginsdk.ResourceData, meta interface{}
if d.HasChange("network_rule_set") {
networkRuleSet := expandNetworkRuleSet(d.Get("network_rule_set").([]interface{}))
if networkRuleSet != nil && isBasicSku {
return fmt.Errorf("`network_rule_set_set` can only be specified for a Premium Sku. If you are reverting from a Premium to Basic SKU plese set network_rule_set = []")
return fmt.Errorf("`network_rule_set` can only be specified for a Premium Sku. If you are reverting from a Premium to Basic SKU plese set network_rule_set = []")
}

payload.Properties.NetworkRuleSet = networkRuleSet
Expand Down Expand Up @@ -540,6 +542,7 @@ func resourceContainerRegistryUpdate(d *pluginsdk.ResourceData, meta interface{}
policyKeys := []string{
"quarantine_policy_enabled",
"export_policy_enabled",
"azuread_authentication_as_arm_policy_enabled",
}

policyKeys = append(policyKeys, []string{"retention_policy_in_days", "trust_policy_enabled"}...)
Expand Down Expand Up @@ -597,6 +600,10 @@ func resourceContainerRegistryUpdate(d *pluginsdk.ResourceData, meta interface{}
}
}

if d.HasChange("azuread_authentication_as_arm_policy_enabled") {
payload.Properties.Policies.AzureADAuthenticationAsArmPolicy = expandAadAuthAsArmPolicy(d.Get("azuread_authentication_as_arm_policy_enabled").(bool))
}

if d.HasChange("admin_enabled") {
payload.Properties.AdminUserEnabled = pointer.To(d.Get("admin_enabled").(bool))
}
Expand All @@ -617,6 +624,14 @@ func resourceContainerRegistryUpdate(d *pluginsdk.ResourceData, meta interface{}
payload.Properties.NetworkRuleBypassOptions = pointer.To(registries.NetworkRuleBypassOptions(d.Get("network_rule_bypass_option").(string)))
}

if d.HasChange("role_assignment_mode") {
payload.Properties.RoleAssignmentMode = pointer.ToEnum[registries.RoleAssignmentMode](d.Get("role_assignment_mode").(string))
}

if d.HasChange("network_rule_bypass_for_tasks_enabled") {
payload.Properties.NetworkRuleBypassAllowedForTasks = pointer.To(d.Get("network_rule_bypass_for_tasks_enabled").(bool))
}

if d.HasChange("tags") {
payload.Tags = tags.Expand(d.Get("tags").(map[string]interface{}))
}
Expand Down Expand Up @@ -857,6 +872,8 @@ func resourceContainerRegistryRead(d *pluginsdk.ResourceData, meta interface{})
d.Set("data_endpoint_enabled", props.DataEndpointEnabled)
d.Set("data_endpoint_host_names", props.DataEndpointHostNames)
d.Set("network_rule_bypass_option", string(pointer.From(props.NetworkRuleBypassOptions)))
d.Set("role_assignment_mode", string(pointer.From(props.RoleAssignmentMode)))
d.Set("network_rule_bypass_for_tasks_enabled", pointer.From(props.NetworkRuleBypassAllowedForTasks))

if policies := props.Policies; policies != nil {
var retentionInDays int64
Expand All @@ -871,6 +888,7 @@ func resourceContainerRegistryRead(d *pluginsdk.ResourceData, meta interface{})
}
d.Set("quarantine_policy_enabled", flattenQuarantinePolicy(props.Policies))
d.Set("export_policy_enabled", flattenExportPolicy(props.Policies))
d.Set("azuread_authentication_as_arm_policy_enabled", flattenAadAuthAsArmPolicy(props.Policies))
}

if *props.AdminUserEnabled {
Expand Down Expand Up @@ -996,6 +1014,18 @@ func expandExportPolicy(enabled bool) *registries.ExportPolicy {
return &exportPolicy
}

func expandAadAuthAsArmPolicy(enabled bool) *registries.AzureADAuthenticationAsArmPolicy {
policy := registries.AzureADAuthenticationAsArmPolicy{
Status: pointer.To(registries.AzureADAuthenticationAsArmPolicyStatusDisabled),
}

if enabled {
policy.Status = pointer.To(registries.AzureADAuthenticationAsArmPolicyStatusEnabled)
}

return &policy
}

func expandReplications(p []interface{}) []replications.Replication {
reps := make([]replications.Replication, 0)
if p == nil {
Expand Down Expand Up @@ -1092,3 +1122,11 @@ func flattenExportPolicy(p *registries.Policies) bool {

return *p.ExportPolicy.Status == registries.ExportPolicyStatusEnabled
}

func flattenAadAuthAsArmPolicy(p *registries.Policies) bool {
if p.AzureADAuthenticationAsArmPolicy == nil {
return false
}

return *p.AzureADAuthenticationAsArmPolicy.Status == registries.AzureADAuthenticationAsArmPolicyStatusEnabled
}
40 changes: 22 additions & 18 deletions internal/services/containers/container_registry_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,15 +491,17 @@ resource "azurerm_container_registry" "test" {
type = "SystemAssigned"
}

public_network_access_enabled = false
quarantine_policy_enabled = true
retention_policy_in_days = 10
trust_policy_enabled = true
export_policy_enabled = false
anonymous_pull_enabled = true
data_endpoint_enabled = true

network_rule_bypass_option = "None"
public_network_access_enabled = false
quarantine_policy_enabled = true
retention_policy_in_days = 10
trust_policy_enabled = true
export_policy_enabled = false
azuread_authentication_as_arm_policy_enabled = false
anonymous_pull_enabled = true
data_endpoint_enabled = true
network_rule_bypass_option = "None"
network_rule_bypass_for_tasks_enabled = true
role_assignment_mode = "AbacRepositoryPermissions"

tags = {
environment = "production"
Expand Down Expand Up @@ -540,15 +542,17 @@ resource "azurerm_container_registry" "test" {
]
}

public_network_access_enabled = true
quarantine_policy_enabled = false
retention_policy_in_days = 15
trust_policy_enabled = false
export_policy_enabled = true
anonymous_pull_enabled = false
data_endpoint_enabled = false

network_rule_bypass_option = "AzureServices"
public_network_access_enabled = true
quarantine_policy_enabled = false
retention_policy_in_days = 15
trust_policy_enabled = false
export_policy_enabled = true
azuread_authentication_as_arm_policy_enabled = true
anonymous_pull_enabled = false
data_endpoint_enabled = false
network_rule_bypass_option = "AzureServices"
network_rule_bypass_for_tasks_enabled = false
role_assignment_mode = "LegacyRegistryPermissions"

tags = {
environment = "production"
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/container_registry.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ The following arguments are supported:

* `export_policy_enabled` - (Optional) Boolean value that indicates whether export policy is enabled. Defaults to `true`. In order to set it to `false`, make sure the `public_network_access_enabled` is also set to `false`.

* `azuread_authentication_as_arm_policy_enabled` - (Optional) Whether to use Azure Resource Manager audience token for this Container Registry? Defaults to `true`.

~> **Note:** `quarantine_policy_enabled`, `retention_policy_in_days`, `trust_policy_enabled`, `export_policy_enabled` and `zone_redundancy_enabled` are only supported on resources with the `Premium` SKU.

* `identity` - (Optional) An `identity` block as defined below.
Expand All @@ -180,6 +182,10 @@ The following arguments are supported:

* `network_rule_bypass_option` - (Optional) Whether to allow trusted Azure services to access a network-restricted Container Registry? Possible values are `None` and `AzureServices`. Defaults to `AzureServices`.

* `network_rule_bypass_for_tasks_enabled` - (Optional) Whether to allow Container Registry Tasks to access a network-restricted Container Registry? Defaults to `false`.

* `role_assignment_mode` - (Optional) The role assignment mode of this Container Registry. Possible values are `AbacRepositoryPermissions` and `LegacyRegistryPermissions`. Defaults to `LegacyRegistryPermissions`.

---

The `georeplications` block supports the following:
Expand Down
Loading