From 218495a1a17635f13720f6cf4614a088c27119d5 Mon Sep 17 00:00:00 2001 From: Krzysztof Klimonda Date: Thu, 26 Jun 2025 14:30:07 +0200 Subject: [PATCH 1/2] fix(specs): update panos xpath for certificate profiles --- .../test/resource_certificate_profile_test.go | 365 ++++++++++++++++++ specs/objects/profiles/certificate.yaml | 63 ++- 2 files changed, 395 insertions(+), 33 deletions(-) create mode 100644 assets/terraform/test/resource_certificate_profile_test.go diff --git a/assets/terraform/test/resource_certificate_profile_test.go b/assets/terraform/test/resource_certificate_profile_test.go new file mode 100644 index 00000000..618a4817 --- /dev/null +++ b/assets/terraform/test/resource_certificate_profile_test.go @@ -0,0 +1,365 @@ +package provider_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestAccCertificateProfile_Basic(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: certificateProfile_Basic, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("block_expired_certificate"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("block_timeout_certificate"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("block_unauthenticated_certificate"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("block_unknown_certificate"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("certificate_status_timeout"), + knownvalue.Int64Exact(10), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("crl_receive_timeout"), + knownvalue.Int64Exact(10), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("domain"), + knownvalue.StringExact("example.com"), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("ocsp_exclude_nonce"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("ocsp_receive_timeout"), + knownvalue.Int64Exact(10), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("use_crl"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("use_ocsp"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("username_field"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "subject": knownvalue.StringExact("common-name"), + "subject_alt": knownvalue.Null(), + }), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("location").AtMapKey("template").AtMapKey("name"), + knownvalue.StringExact(fmt.Sprintf("%s-tmpl", prefix)), + ), + }, + }, + }, + }) +} + +const certificateProfile_Basic = ` +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = "${var.prefix}-tmpl" +} + +resource "panos_certificate_profile" "example" { + location = { template = { name = panos_template.example.name } } + name = var.prefix + + block_expired_certificate = true + block_timeout_certificate = true + block_unauthenticated_certificate = true + block_unknown_certificate = true + certificate_status_timeout = 10 + crl_receive_timeout = 10 + domain = "example.com" + ocsp_exclude_nonce = true + ocsp_receive_timeout = 10 + use_crl = true + use_ocsp = true + username_field = { + subject = "common-name" + } +} +` + +func TestAccCertificateProfile_UsernameFieldSubjectAltEmail(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: certificateProfile_UsernameFieldSubjectAltEmail, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("username_field"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "subject": knownvalue.Null(), + "subject_alt": knownvalue.StringExact("email"), + }), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("location").AtMapKey("template").AtMapKey("name"), + knownvalue.StringExact(fmt.Sprintf("%s-tmpl", prefix)), + ), + }, + }, + }, + }) +} + +const certificateProfile_UsernameFieldSubjectAltEmail = ` +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = "${var.prefix}-tmpl" +} + +resource "panos_certificate_profile" "example" { + location = { template = { name = panos_template.example.name } } + name = var.prefix + + username_field = { + subject_alt = "email" + } +} +` + +func TestAccCertificateProfile_UsernameFieldSubjectAltPrincipalName(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: certificateProfile_UsernameFieldSubjectAltPrincipalName, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("username_field"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "subject": knownvalue.Null(), + "subject_alt": knownvalue.StringExact("principal-name"), + }), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("location").AtMapKey("template").AtMapKey("name"), + knownvalue.StringExact(fmt.Sprintf("%s-tmpl", prefix)), + ), + }, + }, + }, + }) +} + +const certificateProfile_UsernameFieldSubjectAltPrincipalName = ` +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = "${var.prefix}-tmpl" +} + +resource "panos_certificate_profile" "example" { + location = { template = { name = panos_template.example.name } } + name = var.prefix + + username_field = { + subject_alt = "principal-name" + } +} +` + +func TestAccCertificateProfile_WithCertificate(t *testing.T) { + t.Parallel() + t.Skip("This test is skipped because it requires CA and OCSP certificates to be present on the device.") + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: certificateProfile_WithCertificate, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("certificate"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("ca_cert_name"), + "default_ocsp_url": knownvalue.StringExact("http://ocsp.example.com"), + "ocsp_verify_certificate": knownvalue.StringExact("ocsp_signer_cert"), + "template_name": knownvalue.StringExact("cert_template"), + }), + }), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("location").AtMapKey("template").AtMapKey("name"), + knownvalue.StringExact(fmt.Sprintf("%s-tmpl", prefix)), + ), + }, + }, + }, + }) +} + +const certificateProfile_WithCertificate = ` +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = "${var.prefix}-tmpl" +} + +resource "panos_certificate_profile" "example" { + location = { template = { name = panos_template.example.name } } + name = var.prefix + + certificate = [{ + name = "ca_cert_name" + default_ocsp_url = "http://ocsp.example.com" + ocsp_verify_certificate = "ocsp_signer_cert" + template_name = "cert_template" + }] +} +` + +func TestAccCertificateProfile_TemplateLocation(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: certificateProfile_TemplateLocation, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_certificate_profile.example", + tfjsonpath.New("location").AtMapKey("template").AtMapKey("name"), + knownvalue.StringExact(fmt.Sprintf("%s-tmpl", prefix)), + ), + }, + }, + }, + }) +} + +const certificateProfile_TemplateLocation = ` +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = "${var.prefix}-tmpl" +} + +resource "panos_certificate_profile" "example" { + location = { template = { name = panos_template.example.name } } + name = var.prefix +} +` diff --git a/specs/objects/profiles/certificate.yaml b/specs/objects/profiles/certificate.yaml index 98c7a3de..de5dcd7b 100644 --- a/specs/objects/profiles/certificate.yaml +++ b/specs/objects/profiles/certificate.yaml @@ -17,7 +17,7 @@ go_sdk_config: - certificate panos_xpath: path: - - certificate + - certificate-profile vars: [] locations: - name: panorama @@ -27,8 +27,19 @@ locations: - panorama vars: [] description: Located in a panorama. + validators: [] + required: false + read_only: false +- name: shared + xpath: + path: + - config + - shared + vars: [] + description: Panorama shared object devices: - panorama + - ngfw validators: [] required: false read_only: false @@ -44,24 +55,23 @@ locations: - shared vars: - name: panorama_device - description: The panorama device. + description: Specific Panorama device required: false default: localhost.localdomain validators: [] type: entry - name: template - description: The template. + description: Specific Panorama template required: true validators: [] type: entry - description: Located in a specific template. + description: A shared resource located within a specific template devices: - panorama - - ngfw validators: [] required: false read_only: false -- name: template_vsys +- name: template-vsys xpath: path: - config @@ -76,18 +86,18 @@ locations: - $vsys vars: - name: panorama_device - description: The panorama device. + description: Specific Panorama device required: false default: localhost.localdomain validators: [] type: entry - name: template - description: The template. + description: Specific Panorama template required: true validators: [] type: entry - name: ngfw_device - description: The NGFW device. + description: The NGFW device required: false default: localhost.localdomain validators: [] @@ -101,7 +111,7 @@ locations: spec: values: - value: shared - error: The vsys cannot be "shared". Use the "shared" path instead. + error: The vsys cannot be "shared". type: entry description: Located in a specific template, device and vsys. devices: @@ -110,7 +120,7 @@ locations: validators: [] required: false read_only: false -- name: template_stack +- name: template-stack xpath: path: - config @@ -122,24 +132,23 @@ locations: - shared vars: - name: panorama_device - description: The panorama device. + description: Specific Panorama device required: false default: localhost.localdomain validators: [] type: entry - name: template_stack - description: The template stack. + description: The template stack required: true validators: [] type: entry - description: Located in a specific template stack. + description: Located in a specific template devices: - panorama - - ngfw validators: [] required: false read_only: false -- name: template_stack_vsys +- name: template-stack-vsys xpath: path: - config @@ -154,18 +163,18 @@ locations: - $vsys vars: - name: panorama_device - description: The panorama device. + description: Specific Panorama device required: false default: localhost.localdomain validators: [] type: entry - name: template_stack - description: The template stack. + description: The template stack required: true validators: [] type: entry - name: ngfw_device - description: The NGFW device. + description: The NGFW device required: false default: localhost.localdomain validators: [] @@ -179,27 +188,15 @@ locations: spec: values: - value: shared - error: The vsys cannot be "shared". Use the "shared" path instead. + error: The vsys cannot be "shared". type: entry - description: Located in a specific template stack, device and vsys. + description: Located in a specific template, device and vsys. devices: - panorama - ngfw validators: [] required: false read_only: false -- name: shared - xpath: - path: - - config - - shared - vars: [] - description: Located in shared. - devices: - - ngfw - validators: [] - required: false - read_only: false entries: - name: name description: '' From 6db205f194fbb3c68475e6b863ed45d6876195dc Mon Sep 17 00:00:00 2001 From: Krzysztof Klimonda Date: Thu, 29 May 2025 14:27:55 +0200 Subject: [PATCH 2/2] feat(specs): Add spec, tests and examples for server radius profile --- .../test/resource_radius_profile_test.go | 477 +++++++++++++++++ specs/device/profiles/radius.yaml | 480 ++++++++++++++++++ 2 files changed, 957 insertions(+) create mode 100644 assets/terraform/test/resource_radius_profile_test.go create mode 100644 specs/device/profiles/radius.yaml diff --git a/assets/terraform/test/resource_radius_profile_test.go b/assets/terraform/test/resource_radius_profile_test.go new file mode 100644 index 00000000..94942d87 --- /dev/null +++ b/assets/terraform/test/resource_radius_profile_test.go @@ -0,0 +1,477 @@ +package provider_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + //"github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" +) + +func TestAccServerRadiusProfile_Basic(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_Basic_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + }, + }, + }, + }) +} + +const panosServerRadiusProfile_Basic_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + + name = var.prefix +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix +} +` + +const panosServerRadiusProfile_Chap_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + + name = var.prefix +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + protocol = { + chap = {} + } + retries = 3 + timeout = 3 + server = [ + { + name = "server1" + ip_address = "192.168.1.1" + secret = "test-secret-1" + port = 1812 + }, + { + name = "server2" + ip_address = "192.168.1.2" + secret = "test-secret-2" + port = 1813 + } + ] +} +` + +func TestAccServerRadiusProfile_Chap(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_Chap_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("protocol").AtMapKey("chap"), + knownvalue.ObjectExact(map[string]knownvalue.Check{}), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("retries"), + knownvalue.Int64Exact(3), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("timeout"), + knownvalue.Int64Exact(3), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("server"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("server1"), + "ip_address": knownvalue.StringExact("192.168.1.1"), + "secret": knownvalue.StringExact("test-secret-1"), + "port": knownvalue.Int64Exact(1812), + }), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("server2"), + "ip_address": knownvalue.StringExact("192.168.1.2"), + "secret": knownvalue.StringExact("test-secret-2"), + "port": knownvalue.Int64Exact(1813), + }), + }), + ), + }, + }, + }, + }) +} + +const panosServerRadiusProfile_EAP_TTLS_with_PAP_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_certificate_profile" "cert_prof" { + depends_on = [panos_template.example] + location = var.location + name = "test-cert-profile" +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_certificate_profile.cert_prof] + location = var.location + + name = var.prefix + protocol = { + eap_ttls_with_pap = { + anon_outer_id = true + radius_cert_profile = panos_certificate_profile.cert_prof.name + } + } + retries = 4 + timeout = 5 + server = [ + { + name = "server1" + ip_address = "192.168.1.1" + secret = "test-secret-1" + port = 1812 + } + ] +} +` + +func TestAccServerRadiusProfile_EAP_TTLS_with_PAP(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_EAP_TTLS_with_PAP_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("protocol").AtMapKey("eap_ttls_with_pap"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "anon_outer_id": knownvalue.Bool(true), + "radius_cert_profile": knownvalue.StringExact("test-cert-profile"), + }), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("retries"), + knownvalue.Int64Exact(4), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("timeout"), + knownvalue.Int64Exact(5), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("server"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("server1"), + "ip_address": knownvalue.StringExact("192.168.1.1"), + "secret": knownvalue.StringExact("test-secret-1"), + "port": knownvalue.Int64Exact(1812), + }), + }), + ), + }, + }, + }, + }) +} + +const panosServerRadiusProfile_PAP_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + + name = var.prefix +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + protocol = { + pap = {} + } +} +` + +func TestAccServerRadiusProfile_PAP(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_PAP_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("protocol").AtMapKey("pap"), + knownvalue.ObjectExact(map[string]knownvalue.Check{}), + ), + }, + }, + }, + }) +} + +const panosServerRadiusProfile_PEAP_MSCHAPv2_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_certificate_profile" "cert_prof" { + depends_on = [panos_template.example] + location = var.location + name = "test-cert-profile" +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_certificate_profile.cert_prof] + location = var.location + + name = var.prefix + protocol = { + peap_mschapv2 = { + allow_pwd_change = true + anon_outer_id = true + radius_cert_profile = panos_certificate_profile.cert_prof.name + } + } +} +` + +func TestAccServerRadiusProfile_PEAP_MSCHAPv2(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_PEAP_MSCHAPv2_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("protocol").AtMapKey("peap_mschapv2"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "allow_pwd_change": knownvalue.Bool(true), + "anon_outer_id": knownvalue.Bool(true), + "radius_cert_profile": knownvalue.StringExact("test-cert-profile"), + }), + ), + }, + }, + }, + }) +} + +const panosServerRadiusProfile_PEAP_with_GTC_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_certificate_profile" "cert_prof" { + depends_on = [panos_template.example] + location = var.location + name = "test-cert-profile" +} + +resource "panos_radius_profile" "example" { + depends_on = [panos_certificate_profile.cert_prof] + location = var.location + + name = var.prefix + protocol = { + peap_with_gtc = { + anon_outer_id = true + radius_cert_profile = panos_certificate_profile.cert_prof.name + } + } +} +` + +func TestAccServerRadiusProfile_PEAP_with_GTC(t *testing.T) { + t.Parallel() + + nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) + prefix := fmt.Sprintf("test-acc-%s", nameSuffix) + + location := config.ObjectVariable(map[string]config.Variable{ + "template": config.ObjectVariable(map[string]config.Variable{ + "name": config.StringVariable(prefix), + }), + }) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosServerRadiusProfile_PEAP_with_GTC_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_radius_profile.example", + tfjsonpath.New("protocol").AtMapKey("peap_with_gtc"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "anon_outer_id": knownvalue.Bool(true), + "radius_cert_profile": knownvalue.StringExact("test-cert-profile"), + }), + ), + }, + }, + }, + }) +} diff --git a/specs/device/profiles/radius.yaml b/specs/device/profiles/radius.yaml new file mode 100644 index 00000000..8879ed5f --- /dev/null +++ b/specs/device/profiles/radius.yaml @@ -0,0 +1,480 @@ +name: radius-profile +terraform_provider_config: + description: RADIUS Server Profile + skip_resource: false + skip_datasource: false + resource_type: entry + resource_variants: + - singular + suffix: radius_profile + plural_suffix: '' + plural_name: '' + plural_description: '' +go_sdk_config: + skip: false + package: + - device + - profiles + - radius +panos_xpath: + path: + - server-profile + - radius + vars: [] +locations: +- name: panorama + xpath: + path: + - config + - panorama + vars: [] + description: Located in a panorama. + validators: [] + required: false + read_only: false +- name: shared + xpath: + path: + - config + - shared + vars: [] + description: Panorama shared object + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false +- name: vsys + xpath: + path: + - config + - devices + - $ngfw_device + - vsys + - $vsys + vars: + - name: ngfw_device + description: The NGFW device name + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: vsys + description: The Virtual System name + required: false + default: vsys1 + validators: + - type: not-values + spec: + values: + - value: shared + error: The vsys name cannot be "shared". Use the "shared" location instead + type: entry + description: Located in a specific Virtual System + devices: + - ngfw + validators: [] + required: false + read_only: false +- name: template + xpath: + path: + - config + - devices + - $panorama_device + - template + - $template + - config + - shared + vars: + - name: panorama_device + description: Specific Panorama device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: template + description: Specific Panorama template + required: true + validators: [] + type: entry + description: A shared resource located within a specific template + devices: + - panorama + validators: [] + required: false + read_only: false +- name: template-vsys + xpath: + path: + - config + - devices + - $panorama_device + - template + - $template + - config + - devices + - $ngfw_device + - vsys + - $vsys + vars: + - name: panorama_device + description: Specific Panorama device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: template + description: Specific Panorama template + required: true + validators: [] + type: entry + - name: ngfw_device + description: The NGFW device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: vsys + description: The vsys. + required: false + default: vsys1 + validators: + - type: not-values + spec: + values: + - value: shared + error: The vsys cannot be "shared". + type: entry + description: Located in a specific template, device and vsys. + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false +- name: template-stack + xpath: + path: + - config + - devices + - $panorama_device + - template-stack + - $template_stack + - config + - shared + vars: + - name: panorama_device + description: Specific Panorama device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: template_stack + description: The template stack + required: true + validators: [] + type: entry + description: Located in a specific template + devices: + - panorama + validators: [] + required: false + read_only: false +- name: template-stack-vsys + xpath: + path: + - config + - devices + - $panorama_device + - template-stack + - $template_stack + - config + - devices + - $ngfw_device + - vsys + - $vsys + vars: + - name: panorama_device + description: Specific Panorama device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: template_stack + description: The template stack + required: true + validators: [] + type: entry + - name: ngfw_device + description: The NGFW device + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: vsys + description: The vsys. + required: false + default: vsys1 + validators: + - type: not-values + spec: + values: + - value: shared + error: The vsys cannot be "shared". + type: entry + description: Located in a specific template, device and vsys. + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false +entries: +- name: name + description: '' + validators: [] +imports: [] +spec: + params: + - name: protocol + type: object + profiles: + - xpath: + - protocol + validators: [] + spec: + params: [] + variants: + - name: CHAP + type: object + profiles: + - xpath: + - CHAP + validators: [] + spec: + params: [] + variants: [] + description: CHAP + required: false + codegen_overrides: + gosdk: + name: chap + terraform: + name: chap + - name: EAP-TTLS-with-PAP + type: object + profiles: + - xpath: + - EAP-TTLS-with-PAP + validators: [] + spec: + params: + - name: anon-outer-id + type: bool + profiles: + - xpath: + - anon-outer-id + validators: [] + spec: {} + description: Make Outer Identity Anonymous + required: false + - name: radius-cert-profile + type: string + profiles: + - xpath: + - radius-cert-profile + validators: [] + spec: {} + description: Certificate profile for verifying the RADIUS server + required: false + variants: [] + description: EAP-TTLS with PAP + required: false + codegen_overrides: + gosdk: + name: eap-ttls-with-pap + terraform: + name: eap-ttls-with-pap + - name: PAP + type: object + profiles: + - xpath: + - PAP + validators: [] + spec: + params: [] + variants: [] + description: PAP + required: false + codegen_overrides: + gosdk: + name: pap + terraform: + name: pap + - name: PEAP-MSCHAPv2 + type: object + profiles: + - xpath: + - PEAP-MSCHAPv2 + validators: [] + spec: + params: + - name: allow-pwd-change + type: bool + profiles: + - xpath: + - allow-pwd-change + validators: [] + spec: {} + description: Allow users to change passwords after expiry + required: false + - name: anon-outer-id + type: bool + profiles: + - xpath: + - anon-outer-id + validators: [] + spec: {} + description: Make Outer Identity Anonymous + required: false + - name: radius-cert-profile + type: string + profiles: + - xpath: + - radius-cert-profile + validators: [] + spec: {} + description: Certificate profile for verifying the RADIUS server + required: false + variants: [] + description: PEAP-MSCHAPv2 + required: false + codegen_overrides: + gosdk: + name: peap-mschapv2 + terraform: + name: peap-mschapv2 + - name: PEAP-with-GTC + type: object + profiles: + - xpath: + - PEAP-with-GTC + validators: [] + spec: + params: + - name: anon-outer-id + type: bool + profiles: + - xpath: + - anon-outer-id + validators: [] + spec: {} + description: Make Outer Identity Anonymous + required: false + - name: radius-cert-profile + type: string + profiles: + - xpath: + - radius-cert-profile + validators: [] + spec: {} + description: Certificate profile for verifying the RADIUS server + required: false + variants: [] + description: PEAP with GTC + required: false + codegen_overrides: + gosdk: + name: peap-with-gtc + terraform: + name: peap-with-gtc + description: Select authentication protocol + required: false + - name: retries + type: int64 + profiles: + - xpath: + - retries + validators: + - type: length + spec: + min: 1 + max: 5 + spec: + default: 3 + description: number of attempts before giving up authentication + required: false + - name: server + type: list + profiles: + - xpath: + - server + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: ip-address + type: string + profiles: + - xpath: + - ip-address + validators: [] + spec: {} + description: RADIUS server IP or host name + required: false + - name: secret + type: string + profiles: + - xpath: + - secret + validators: + - type: length + spec: + max: 64 + spec: {} + description: Shared secret for RADIUS communication + required: false + codegen_overrides: + terraform: + sensitive: false + hashing: + type: solo + - name: port + type: int64 + profiles: + - xpath: + - port + validators: + - type: length + spec: + min: 1 + max: 65535 + spec: + default: 1812 + description: RADIUS server port + required: false + variants: [] + description: '' + required: false + - name: timeout + type: int64 + profiles: + - xpath: + - timeout + validators: + - type: length + spec: + min: 1 + max: 120 + spec: + default: 3 + description: number of seconds to wait for when performing authentication + required: false + variants: []