Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,64 @@ func TestAccKubernetesCluster_advancedNetworkingNetworkDataplane(t *testing.T) {
})
}

func TestAccKubernetesCluster_advancedNetworkingPolicies(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.advancedNetworkingWithPolicies(data, "FQDN"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
{
Config: r.advancedNetworkingWithPolicies(data, "L7"),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep(),
})
}

func TestAccKubernetesCluster_advancedNetworkingPoliciesFQDNRequiresSecurity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.advancedNetworkingWithPoliciesSecurityDisabled(data, "FQDN"),
ExpectError: regexp.MustCompile("`network_profile.0.advanced_networking.0.advanced_network_policies` can only be set when `network_profile.0.advanced_networking.0.security_enabled` is set to `true`"),
},
})
}

func TestAccKubernetesCluster_advancedNetworkingPoliciesL7RequiresSecurity(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.advancedNetworkingWithPoliciesSecurityDisabled(data, "L7"),
ExpectError: regexp.MustCompile("`network_profile.0.advanced_networking.0.advanced_network_policies` can only be set when `network_profile.0.advanced_networking.0.security_enabled` is set to `true`"),
},
})
}

func TestAccKubernetesCluster_advancedNetworkingPoliciesConflictsWithIstio(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.advancedNetworkingWithPoliciesAndIstio(data, "L7"),
ExpectError: regexp.MustCompile("`network_profile.0.advanced_networking.0.advanced_network_policies` cannot be set when `service_mesh_profile.0.mode` is set to `Istio`"),
},
})
}

func TestAccKubernetesCluster_serviceMeshProfile(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_kubernetes_cluster", "test")
r := KubernetesClusterResource{}
Expand Down Expand Up @@ -1549,6 +1607,211 @@ resource "azurerm_kubernetes_cluster" "test" {
`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, data.RandomInteger, networkPlugin)
}

func (KubernetesClusterResource) advancedNetworkingWithPolicies(data acceptance.TestData, advancedNetworkPolicies string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%[1]d"
location = "%[2]s"
}

resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%[1]d"
address_space = ["10.0.0.0/8"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_subnet" "test" {
name = "acctestsubnet%[1]d"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.1.0.0/16"]
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%[1]d"

linux_profile {
admin_username = "acctestuser%[1]d"

ssh_key {
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld"
}
}

default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_DS2_v2"
vnet_subnet_id = azurerm_subnet.test.id
upgrade_settings {
max_surge = "10%%"
}
}

identity {
type = "SystemAssigned"
}

network_profile {
network_plugin = "azure"
network_data_plane = "cilium"

advanced_networking {
observability_enabled = true
security_enabled = true
advanced_network_policies = "%[3]s"
}
}
}
`, data.RandomInteger, data.Locations.Primary, advancedNetworkPolicies)
}

func (KubernetesClusterResource) advancedNetworkingWithPoliciesSecurityDisabled(data acceptance.TestData, advancedNetworkPolicies string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%[1]d"
location = "%[2]s"
}

resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%[1]d"
address_space = ["10.0.0.0/8"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_subnet" "test" {
name = "acctestsubnet%[1]d"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.1.0.0/16"]
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%[1]d"

linux_profile {
admin_username = "acctestuser%[1]d"

ssh_key {
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld"
}
}

default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_DS2_v2"
vnet_subnet_id = azurerm_subnet.test.id
upgrade_settings {
max_surge = "10%%"
}
}

identity {
type = "SystemAssigned"
}

network_profile {
network_plugin = "azure"
network_data_plane = "cilium"

advanced_networking {
observability_enabled = true
security_enabled = false
advanced_network_policies = "%[3]s"
}
}
}
`, data.RandomInteger, data.Locations.Primary, advancedNetworkPolicies)
}

func (KubernetesClusterResource) advancedNetworkingWithPoliciesAndIstio(data acceptance.TestData, advancedNetworkPolicies string) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}

resource "azurerm_resource_group" "test" {
name = "acctestRG-aks-%[1]d"
location = "%[2]s"
}

resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%[1]d"
address_space = ["10.0.0.0/8"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}

resource "azurerm_subnet" "test" {
name = "acctestsubnet%[1]d"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.1.0.0/16"]
}

resource "azurerm_kubernetes_cluster" "test" {
name = "acctestaks%[1]d"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
dns_prefix = "acctestaks%[1]d"

linux_profile {
admin_username = "acctestuser%[1]d"

ssh_key {
key_data = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqaZoyiz1qbdOQ8xEf6uEu1cCwYowo5FHtsBhqLoDnnp7KUTEBN+L2NxRIfQ781rxV6Iq5jSav6b2Q8z5KiseOlvKA/RF2wqU0UPYqQviQhLmW6THTpmrv/YkUCuzxDpsH7DUDhZcwySLKVVe0Qm3+5N2Ta6UYH3lsDf9R9wTP2K/+vAnflKebuypNlmocIvakFWoZda18FOmsOoIVXQ8HWFNCuw9ZCunMSN62QGamCe3dL5cXlkgHYv7ekJE15IA9aOJcM7e90oeTqo+7HTcWfdu0qQqPWY5ujyMw/llas8tsXY85LFqRnr3gJ02bAscjc477+X+j/gkpFoN1QEmt terraform@demo.tld"
}
}

default_node_pool {
name = "default"
node_count = 2
vm_size = "Standard_DS2_v2"
vnet_subnet_id = azurerm_subnet.test.id
upgrade_settings {
max_surge = "10%%"
}
}

identity {
type = "SystemAssigned"
}

network_profile {
network_plugin = "azure"
network_data_plane = "cilium"

advanced_networking {
observability_enabled = true
security_enabled = true
advanced_network_policies = "%[3]s"
}
}

service_mesh_profile {
mode = "Istio"
}
}
`, data.RandomInteger, data.Locations.Primary, advancedNetworkPolicies)
}

func (KubernetesClusterResource) serviceMeshProfile(data acceptance.TestData, internalIngressEnabled bool, externalIngressEnabled bool) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
40 changes: 35 additions & 5 deletions internal/services/containers/kubernetes_cluster_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
return fmt.Errorf("when `network_profile.0.advanced_networking` has `security_enabled` set to `true`, `network_profile.0.network_plugin` must be set to `%s`", managedclusters.NetworkPluginAzure)
}
}
advancedNetworkPolicies := d.Get("network_profile.0.advanced_networking.0.advanced_network_policies").(string)
if !securityEnabled && advancedNetworkPolicies != "" {
return fmt.Errorf("`network_profile.0.advanced_networking.0.advanced_network_policies` can only be set when `network_profile.0.advanced_networking.0.security_enabled` is set to `true`")
}
if advancedNetworkPolicies != "" {
if mode := d.Get("service_mesh_profile.0.mode").(string); mode == string(managedclusters.ServiceMeshModeIstio) {
return fmt.Errorf("`network_profile.0.advanced_networking.0.advanced_network_policies` cannot be set when `service_mesh_profile.0.mode` is set to `%s`", managedclusters.ServiceMeshModeIstio)
}
}
}
return nil
},
Expand Down Expand Up @@ -1366,6 +1375,15 @@ func resourceKubernetesCluster() *pluginsdk.Resource {
Default: false,
AtLeastOneOf: []string{"network_profile.0.advanced_networking.0.observability_enabled", "network_profile.0.advanced_networking.0.security_enabled"},
},
"advanced_network_policies": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

as this in nest in the advanced_networking block and only one item is allowed, we may rename it to

Suggested change
"advanced_network_policies": {
"policy": {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

this is the official name for this feature in the API, so I don't think we can change it

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The field name in Terraform resource doesn't have to be the same as the API/official, we prefer to deliver a clear and easy to use schema

Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
string(managedclusters.AdvancedNetworkPoliciesFQDN),
string(managedclusters.AdvancedNetworkPoliciesLSeven),
// Note: Whilst the `None` value exists it's handled in the Create/Update and Read functions.
}, false),
},
},
},
},
Expand Down Expand Up @@ -3739,14 +3757,21 @@ func expandKubernetesClusterAdvancedNetworking(input []interface{}, d *pluginsdk
observabilityEnabled := config["observability_enabled"].(bool)
securityEnabled := config["security_enabled"].(bool)

advancedNetworkPolicies := managedclusters.AdvancedNetworkPoliciesNone
if v := config["advanced_network_policies"].(string); v != "" {
advancedNetworkPolicies = managedclusters.AdvancedNetworkPolicies(v)
}
security := &managedclusters.AdvancedNetworkingSecurity{
Enabled: pointer.To(securityEnabled),
AdvancedNetworkPolicies: pointer.To(advancedNetworkPolicies),
}

return &managedclusters.AdvancedNetworking{
Enabled: pointer.To(true),
Observability: &managedclusters.AdvancedNetworkingObservability{
Enabled: pointer.To(observabilityEnabled),
},
Security: &managedclusters.AdvancedNetworkingSecurity{
Enabled: pointer.To(securityEnabled),
},
Security: security,
}
}

Expand All @@ -3761,14 +3786,19 @@ func flattenKubernetesClusterAdvancedNetworking(advancedNetworking *managedclust
}

securityEnabled := false
advancedNetworkPolicies := ""
if advancedNetworking.Security != nil {
securityEnabled = pointer.From(advancedNetworking.Security.Enabled)
if v := advancedNetworking.Security.AdvancedNetworkPolicies; v != nil && *v != managedclusters.AdvancedNetworkPoliciesNone {
advancedNetworkPolicies = string(*v)
}
}

return []interface{}{
map[string]interface{}{
"observability_enabled": observabilityEnabled,
"security_enabled": securityEnabled,
"observability_enabled": observabilityEnabled,
"security_enabled": securityEnabled,
"advanced_network_policies": advancedNetworkPolicies,
},
}
}
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/kubernetes_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,8 @@ An `advanced_networking` block supports the following:

* `security_enabled` - (Optional) Is security enabled? Defaults to `false`. This can only be enabled (set to `true`) when `network_plugin` is set to `azure` and `network_data_plane` is set to `cilium`.

* `advanced_network_policies` - (Optional) Specifies the advanced network policy for the cluster. Possible values are `FQDN` and `L7`. This can only be set when `security_enabled` is set to `true` and `network_data_plane` is set to `cilium`. This cannot be set when `service_mesh_profile` `mode` is set to `Istio`. Omitting this field disables advanced network policy enforcement (equivalent to `None`).

---

A `load_balancer_profile` block supports the following:
Expand Down
Loading