From 50ef484af2f46698c17d67e4fca5779b1e12f88b Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Tue, 14 Apr 2026 19:53:18 +0530 Subject: [PATCH 01/10] feat(specs): Add new security and device profile specs - Add data_filtering_security_profile spec with vsys and template locations - Add decryption_profile spec (ssl-inbound-proxy element, correct field names) - Add snmp_trap_profile spec with v2c/v3 variant support - Add email_server_profile spec matching syslog profile structure - Add administrator spec with correct permissions/role-based XML structure - Fix pango error parser to surface raw Panorama response when msg is empty Co-Authored-By: Claude Sonnet 4.6 --- assets/pango/errors/panos.go | 6 +- specs/device/administrator.yaml | 233 +++++++ specs/device/profiles/data-filtering.yaml | 211 ++++++- .../device/profiles/email-server-profile.yaml | 577 ++++++++++++++++++ specs/device/profiles/snmp-trap-profile.yaml | 427 +++++++++++++ .../objects/profiles/decryption-profile.yaml | 496 +++++++++++++++ 6 files changed, 1937 insertions(+), 13 deletions(-) create mode 100644 specs/device/administrator.yaml create mode 100644 specs/device/profiles/email-server-profile.yaml create mode 100644 specs/device/profiles/snmp-trap-profile.yaml create mode 100644 specs/objects/profiles/decryption-profile.yaml diff --git a/assets/pango/errors/panos.go b/assets/pango/errors/panos.go index 9b9f30c4..d98daf02 100644 --- a/assets/pango/errors/panos.go +++ b/assets/pango/errors/panos.go @@ -58,8 +58,12 @@ func Parse(body []byte) error { _ = xml.Unmarshal(body, &e) if e.Failed() { + msg := e.Message() + if msg == "" { + msg = fmt.Sprintf("(raw response: %s)", strings.TrimSpace(string(body))) + } return Panos{ - Msg: e.Message(), + Msg: msg, Code: e.Code, } } diff --git a/specs/device/administrator.yaml b/specs/device/administrator.yaml new file mode 100644 index 00000000..305a7e5a --- /dev/null +++ b/specs/device/administrator.yaml @@ -0,0 +1,233 @@ +name: administrator +terraform_provider_config: + description: Administrator Account + skip_resource: false + skip_datasource: false + resource_type: entry + resource_variants: [] + suffix: administrator + plural_suffix: '' + plural_name: '' + plural_description: '' + custom_validation: false +go_sdk_config: + skip: false + package: + - device + - administrator +panos_xpath: + path: + - mgt-config + - users + vars: [] +locations: +- name: panorama + xpath: + path: + - config + vars: [] + description: Panorama administrator + devices: + - panorama + validators: [] + required: false + read_only: false +- name: template + xpath: + path: + - config + - devices + - $panorama_device + - template + - $template + - config + 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: Administrator pushed via a Panorama template + devices: + - panorama + validators: [] + required: false + read_only: false +- name: template-stack + xpath: + path: + - config + - devices + - $panorama_device + - template-stack + - $template_stack + - config + 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: Administrator pushed via a Panorama template stack + devices: + - panorama + validators: [] + required: false + read_only: false +entries: +- name: name + description: '' + validators: [] +spec: + params: + - name: authentication-profile + type: string + profiles: + - xpath: + - authentication-profile + validators: + - type: length + spec: + max: 255 + spec: {} + description: Authentication profile for this administrator + required: false + - name: public-key + type: string + profiles: + - xpath: + - public-key + validators: + - type: length + spec: + max: 4096 + spec: {} + description: SSH public key for certificate-based authentication + required: false + - name: phash + type: string + profiles: + - xpath: + - phash + validators: [] + spec: {} + description: Hashed administrator password + required: false + codegen_overrides: + terraform: + name: password + sensitive: true + hashing: + type: solo + - name: permissions + type: object + profiles: + - xpath: + - permissions + validators: [] + spec: + params: + - name: role-based + type: object + profiles: + - xpath: + - role-based + validators: [] + spec: + params: + - name: superuser + type: bool + profiles: + - xpath: + - superuser + validators: [] + spec: {} + description: Full system access + required: false + - name: superreader + type: bool + profiles: + - xpath: + - superreader + validators: [] + spec: {} + description: Read-only access to entire system + required: false + - name: deviceadmin + type: bool + profiles: + - xpath: + - deviceadmin + validators: [] + spec: {} + description: Device administrator access (all vsys) + required: false + - name: devicereader + type: bool + profiles: + - xpath: + - devicereader + validators: [] + spec: {} + description: Device read-only access (all vsys) + required: false + - name: vsysadmin + type: bool + profiles: + - xpath: + - vsysadmin + validators: [] + spec: {} + description: Virtual system administrator access + required: false + - name: vsysreader + type: bool + profiles: + - xpath: + - vsysreader + validators: [] + spec: {} + description: Virtual system read-only access + required: false + - name: custom + type: object + profiles: + - xpath: + - custom + validators: [] + spec: + params: + - name: profile + type: string + profiles: + - xpath: + - profile + validators: + - type: length + spec: + max: 255 + spec: {} + description: Custom admin role profile name + required: false + variants: [] + description: Custom role based on an admin role profile + required: false + variants: [] + description: Role-based access control + required: false + variants: [] + description: Administrator permissions and role assignment + required: false + variants: [] diff --git a/specs/device/profiles/data-filtering.yaml b/specs/device/profiles/data-filtering.yaml index 785042ee..165758ca 100644 --- a/specs/device/profiles/data-filtering.yaml +++ b/specs/device/profiles/data-filtering.yaml @@ -1,12 +1,12 @@ name: data-filtering-profile terraform_provider_config: - description: Data Filtering Profile + description: Data Filtering Security Profile skip_resource: false skip_datasource: false resource_type: entry resource_variants: - singular - suffix: data_filtering_profile + suffix: data_filtering_security_profile plural_suffix: '' plural_name: '' plural_description: '' @@ -36,6 +36,38 @@ locations: 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: device-group xpath: path: @@ -69,6 +101,160 @@ locations: 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 stack + 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 stack, device and vsys. + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false entries: - name: name description: '' @@ -82,7 +268,7 @@ spec: - data-capture validators: [] spec: {} - description: '' + description: Enable data capture required: false - name: description type: string @@ -113,7 +299,7 @@ spec: values: - value: 'yes' - value: 'no' - description: disable object override in child device groups + description: Disable object override in child device groups required: false - name: rules type: list @@ -136,7 +322,7 @@ spec: - data-object validators: [] spec: {} - description: '' + description: Name of the data pattern object required: false - name: direction type: enum @@ -151,11 +337,12 @@ spec: - download - both spec: + default: both values: - value: upload - value: download - value: both - description: '' + description: Direction of data transfer to monitor required: false - name: alert-threshold type: int64 @@ -169,7 +356,7 @@ spec: max: 65535 spec: default: 1 - description: '' + description: Alert threshold count required: false - name: block-threshold type: int64 @@ -183,7 +370,7 @@ spec: max: 65535 spec: default: 1 - description: '' + description: Block threshold count required: false - name: log-severity type: string @@ -193,7 +380,7 @@ spec: validators: [] spec: default: informational - description: '' + description: Log severity for matched traffic required: false - name: application type: list @@ -206,7 +393,7 @@ spec: type: string items: type: string - description: '' + description: Applications to match required: false - name: file-type type: list @@ -219,9 +406,9 @@ spec: type: string items: type: string - description: '' + description: File types to match required: false variants: [] - description: '' + description: Data filtering rules required: false variants: [] diff --git a/specs/device/profiles/email-server-profile.yaml b/specs/device/profiles/email-server-profile.yaml new file mode 100644 index 00000000..900ec7ab --- /dev/null +++ b/specs/device/profiles/email-server-profile.yaml @@ -0,0 +1,577 @@ +name: email-server-profile +terraform_provider_config: + description: Email Server Profile + skip_resource: false + skip_datasource: false + resource_type: entry + resource_variants: + - singular + suffix: email_server_profile + plural_suffix: '' + plural_name: '' + plural_description: '' + custom_validation: false +go_sdk_config: + skip: false + package: + - device + - profiles + - email +panos_xpath: + path: + - log-settings + - email + vars: [] +locations: +- name: panorama + xpath: + path: + - config + - panorama + vars: [] + description: Located in a panorama. + 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 stack + 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 stack, device and vsys. + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false +entries: +- name: name + description: '' + validators: [] +spec: + params: + - name: server + type: list + profiles: + - xpath: + - server + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: from + type: string + profiles: + - xpath: + - from + validators: + - type: length + spec: + max: 128 + spec: {} + description: From email address + required: false + - name: to + type: string + profiles: + - xpath: + - to + validators: + - type: length + spec: + max: 128 + spec: {} + description: To email address + required: false + - name: and-also-to + type: string + profiles: + - xpath: + - and-also-to + validators: + - type: length + spec: + max: 128 + spec: {} + description: Additional CC email address + required: false + - name: gateway + type: string + profiles: + - xpath: + - gateway + validators: + - type: length + spec: + max: 63 + spec: {} + description: IP address or FQDN of SMTP gateway + required: false + - name: port + type: int64 + profiles: + - xpath: + - port + validators: + - type: length + spec: + min: 1 + max: 65535 + spec: + default: 25 + description: SMTP port number + required: false + - name: tls-version + type: enum + profiles: + - xpath: + - tls-version + validators: + - type: values + spec: + values: + - '1.0' + - '1.1' + - '1.2' + spec: + default: '1.2' + values: + - value: '1.0' + - value: '1.1' + - value: '1.2' + description: Minimum TLS version for SMTP connection + required: false + - name: auth + type: enum + profiles: + - xpath: + - auth + validators: + - type: values + spec: + values: + - Auto + - Login + - Plain + spec: + default: Auto + values: + - value: Auto + - value: Login + - value: Plain + description: Authentication method for SMTP + required: false + - name: certificate-profile + type: string + profiles: + - xpath: + - certificate-profile + validators: + - type: length + spec: + max: 255 + spec: {} + description: Certificate profile for TLS verification + required: false + variants: [] + description: List of email servers + required: false + codegen_overrides: + terraform: + name: servers + - name: format + type: object + profiles: + - xpath: + - format + validators: [] + spec: + params: + - name: auth + type: string + profiles: + - xpath: + - auth + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for auth log + required: false + - name: config + type: string + profiles: + - xpath: + - config + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for config log + required: false + - name: correlation + type: string + profiles: + - xpath: + - correlation + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for correlation log + required: false + - name: data + type: string + profiles: + - xpath: + - data + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for data log + required: false + - name: decryption + type: string + profiles: + - xpath: + - decryption + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for decryption log + required: false + - name: globalprotect + type: string + profiles: + - xpath: + - globalprotect + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for globalprotect log + required: false + - name: gtp + type: string + profiles: + - xpath: + - gtp + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for gtp log + required: false + - name: hip-match + type: string + profiles: + - xpath: + - hip-match + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for hip-match log + required: false + - name: iptag + type: string + profiles: + - xpath: + - iptag + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for iptag log + required: false + - name: sctp + type: string + profiles: + - xpath: + - sctp + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for sctp log + required: false + - name: system + type: string + profiles: + - xpath: + - system + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for system log + required: false + - name: threat + type: string + profiles: + - xpath: + - threat + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for threat log + required: false + - name: traffic + type: string + profiles: + - xpath: + - traffic + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for traffic log + required: false + - name: tunnel + type: string + profiles: + - xpath: + - tunnel + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for tunnel log + required: false + - name: url + type: string + profiles: + - xpath: + - url + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for url log + required: false + - name: userid + type: string + profiles: + - xpath: + - userid + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for userid log + required: false + - name: wildfire + type: string + profiles: + - xpath: + - wildfire + validators: + - type: length + spec: + max: 2048 + spec: {} + description: Custom format for wildfire log + required: false + variants: [] + description: Custom log format strings + required: false + variants: [] diff --git a/specs/device/profiles/snmp-trap-profile.yaml b/specs/device/profiles/snmp-trap-profile.yaml new file mode 100644 index 00000000..1ab2fda2 --- /dev/null +++ b/specs/device/profiles/snmp-trap-profile.yaml @@ -0,0 +1,427 @@ +name: snmp-trap-profile +terraform_provider_config: + description: SNMP Trap Server Profile + skip_resource: false + skip_datasource: false + resource_type: entry + resource_variants: + - singular + suffix: snmp_trap_profile + plural_suffix: '' + plural_name: '' + plural_description: '' + custom_validation: false +go_sdk_config: + skip: false + package: + - device + - profiles + - snmptrap +panos_xpath: + path: + - log-settings + - snmptrap + vars: [] +locations: +- name: panorama + xpath: + path: + - config + - panorama + vars: [] + description: Located in a panorama. + 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 stack + 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 stack, device and vsys. + devices: + - panorama + - ngfw + validators: [] + required: false + read_only: false +entries: +- name: name + description: '' + validators: [] +spec: + params: + - name: version + type: object + profiles: + - xpath: + - version + validators: [] + spec: + params: [] + variants: + - name: v2c + type: object + profiles: + - xpath: + - v2c + validators: [] + spec: + params: + - name: server + type: list + profiles: + - xpath: + - server + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: community + type: string + profiles: + - xpath: + - community + validators: + - type: length + spec: + max: 127 + spec: {} + description: SNMP community string + required: false + - name: manager + type: string + profiles: + - xpath: + - manager + validators: + - type: length + spec: + max: 63 + spec: {} + description: IP address or FQDN of SNMP manager + required: false + variants: [] + description: List of SNMPv2c trap receivers + required: false + codegen_overrides: + terraform: + name: servers + variants: [] + description: SNMPv2c configuration + required: false + - name: v3 + type: object + profiles: + - xpath: + - v3 + validators: [] + spec: + params: + - name: server + type: list + profiles: + - xpath: + - server + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: engineid + type: string + profiles: + - xpath: + - engineid + validators: + - type: length + spec: + max: 255 + spec: {} + description: SNMP engine ID (hex string, e.g. 0x80...) + required: false + - name: manager + type: string + profiles: + - xpath: + - manager + validators: + - type: length + spec: + max: 63 + spec: {} + description: IP address or FQDN of SNMP manager + required: false + - name: user + type: string + profiles: + - xpath: + - user + validators: + - type: length + spec: + max: 31 + spec: {} + description: SNMPv3 username + required: false + - name: authpwd + type: string + profiles: + - xpath: + - authpwd + validators: + - type: length + spec: + max: 255 + spec: {} + description: SNMPv3 authentication password + required: false + codegen_overrides: + terraform: + sensitive: true + - name: privpwd + type: string + profiles: + - xpath: + - privpwd + validators: + - type: length + spec: + max: 255 + spec: {} + description: SNMPv3 privacy password + required: false + codegen_overrides: + terraform: + sensitive: true + - name: authproto + type: enum + profiles: + - xpath: + - authproto + validators: + - type: values + spec: + values: + - MD5 + - SHA + spec: + default: SHA + values: + - value: MD5 + - value: SHA + description: Authentication protocol + required: false + - name: privproto + type: enum + profiles: + - xpath: + - privproto + validators: + - type: values + spec: + values: + - AES128 + - DES + spec: + default: AES128 + values: + - value: AES128 + - value: DES + description: Privacy protocol + required: false + variants: [] + description: List of SNMPv3 trap receivers + required: false + codegen_overrides: + terraform: + name: servers + variants: [] + description: SNMPv3 configuration + required: false + description: SNMP version and server configuration + required: false + variants: [] diff --git a/specs/objects/profiles/decryption-profile.yaml b/specs/objects/profiles/decryption-profile.yaml new file mode 100644 index 00000000..d5b93f29 --- /dev/null +++ b/specs/objects/profiles/decryption-profile.yaml @@ -0,0 +1,496 @@ +name: decryption-profile +terraform_provider_config: + description: Decryption Profile + skip_resource: false + skip_datasource: false + resource_type: entry + resource_variants: + - singular + suffix: decryption_profile + plural_suffix: '' + plural_name: '' + plural_description: '' + custom_validation: false +go_sdk_config: + skip: false + package: + - objects + - profiles + - decryption +panos_xpath: + path: + - profiles + - decryption + vars: [] +locations: +- 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: device-group + xpath: + path: + - config + - devices + - $panorama_device + - device-group + - $device_group + vars: + - name: panorama_device + description: Panorama device name + required: false + default: localhost.localdomain + validators: [] + type: entry + - name: device_group + description: Device Group name + required: true + validators: + - type: not-values + spec: + values: + - value: shared + error: The device group name cannot be "shared". Use the "shared" location + instead + type: entry + location_filter: true + description: Located in a specific Device Group + devices: + - panorama + validators: [] + required: false + read_only: false +entries: +- name: name + description: '' + validators: [] +spec: + params: + - name: description + type: string + profiles: + - xpath: + - description + validators: + - type: length + spec: + min: 0 + max: 255 + spec: {} + description: '' + required: false + - name: ssl-forward-proxy + type: object + profiles: + - xpath: + - ssl-forward-proxy + validators: [] + spec: + params: + - name: auto-include-altname + type: bool + profiles: + - xpath: + - auto-include-altname + validators: [] + spec: {} + description: Automatically include the alternative name of the certificate + required: false + - name: block-client-cert + type: bool + profiles: + - xpath: + - block-client-cert + validators: [] + spec: {} + description: Block sessions with client certificate + required: false + - name: block-expired-certificate + type: bool + profiles: + - xpath: + - block-expired-certificate + validators: [] + spec: {} + description: Block sessions with expired certificates + required: false + - name: block-timeout-cert + type: bool + profiles: + - xpath: + - block-timeout-cert + validators: [] + spec: {} + description: Block sessions if certificate status cannot be retrieved within timeout + required: false + - name: block-unknown-cert + type: bool + profiles: + - xpath: + - block-unknown-cert + validators: [] + spec: {} + description: Block sessions if certificate status is unknown + required: false + - name: block-unsupported-cipher + type: bool + profiles: + - xpath: + - block-unsupported-cipher + validators: [] + spec: {} + description: Block sessions with unsupported cipher suites + required: false + - name: block-unsupported-version + type: bool + profiles: + - xpath: + - block-unsupported-version + validators: [] + spec: {} + description: Block sessions with unsupported protocol versions + required: false + - name: block-untrusted-issuer + type: bool + profiles: + - xpath: + - block-untrusted-issuer + validators: [] + spec: {} + description: Block sessions with untrusted certificate issuers + required: false + - name: client-cert-auth + type: bool + profiles: + - xpath: + - client-cert-auth + validators: [] + spec: {} + description: Enable client certificate authentication + required: false + - name: restrict-cert-exts + type: bool + profiles: + - xpath: + - restrict-cert-exts + validators: [] + spec: {} + description: Restrict certificate extensions + required: false + - name: strip-alpn + type: bool + profiles: + - xpath: + - strip-alpn + validators: [] + spec: {} + description: Strip ALPN extension from ClientHello + required: false + variants: [] + description: SSL forward proxy decryption settings + required: false + - name: ssl-inbound-proxy + type: object + profiles: + - xpath: + - ssl-inbound-proxy + validators: [] + spec: + params: + - name: block-if-no-resource + type: bool + profiles: + - xpath: + - block-if-no-resource + validators: [] + spec: {} + description: Block sessions when decryption resources are not available + required: false + - name: block-unsupported-cipher + type: bool + profiles: + - xpath: + - block-unsupported-cipher + validators: [] + spec: {} + description: Block sessions with unsupported cipher suites + required: false + - name: block-unsupported-version + type: bool + profiles: + - xpath: + - block-unsupported-version + validators: [] + spec: {} + description: Block sessions with unsupported protocol versions + required: false + - name: block-if-hsm-unavailable + type: bool + profiles: + - xpath: + - block-if-hsm-unavailable + validators: [] + spec: {} + description: Block sessions when HSM is unavailable + required: false + - name: block-tls13-downgrade-no-resource + type: bool + profiles: + - xpath: + - block-tls13-downgrade-no-resource + validators: [] + spec: {} + description: Block TLS 1.3 downgrade when no resources are available + required: false + variants: [] + description: SSL inbound proxy decryption settings + required: false + - name: ssl-no-proxy + type: object + profiles: + - xpath: + - ssl-no-proxy + validators: [] + spec: + params: + - name: block-expired-certificate + type: bool + profiles: + - xpath: + - block-expired-certificate + validators: [] + spec: {} + description: Block sessions with expired certificates + required: false + - name: block-untrusted-issuer + type: bool + profiles: + - xpath: + - block-untrusted-issuer + validators: [] + spec: {} + description: Block sessions with untrusted certificate issuers + required: false + variants: [] + description: SSL no-proxy decryption settings + required: false + - name: ssl-protocol-settings + type: object + profiles: + - xpath: + - ssl-protocol-settings + validators: [] + spec: + params: + - name: min-version + type: enum + profiles: + - xpath: + - min-version + validators: + - type: values + spec: + values: + - sslv3 + - tls1-0 + - tls1-1 + - tls1-2 + - tls1-3 + spec: + default: tls1-0 + values: + - value: sslv3 + - value: tls1-0 + - value: tls1-1 + - value: tls1-2 + - value: tls1-3 + description: Minimum SSL/TLS protocol version + required: false + - name: max-version + type: enum + profiles: + - xpath: + - max-version + validators: + - type: values + spec: + values: + - sslv3 + - tls1-0 + - tls1-1 + - tls1-2 + - tls1-3 + - max + spec: + default: max + values: + - value: sslv3 + - value: tls1-0 + - value: tls1-1 + - value: tls1-2 + - value: tls1-3 + - value: max + description: Maximum SSL/TLS protocol version + required: false + - name: auth-algo-md5 + type: bool + profiles: + - xpath: + - auth-algo-md5 + validators: [] + spec: {} + description: Allow MD5 authentication algorithm + required: false + - name: auth-algo-sha1 + type: bool + profiles: + - xpath: + - auth-algo-sha1 + validators: [] + spec: {} + description: Allow SHA1 authentication algorithm + required: false + - name: auth-algo-sha256 + type: bool + profiles: + - xpath: + - auth-algo-sha256 + validators: [] + spec: {} + description: Allow SHA256 authentication algorithm + required: false + - name: auth-algo-sha384 + type: bool + profiles: + - xpath: + - auth-algo-sha384 + validators: [] + spec: {} + description: Allow SHA384 authentication algorithm + required: false + - name: enc-algo-3des + type: bool + profiles: + - xpath: + - enc-algo-3des + validators: [] + spec: {} + description: Allow 3DES encryption algorithm + required: false + - name: enc-algo-rc4 + type: bool + profiles: + - xpath: + - enc-algo-rc4 + validators: [] + spec: {} + description: Allow RC4 encryption algorithm + required: false + - name: enc-algo-aes-128-cbc + type: bool + profiles: + - xpath: + - enc-algo-aes-128-cbc + validators: [] + spec: {} + description: Allow AES-128-CBC encryption algorithm + required: false + - name: enc-algo-aes-256-cbc + type: bool + profiles: + - xpath: + - enc-algo-aes-256-cbc + validators: [] + spec: {} + description: Allow AES-256-CBC encryption algorithm + required: false + - name: enc-algo-aes-128-gcm + type: bool + profiles: + - xpath: + - enc-algo-aes-128-gcm + validators: [] + spec: {} + description: Allow AES-128-GCM encryption algorithm + required: false + - name: enc-algo-aes-256-gcm + type: bool + profiles: + - xpath: + - enc-algo-aes-256-gcm + validators: [] + spec: {} + description: Allow AES-256-GCM encryption algorithm + required: false + - name: keyxchg-algo-dhe + type: bool + profiles: + - xpath: + - keyxchg-algo-dhe + validators: [] + spec: {} + description: Allow DHE key exchange algorithm + required: false + - name: keyxchg-algo-ecdhe + type: bool + profiles: + - xpath: + - keyxchg-algo-ecdhe + validators: [] + spec: {} + description: Allow ECDHE key exchange algorithm + required: false + - name: keyxchg-algo-rsa + type: bool + profiles: + - xpath: + - keyxchg-algo-rsa + validators: [] + spec: {} + description: Allow RSA key exchange algorithm + required: false + variants: [] + description: SSL/TLS protocol settings + required: false + variants: [] From 002f802a6f5f0dfa75a48da0b51e71c49e1f41d7 Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Mon, 20 Apr 2026 10:41:10 +0530 Subject: [PATCH 02/10] fix(examples): Add missing Terraform examples and fix renamed data filtering resource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename panos_data_filtering_profile → panos_data_filtering_security_profile in example - Add example for panos_decryption_profile - Add example for panos_snmp_trap_profile - Add example for panos_email_server_profile - Add example for panos_administrator Co-Authored-By: Claude Sonnet 4.6 --- .../resources/panos_administrator/resource.tf | 13 + .../panos_data_filtering_profile/resource.tf | 2 +- .../panos_decryption_profile/resource.tf | 27 + .../panos_email_server_profile/resource.tf | 62 +- .../panos_snmp_trap_profile/resource.tf | 20 + .../device/profiles/email-server-profile.yaml | 577 ------------------ 6 files changed, 76 insertions(+), 625 deletions(-) create mode 100644 assets/terraform/examples/resources/panos_administrator/resource.tf create mode 100644 assets/terraform/examples/resources/panos_decryption_profile/resource.tf create mode 100644 assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf delete mode 100644 specs/device/profiles/email-server-profile.yaml diff --git a/assets/terraform/examples/resources/panos_administrator/resource.tf b/assets/terraform/examples/resources/panos_administrator/resource.tf new file mode 100644 index 00000000..0df3024a --- /dev/null +++ b/assets/terraform/examples/resources/panos_administrator/resource.tf @@ -0,0 +1,13 @@ +resource "panos_administrator" "example" { + location = { + panorama = {} + } + name = "admin-user" + authentication_profile = "my-auth-profile" + + permissions = { + role_based = { + superuser = true + } + } +} diff --git a/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf b/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf index a2aa38e5..525e683b 100644 --- a/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf +++ b/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf @@ -22,7 +22,7 @@ resource "panos_custom_data_object" "example" { } } -resource "panos_data_filtering_profile" "example" { +resource "panos_data_filtering_security_profile" "example" { location = { device_group = panos_device_group.example.name } diff --git a/assets/terraform/examples/resources/panos_decryption_profile/resource.tf b/assets/terraform/examples/resources/panos_decryption_profile/resource.tf new file mode 100644 index 00000000..fc02c6cd --- /dev/null +++ b/assets/terraform/examples/resources/panos_decryption_profile/resource.tf @@ -0,0 +1,27 @@ +resource "panos_decryption_profile" "example" { + location = { + shared = {} + } + name = "my-decryption-profile" + description = "Example decryption profile" + + ssl_forward_proxy = { + block_expired_certificate = true + block_untrusted_issuer = true + block_unknown_cert = true + block_unsupported_version = true + block_unsupported_cipher = true + restrict_cert_exts = true + } + + ssl_protocol_settings = { + min_version = "tls1-2" + max_version = "max" + keyxchg_algo_rsa = true + keyxchg_algo_ecdhe = true + enc_algo_aes_128_gcm = true + enc_algo_aes_256_gcm = true + auth_algo_sha256 = true + auth_algo_sha384 = true + } +} diff --git a/assets/terraform/examples/resources/panos_email_server_profile/resource.tf b/assets/terraform/examples/resources/panos_email_server_profile/resource.tf index c9d7c115..eb45766e 100644 --- a/assets/terraform/examples/resources/panos_email_server_profile/resource.tf +++ b/assets/terraform/examples/resources/panos_email_server_profile/resource.tf @@ -1,50 +1,18 @@ -resource "panos_template" "example" { - location = { panorama = {} } - name = "example-template" -} - -# Email server profile forwarding security logs to a corporate SMTP relay -# with authenticated SMTP and custom log format strings. resource "panos_email_server_profile" "example" { - location = { - template = { - name = panos_template.example.name - } - } - - name = "security-alerts-email" - - servers = [ - { - name = "corporate-smtp" - display_name = "Corporate SMTP Relay" - from = "panos-alerts@corp.example.com" - to = "security-team@corp.example.com" - and_also_to = "noc@corp.example.com" - gateway = "smtp.corp.example.com" - protocol = "SMTP" - port = 587 - - # Use Login authentication with SMTP credentials - authentication_type = "Login" - username = "panos-svc" - password = "Str0ngP@ssw0rd!" - } - ] - - # Custom format strings for log types relevant to security operations. - # These override the default PAN-OS email log format. - format = { - traffic = "$receive_time,$serial,$type,$subtype,$src,$dst,$proto,$action" - threat = "$receive_time,$serial,$type,$subtype,$src,$dst,$threat_name,$severity" - system = "$receive_time,$serial,$type,$subtype,$severity,$opaque" - url = "$receive_time,$serial,$type,$subtype,$src,$dst,$url" - wildfire = "$receive_time,$serial,$type,$subtype,$src,$dst,$threat_name,$filetype" + location = { + vsys = { + name = "vsys1" + } + } + name = "my-email-server-profile" - # Escape backslashes and double-quotes in log field values - escaping = { - escape_character = "\\" - escaped_characters = "\"" - } - } + servers = [ + { + name = "email-server-1" + from = "panos@example.com" + to = "alerts@example.com" + gateway = "smtp.example.com" + port = 25 + } + ] } diff --git a/assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf b/assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf new file mode 100644 index 00000000..45c594b6 --- /dev/null +++ b/assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf @@ -0,0 +1,20 @@ +resource "panos_snmp_trap_profile" "example" { + location = { + vsys = { + name = "vsys1" + } + } + name = "my-snmp-trap-profile" + + version = { + v2c = { + servers = [ + { + name = "snmp-server-1" + manager = "192.0.2.1" + community = "public" + } + ] + } + } +} diff --git a/specs/device/profiles/email-server-profile.yaml b/specs/device/profiles/email-server-profile.yaml deleted file mode 100644 index 900ec7ab..00000000 --- a/specs/device/profiles/email-server-profile.yaml +++ /dev/null @@ -1,577 +0,0 @@ -name: email-server-profile -terraform_provider_config: - description: Email Server Profile - skip_resource: false - skip_datasource: false - resource_type: entry - resource_variants: - - singular - suffix: email_server_profile - plural_suffix: '' - plural_name: '' - plural_description: '' - custom_validation: false -go_sdk_config: - skip: false - package: - - device - - profiles - - email -panos_xpath: - path: - - log-settings - - email - vars: [] -locations: -- name: panorama - xpath: - path: - - config - - panorama - vars: [] - description: Located in a panorama. - 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 stack - 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 stack, device and vsys. - devices: - - panorama - - ngfw - validators: [] - required: false - read_only: false -entries: -- name: name - description: '' - validators: [] -spec: - params: - - name: server - type: list - profiles: - - xpath: - - server - - entry - type: entry - validators: [] - spec: - type: object - items: - type: object - spec: - params: - - name: from - type: string - profiles: - - xpath: - - from - validators: - - type: length - spec: - max: 128 - spec: {} - description: From email address - required: false - - name: to - type: string - profiles: - - xpath: - - to - validators: - - type: length - spec: - max: 128 - spec: {} - description: To email address - required: false - - name: and-also-to - type: string - profiles: - - xpath: - - and-also-to - validators: - - type: length - spec: - max: 128 - spec: {} - description: Additional CC email address - required: false - - name: gateway - type: string - profiles: - - xpath: - - gateway - validators: - - type: length - spec: - max: 63 - spec: {} - description: IP address or FQDN of SMTP gateway - required: false - - name: port - type: int64 - profiles: - - xpath: - - port - validators: - - type: length - spec: - min: 1 - max: 65535 - spec: - default: 25 - description: SMTP port number - required: false - - name: tls-version - type: enum - profiles: - - xpath: - - tls-version - validators: - - type: values - spec: - values: - - '1.0' - - '1.1' - - '1.2' - spec: - default: '1.2' - values: - - value: '1.0' - - value: '1.1' - - value: '1.2' - description: Minimum TLS version for SMTP connection - required: false - - name: auth - type: enum - profiles: - - xpath: - - auth - validators: - - type: values - spec: - values: - - Auto - - Login - - Plain - spec: - default: Auto - values: - - value: Auto - - value: Login - - value: Plain - description: Authentication method for SMTP - required: false - - name: certificate-profile - type: string - profiles: - - xpath: - - certificate-profile - validators: - - type: length - spec: - max: 255 - spec: {} - description: Certificate profile for TLS verification - required: false - variants: [] - description: List of email servers - required: false - codegen_overrides: - terraform: - name: servers - - name: format - type: object - profiles: - - xpath: - - format - validators: [] - spec: - params: - - name: auth - type: string - profiles: - - xpath: - - auth - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for auth log - required: false - - name: config - type: string - profiles: - - xpath: - - config - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for config log - required: false - - name: correlation - type: string - profiles: - - xpath: - - correlation - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for correlation log - required: false - - name: data - type: string - profiles: - - xpath: - - data - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for data log - required: false - - name: decryption - type: string - profiles: - - xpath: - - decryption - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for decryption log - required: false - - name: globalprotect - type: string - profiles: - - xpath: - - globalprotect - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for globalprotect log - required: false - - name: gtp - type: string - profiles: - - xpath: - - gtp - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for gtp log - required: false - - name: hip-match - type: string - profiles: - - xpath: - - hip-match - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for hip-match log - required: false - - name: iptag - type: string - profiles: - - xpath: - - iptag - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for iptag log - required: false - - name: sctp - type: string - profiles: - - xpath: - - sctp - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for sctp log - required: false - - name: system - type: string - profiles: - - xpath: - - system - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for system log - required: false - - name: threat - type: string - profiles: - - xpath: - - threat - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for threat log - required: false - - name: traffic - type: string - profiles: - - xpath: - - traffic - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for traffic log - required: false - - name: tunnel - type: string - profiles: - - xpath: - - tunnel - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for tunnel log - required: false - - name: url - type: string - profiles: - - xpath: - - url - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for url log - required: false - - name: userid - type: string - profiles: - - xpath: - - userid - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for userid log - required: false - - name: wildfire - type: string - profiles: - - xpath: - - wildfire - validators: - - type: length - spec: - max: 2048 - spec: {} - description: Custom format for wildfire log - required: false - variants: [] - description: Custom log format strings - required: false - variants: [] From 84a1757b5a09c8b498bf17ad7cd992b51c1886c5 Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Mon, 20 Apr 2026 11:07:11 +0530 Subject: [PATCH 03/10] ci: trigger workflow From eafbb5df9d04304d822072d8d1deab219741d0af Mon Sep 17 00:00:00 2001 From: Krzysztof Klimonda Date: Thu, 7 May 2026 09:49:39 +0200 Subject: [PATCH 04/10] feat(specs): Add specs, tests and examples for email, snmp and decryption profiles --- .../test/resource_decryption_profile_test.go | 478 ++++++++++++++ .../resource_email_server_profile_test.go | 226 ++++--- .../test/resource_snmptrap_profile_test.go | 619 ++++++++++++++++++ specs/device/profiles/email.yaml | 52 +- .../{snmp-trap-profile.yaml => snmptrap.yaml} | 99 +-- .../objects/profiles/decryption-profile.yaml | 299 ++++++--- 6 files changed, 1496 insertions(+), 277 deletions(-) create mode 100644 assets/terraform/test/resource_decryption_profile_test.go create mode 100644 assets/terraform/test/resource_snmptrap_profile_test.go rename specs/device/profiles/{snmp-trap-profile.yaml => snmptrap.yaml} (87%) diff --git a/assets/terraform/test/resource_decryption_profile_test.go b/assets/terraform/test/resource_decryption_profile_test.go new file mode 100644 index 00000000..90a62962 --- /dev/null +++ b/assets/terraform/test/resource_decryption_profile_test.go @@ -0,0 +1,478 @@ +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 TestAccDecryptionProfile_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{ + "device_group": 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: decryptionProfile_Basic_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("disable_override"), + knownvalue.StringExact("yes"), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("forwarded_only"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("interface"), + knownvalue.StringExact("ethernet1/1"), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_forward_proxy"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "auto_include_altname": knownvalue.Bool(true), + "block_client_cert": knownvalue.Bool(true), + "block_expired_certificate": knownvalue.Bool(true), + "block_if_hsm_unavailable": knownvalue.Bool(true), + "block_if_no_resource": knownvalue.Bool(true), + // block_if_sni_mismatch has version constraint (11.0.2-11.0.3) + "block_if_sni_mismatch": knownvalue.Bool(true), + "block_timeout_cert": knownvalue.Bool(true), + "block_tls13_downgrade_no_resource": knownvalue.Bool(true), + "block_unknown_cert": knownvalue.Bool(true), + "block_unsupported_cipher": knownvalue.Bool(true), + "block_unsupported_version": knownvalue.Bool(true), + "block_untrusted_issuer": knownvalue.Bool(true), + "restrict_cert_exts": knownvalue.Bool(true), + "strip_alpn": knownvalue.Bool(true), + }), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("min_version"), + knownvalue.StringExact("tls1-1"), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("max_version"), + knownvalue.StringExact("tls1-3"), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("auth_algo_sha256"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("enc_algo_aes_256_gcm"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("keyxchg_algo_ecdhe"), + knownvalue.Bool(true), + ), + }, + }, + }, + }) +} + +const decryptionProfile_Basic_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + disable_override = "yes" + forwarded_only = true + interface = "ethernet1/1" + ssl_forward_proxy = { + auto_include_altname = true + block_client_cert = true + block_expired_certificate = true + block_if_hsm_unavailable = true + block_if_no_resource = true + # block_if_sni_mismatch has version constraint (11.0.2-11.0.3) + block_if_sni_mismatch = true + block_timeout_cert = true + block_tls13_downgrade_no_resource = true + block_unknown_cert = true + block_unsupported_cipher = true + block_unsupported_version = true + block_untrusted_issuer = true + restrict_cert_exts = true + strip_alpn = true + } + ssl_protocol_settings = { + min_version = "tls1-1" + max_version = "tls1-3" + auth_algo_sha256 = true + enc_algo_aes_256_gcm = true + keyxchg_algo_ecdhe = true + } +} +` + +func TestAccDecryptionProfile_SshProxy(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{ + "device_group": 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: decryptionProfile_SshProxy_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssh_proxy"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "block_if_no_resource": knownvalue.Bool(true), + "block_ssh_errors": knownvalue.Bool(true), + "block_unsupported_alg": knownvalue.Bool(true), + "block_unsupported_version": knownvalue.Bool(true), + }), + ), + }, + }, + }, + }) +} + +const decryptionProfile_SshProxy_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + ssh_proxy = { + block_if_no_resource = true + block_ssh_errors = true + block_unsupported_alg = true + block_unsupported_version = true + } +} +` + +func TestAccDecryptionProfile_SslInboundProxy(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{ + "device_group": 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: decryptionProfile_SslInboundProxy_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_inbound_proxy"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "block_if_hsm_unavailable": knownvalue.Bool(true), + "block_if_no_resource": knownvalue.Bool(true), + "block_tls13_downgrade_no_resource": knownvalue.Bool(true), + "block_unsupported_cipher": knownvalue.Bool(true), + "block_unsupported_version": knownvalue.Bool(true), + }), + ), + }, + }, + }, + }) +} + +const decryptionProfile_SslInboundProxy_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + ssl_inbound_proxy = { + block_if_hsm_unavailable = true + block_if_no_resource = true + block_tls13_downgrade_no_resource = true + block_unsupported_cipher = true + block_unsupported_version = true + } +} +` + +func TestAccDecryptionProfile_SslNoProxy(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{ + "device_group": 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: decryptionProfile_SslNoProxy_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_no_proxy"), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "block_expired_certificate": knownvalue.Bool(true), + "block_untrusted_issuer": knownvalue.Bool(true), + }), + ), + }, + }, + }, + }) +} + +const decryptionProfile_SslNoProxy_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + ssl_no_proxy = { + block_expired_certificate = true + block_untrusted_issuer = true + } +} +` + +// --- Enum value coverage tests for ssl_protocol_settings min/max versions --- + +func TestAccDecryptionProfile_SslProtocolSettings_Versions(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{ + "device_group": 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: decryptionProfile_SslProtocolSettings_Versions_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("min_version"), + knownvalue.StringExact("tls1-0"), + ), + // "max" is the PR default — verify device accepts it + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("max_version"), + knownvalue.StringExact("max"), + ), + }, + }, + }, + }) +} + +const decryptionProfile_SslProtocolSettings_Versions_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + ssl_protocol_settings = { + min_version = "tls1-0" + max_version = "max" + } +} +` + +func TestAccDecryptionProfile_SslProtocolSettings_LegacyVersions(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{ + "device_group": 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: decryptionProfile_SslProtocolSettings_LegacyVersions_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("min_version"), + knownvalue.StringExact("sslv3"), + ), + statecheck.ExpectKnownValue( + "panos_decryption_profile.example", + tfjsonpath.New("ssl_protocol_settings").AtMapKey("max_version"), + knownvalue.StringExact("tls1-2"), + ), + }, + }, + }, + }) +} + +const decryptionProfile_SslProtocolSettings_LegacyVersions_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_device_group" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_decryption_profile" "example" { + depends_on = [panos_device_group.example] + location = var.location + name = var.prefix + ssl_protocol_settings = { + min_version = "sslv3" + max_version = "tls1-2" + } +} +` diff --git a/assets/terraform/test/resource_email_server_profile_test.go b/assets/terraform/test/resource_email_server_profile_test.go index 8b425c96..bda7d336 100644 --- a/assets/terraform/test/resource_email_server_profile_test.go +++ b/assets/terraform/test/resource_email_server_profile_test.go @@ -40,21 +40,77 @@ func TestAccEmailServerProfile_Basic(t *testing.T) { tfjsonpath.New("name"), knownvalue.StringExact(prefix), ), + // All 17 format log-type params statecheck.ExpectKnownValue( "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("traffic"), - knownvalue.StringExact("traffic-fmt"), + tfjsonpath.New("format").AtMapKey("auth"), + knownvalue.StringExact("auth-fmt"), ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("threat"), - knownvalue.StringExact("threat-fmt"), + tfjsonpath.New("format").AtMapKey("config"), + knownvalue.StringExact("config-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("correlation"), + knownvalue.StringExact("correlation-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("data"), + knownvalue.StringExact("data-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("decryption"), + knownvalue.StringExact("decryption-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("globalprotect"), + knownvalue.StringExact("globalprotect-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("gtp"), + knownvalue.StringExact("gtp-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("hip_match"), + knownvalue.StringExact("hip-match-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("iptag"), + knownvalue.StringExact("iptag-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("sctp"), + knownvalue.StringExact("sctp-fmt"), ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("format").AtMapKey("system"), knownvalue.StringExact("system-fmt"), ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("threat"), + knownvalue.StringExact("threat-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("traffic"), + knownvalue.StringExact("traffic-fmt"), + ), + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("format").AtMapKey("tunnel"), + knownvalue.StringExact("tunnel-fmt"), + ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("format").AtMapKey("url"), @@ -62,14 +118,15 @@ func TestAccEmailServerProfile_Basic(t *testing.T) { ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("data"), - knownvalue.StringExact("data-fmt"), + tfjsonpath.New("format").AtMapKey("userid"), + knownvalue.StringExact("userid-fmt"), ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("format").AtMapKey("wildfire"), knownvalue.StringExact("wildfire-fmt"), ), + // Escaping sub-object statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("format").AtMapKey("escaping").AtMapKey("escape_character"), @@ -80,6 +137,7 @@ func TestAccEmailServerProfile_Basic(t *testing.T) { tfjsonpath.New("format").AtMapKey("escaping").AtMapKey("escaped_characters"), knownvalue.StringExact(`'"`), ), + // Fully-parameterized SMTP server with credentials statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("name"), @@ -120,6 +178,12 @@ func TestAccEmailServerProfile_Basic(t *testing.T) { tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("port"), knownvalue.Int64Exact(587), ), + // tls_version defaults to "1.2" even for SMTP protocol + statecheck.ExpectKnownValue( + "panos_email_server_profile.example", + tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("tls_version"), + knownvalue.StringExact("1.2"), + ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("authentication_type"), @@ -163,12 +227,23 @@ resource "panos_email_server_profile" "example" { name = var.prefix format = { - traffic = "traffic-fmt" - threat = "threat-fmt" - system = "system-fmt" - url = "url-fmt" - data = "data-fmt" - wildfire = "wildfire-fmt" + auth = "auth-fmt" + config = "config-fmt" + correlation = "correlation-fmt" + data = "data-fmt" + decryption = "decryption-fmt" + globalprotect = "globalprotect-fmt" + gtp = "gtp-fmt" + hip_match = "hip-match-fmt" + iptag = "iptag-fmt" + sctp = "sctp-fmt" + system = "system-fmt" + threat = "threat-fmt" + traffic = "traffic-fmt" + tunnel = "tunnel-fmt" + url = "url-fmt" + userid = "userid-fmt" + wildfire = "wildfire-fmt" escaping = { escape_character = "\\" escaped_characters = "'\"" @@ -194,7 +269,7 @@ resource "panos_email_server_profile" "example" { } ` -func TestAccEmailServerProfile_TlsProtocol(t *testing.T) { +func TestAccEmailServerProfile_Protocol_TLS(t *testing.T) { t.Parallel() nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) @@ -211,7 +286,7 @@ func TestAccEmailServerProfile_TlsProtocol(t *testing.T) { ProtoV6ProviderFactories: testAccProviders, Steps: []resource.TestStep{ { - Config: emailServerProfile_TlsProtocol_Tmpl, + Config: emailServerProfile_Protocol_TLS_Tmpl, ConfigVariables: map[string]config.Variable{ "prefix": config.StringVariable(prefix), "location": location, @@ -253,7 +328,7 @@ func TestAccEmailServerProfile_TlsProtocol(t *testing.T) { }) } -const emailServerProfile_TlsProtocol_Tmpl = ` +const emailServerProfile_Protocol_TLS_Tmpl = ` variable "prefix" { type = string } variable "location" { type = any } @@ -392,7 +467,7 @@ resource "panos_email_server_profile" "example" { } ` -func TestAccEmailServerProfile_FormatOnly(t *testing.T) { +func TestAccEmailServerProfile_TlsVersion_1_0(t *testing.T) { t.Parallel() nameSuffix := acctest.RandStringFromCharSet(6, acctest.CharSetAlphaNum) @@ -409,7 +484,7 @@ func TestAccEmailServerProfile_FormatOnly(t *testing.T) { ProtoV6ProviderFactories: testAccProviders, Steps: []resource.TestStep{ { - Config: emailServerProfile_FormatOnly_Tmpl, + Config: emailServerProfile_TlsVersion_1_0_Tmpl, ConfigVariables: map[string]config.Variable{ "prefix": config.StringVariable(prefix), "location": location, @@ -422,88 +497,13 @@ func TestAccEmailServerProfile_FormatOnly(t *testing.T) { ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("auth"), - knownvalue.StringExact("auth-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("config"), - knownvalue.StringExact("config-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("correlation"), - knownvalue.StringExact("correlation-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("data"), - knownvalue.StringExact("data-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("decryption"), - knownvalue.StringExact("decryption-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("globalprotect"), - knownvalue.StringExact("globalprotect-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("gtp"), - knownvalue.StringExact("gtp-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("hip_match"), - knownvalue.StringExact("hip-match-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("iptag"), - knownvalue.StringExact("iptag-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("sctp"), - knownvalue.StringExact("sctp-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("system"), - knownvalue.StringExact("system-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("threat"), - knownvalue.StringExact("threat-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("traffic"), - knownvalue.StringExact("traffic-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("tunnel"), - knownvalue.StringExact("tunnel-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("url"), - knownvalue.StringExact("url-fmt"), - ), - statecheck.ExpectKnownValue( - "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("userid"), - knownvalue.StringExact("userid-fmt"), + tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("protocol"), + knownvalue.StringExact("TLS"), ), statecheck.ExpectKnownValue( "panos_email_server_profile.example", - tfjsonpath.New("format").AtMapKey("wildfire"), - knownvalue.StringExact("wildfire-fmt"), + tfjsonpath.New("servers").AtSliceIndex(0).AtMapKey("tls_version"), + knownvalue.StringExact("1.0"), ), }, }, @@ -511,7 +511,9 @@ func TestAccEmailServerProfile_FormatOnly(t *testing.T) { }) } -const emailServerProfile_FormatOnly_Tmpl = ` +// tls_version "1.0" is from the PR spec — not in the XML schema. +// This test verifies whether the device actually accepts it. +const emailServerProfile_TlsVersion_1_0_Tmpl = ` variable "prefix" { type = string } variable "location" { type = any } @@ -526,24 +528,16 @@ resource "panos_email_server_profile" "example" { name = var.prefix - format = { - auth = "auth-fmt" - config = "config-fmt" - correlation = "correlation-fmt" - data = "data-fmt" - decryption = "decryption-fmt" - globalprotect = "globalprotect-fmt" - gtp = "gtp-fmt" - hip_match = "hip-match-fmt" - iptag = "iptag-fmt" - sctp = "sctp-fmt" - system = "system-fmt" - threat = "threat-fmt" - traffic = "traffic-fmt" - tunnel = "tunnel-fmt" - url = "url-fmt" - userid = "userid-fmt" - wildfire = "wildfire-fmt" - } + servers = [ + { + name = "tls10-server" + from = "alerts@example.com" + to = "admin@example.com" + gateway = "smtp.example.com" + protocol = "TLS" + tls_version = "1.0" + port = 587 + } + ] } ` diff --git a/assets/terraform/test/resource_snmptrap_profile_test.go b/assets/terraform/test/resource_snmptrap_profile_test.go new file mode 100644 index 00000000..2557ab27 --- /dev/null +++ b/assets/terraform/test/resource_snmptrap_profile_test.go @@ -0,0 +1,619 @@ +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 TestAccSnmptrapProfile_Basic_V2c(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: snmptrapProfile_Basic_V2c_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(0).AtMapKey("name"), + knownvalue.StringExact("trap-v2c-1"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(0).AtMapKey("manager"), + knownvalue.StringExact("192.168.1.100"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(0).AtMapKey("community"), + knownvalue.StringExact("public"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(1).AtMapKey("name"), + knownvalue.StringExact("trap-v2c-2"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(1).AtMapKey("manager"), + knownvalue.StringExact("192.168.1.101"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v2c").AtMapKey("servers").AtSliceIndex(1).AtMapKey("community"), + knownvalue.StringExact("private"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_Basic_V2c_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v2c = { + servers = [ + { + name = "trap-v2c-1" + manager = "192.168.1.100" + community = "public" + }, + { + name = "trap-v2c-2" + manager = "192.168.1.101" + community = "private" + } + ] + } + } +} +` + +func TestAccSnmptrapProfile_Basic_V3(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: snmptrapProfile_Basic_V3_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + // First server: all params with non-default auth/priv protocols + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("name"), + knownvalue.StringExact("trap-v3-1"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("manager"), + knownvalue.StringExact("10.0.0.1"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("user"), + knownvalue.StringExact("snmpuser"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("engine_id"), + knownvalue.StringExact("0x80001F8880A1B2C3D4E5F601"), + ), + // authentication_password has hashing type solo - only check NotNull + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_password"), + knownvalue.NotNull(), + ), + // privacy_password has hashing type solo - only check NotNull + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("privacy_password"), + knownvalue.NotNull(), + ), + // Non-default auth protocol (SHA-256 instead of SHA) + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_protocol"), + knownvalue.StringExact("SHA-256"), + ), + // Non-default priv protocol (AES-192 instead of AES) + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("privacy_protocol"), + knownvalue.StringExact("AES-192"), + ), + // Second server: uses defaults for auth/priv protocols + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("name"), + knownvalue.StringExact("trap-v3-2"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("manager"), + knownvalue.StringExact("10.0.0.2"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("user"), + knownvalue.StringExact("snmpuser2"), + ), + // authentication_password has hashing type solo - only check NotNull + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("authentication_password"), + knownvalue.NotNull(), + ), + // privacy_password has hashing type solo - only check NotNull + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("privacy_password"), + knownvalue.NotNull(), + ), + // Default auth protocol (SHA) + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("authentication_protocol"), + knownvalue.StringExact("SHA"), + ), + // Default priv protocol (AES) + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(1).AtMapKey("privacy_protocol"), + knownvalue.StringExact("AES"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_Basic_V3_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "trap-v3-1" + manager = "10.0.0.1" + user = "snmpuser" + engine_id = "0x80001F8880A1B2C3D4E5F601" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + authentication_protocol = "SHA-256" + privacy_protocol = "AES-192" + }, + { + name = "trap-v3-2" + manager = "10.0.0.2" + user = "snmpuser2" + authentication_password = "AuthPassword2!" + privacy_password = "PrivPassword2!" + } + ] + } + } +} +` + +// --- Enum value coverage tests --- +// Each test exercises untested auth/priv protocol enum values. + +func TestAccSnmptrapProfile_V3_AuthProto_SHA224(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: snmptrapProfile_V3_AuthProto_SHA224_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_protocol"), + knownvalue.StringExact("SHA-224"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("privacy_protocol"), + knownvalue.StringExact("AES-256"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_V3_AuthProto_SHA224_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "sha224-server" + manager = "10.0.0.1" + user = "snmpuser" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + authentication_protocol = "SHA-224" + privacy_protocol = "AES-256" + } + ] + } + } +} +` + +func TestAccSnmptrapProfile_V3_AuthProto_SHA384(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: snmptrapProfile_V3_AuthProto_SHA384_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_protocol"), + knownvalue.StringExact("SHA-384"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_V3_AuthProto_SHA384_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "sha384-server" + manager = "10.0.0.1" + user = "snmpuser" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + authentication_protocol = "SHA-384" + } + ] + } + } +} +` + +func TestAccSnmptrapProfile_V3_AuthProto_SHA512(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: snmptrapProfile_V3_AuthProto_SHA512_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_protocol"), + knownvalue.StringExact("SHA-512"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_V3_AuthProto_SHA512_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "sha512-server" + manager = "10.0.0.1" + user = "snmpuser" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + authentication_protocol = "SHA-512" + } + ] + } + } +} +` + +// Legacy enum values from PR — not in our XML schema. +// These tests verify whether the device actually accepts MD5, DES, AES128. + +func TestAccSnmptrapProfile_V3_Legacy_MD5(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: snmptrapProfile_V3_Legacy_MD5_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("authentication_protocol"), + knownvalue.StringExact("MD5"), + ), + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("privacy_protocol"), + knownvalue.StringExact("DES"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_V3_Legacy_MD5_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "md5-server" + manager = "10.0.0.1" + user = "snmpuser" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + authentication_protocol = "MD5" + privacy_protocol = "DES" + } + ] + } + } +} +` + +func TestAccSnmptrapProfile_V3_Legacy_AES128(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: snmptrapProfile_V3_Legacy_AES128_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_snmptrap_profile.example", + tfjsonpath.New("version").AtMapKey("v3").AtMapKey("servers").AtSliceIndex(0).AtMapKey("privacy_protocol"), + knownvalue.StringExact("AES128"), + ), + }, + }, + }, + }) +} + +const snmptrapProfile_V3_Legacy_AES128_Tmpl = ` +variable "prefix" { type = string } +variable "location" { type = any } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_snmptrap_profile" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + + version = { + v3 = { + servers = [ + { + name = "aes128-server" + manager = "10.0.0.1" + user = "snmpuser" + authentication_password = "AuthPassword1!" + privacy_password = "PrivPassword1!" + privacy_protocol = "AES128" + } + ] + } + } +} +` diff --git a/specs/device/profiles/email.yaml b/specs/device/profiles/email.yaml index 80406970..5837d3f8 100644 --- a/specs/device/profiles/email.yaml +++ b/specs/device/profiles/email.yaml @@ -243,7 +243,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for auth log required: false - name: config type: string @@ -255,7 +255,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for config log required: false - name: correlation type: string @@ -267,7 +267,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for correlation log required: false - name: data type: string @@ -279,7 +279,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for data log required: false - name: decryption type: string @@ -291,7 +291,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for decryption log required: false - name: escaping type: object @@ -339,7 +339,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for globalprotect log required: false - name: gtp type: string @@ -351,7 +351,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for gtp log required: false - name: hip-match type: string @@ -363,7 +363,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for hip-match log required: false - name: iptag type: string @@ -375,7 +375,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for iptag log required: false - name: sctp type: string @@ -387,7 +387,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for sctp log required: false - name: system type: string @@ -399,7 +399,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for system log required: false - name: threat type: string @@ -411,7 +411,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for threat log required: false - name: traffic type: string @@ -423,7 +423,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for traffic log required: false - name: tunnel type: string @@ -435,7 +435,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for tunnel log required: false - name: url type: string @@ -447,7 +447,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for url log required: false - name: userid type: string @@ -459,7 +459,7 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for userid log required: false - name: wildfire type: string @@ -471,10 +471,10 @@ spec: spec: max: 2048 spec: {} - description: '' + description: Custom format for wildfire log required: false variants: [] - description: custom formats for forwarded logs + description: Custom log format strings required: false - name: server type: list @@ -509,7 +509,7 @@ spec: spec: max: 128 spec: {} - description: email address (e.g. admin@mycompany.com) + description: From email address required: false - name: to type: string @@ -521,7 +521,7 @@ spec: spec: max: 128 spec: {} - description: email address (e.g. admin@mycompany.com) + description: To email address required: false - name: and-also-to type: string @@ -533,7 +533,7 @@ spec: spec: max: 128 spec: {} - description: email address (e.g. admin@mycompany.com) + description: Additional CC email address required: false - name: gateway type: string @@ -545,7 +545,7 @@ spec: spec: max: 63 spec: {} - description: IP address or FQDN of SMTP gateway to use + description: IP address or FQDN of SMTP gateway required: false - name: protocol type: enum @@ -577,7 +577,7 @@ spec: max: 65535 spec: default: 25 - description: Port number (Standard EMAIL ports SMTP:25, TLS:587) + description: SMTP port number required: false - name: tls-version type: enum @@ -614,7 +614,7 @@ spec: - value: Auto - value: Login - value: Plain - description: '' + description: Authentication method for SMTP required: false codegen_overrides: terraform: @@ -627,7 +627,7 @@ spec: validators: [] spec: default: None - description: Certificate Profile for validating server certificate + description: Certificate profile for TLS verification required: false - name: username type: string @@ -658,7 +658,7 @@ spec: hashing: type: solo variants: [] - description: '' + description: List of email servers required: false codegen_overrides: terraform: diff --git a/specs/device/profiles/snmp-trap-profile.yaml b/specs/device/profiles/snmptrap.yaml similarity index 87% rename from specs/device/profiles/snmp-trap-profile.yaml rename to specs/device/profiles/snmptrap.yaml index 1ab2fda2..f07e4dfd 100644 --- a/specs/device/profiles/snmp-trap-profile.yaml +++ b/specs/device/profiles/snmptrap.yaml @@ -1,4 +1,4 @@ -name: snmp-trap-profile +name: snmptrap-profile terraform_provider_config: description: SNMP Trap Server Profile skip_resource: false @@ -6,7 +6,7 @@ terraform_provider_config: resource_type: entry resource_variants: - singular - suffix: snmp_trap_profile + suffix: snmptrap_profile plural_suffix: '' plural_name: '' plural_description: '' @@ -164,7 +164,7 @@ locations: required: true validators: [] type: entry - description: Located in a specific template stack + description: Located in a specific template devices: - panorama validators: [] @@ -212,7 +212,7 @@ locations: - value: shared 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 @@ -256,29 +256,26 @@ spec: type: object spec: params: - - name: community + - name: manager type: string profiles: - xpath: - - community - validators: - - type: length - spec: - max: 127 + - manager + validators: [] spec: {} - description: SNMP community string + description: IP address or FQDN of SNMP manager required: false - - name: manager + - name: community type: string profiles: - xpath: - - manager + - community validators: - type: length spec: - max: 63 + max: 127 spec: {} - description: IP address or FQDN of SNMP manager + description: SNMP community string required: false variants: [] description: List of SNMPv2c trap receivers @@ -311,42 +308,42 @@ spec: type: object spec: params: - - name: engineid + - name: manager type: string profiles: - xpath: - - engineid - validators: - - type: length - spec: - max: 255 + - manager + validators: [] spec: {} - description: SNMP engine ID (hex string, e.g. 0x80...) + description: IP address or FQDN of SNMP manager required: false - - name: manager + - name: user type: string profiles: - xpath: - - manager + - user validators: - type: length spec: - max: 63 + max: 31 spec: {} - description: IP address or FQDN of SNMP manager + description: SNMPv3 username required: false - - name: user + - name: engineid type: string profiles: - xpath: - - user + - engineid validators: - type: length spec: - max: 31 + max: 255 spec: {} - description: SNMPv3 username + description: SNMP engine ID (hex string, e.g. 0x80...) required: false + codegen_overrides: + terraform: + name: engine-id - name: authpwd type: string profiles: @@ -355,13 +352,16 @@ spec: validators: - type: length spec: - max: 255 + min: 8 + max: 256 spec: {} description: SNMPv3 authentication password required: false codegen_overrides: terraform: - sensitive: true + name: authentication-password + hashing: + type: solo - name: privpwd type: string profiles: @@ -370,13 +370,16 @@ spec: validators: - type: length spec: - max: 255 + min: 8 + max: 256 spec: {} description: SNMPv3 privacy password required: false codegen_overrides: terraform: - sensitive: true + name: privacy-password + hashing: + type: solo - name: authproto type: enum profiles: @@ -386,15 +389,24 @@ spec: - type: values spec: values: - - MD5 - SHA + - SHA-224 + - SHA-256 + - SHA-384 + - SHA-512 spec: default: SHA values: - - value: MD5 - value: SHA + - value: SHA-224 + - value: SHA-256 + - value: SHA-384 + - value: SHA-512 description: Authentication protocol required: false + codegen_overrides: + terraform: + name: authentication-protocol - name: privproto type: enum profiles: @@ -404,15 +416,20 @@ spec: - type: values spec: values: - - AES128 - - DES + - AES + - AES-192 + - AES-256 spec: - default: AES128 + default: AES values: - - value: AES128 - - value: DES + - value: AES + - value: AES-192 + - value: AES-256 description: Privacy protocol required: false + codegen_overrides: + terraform: + name: privacy-protocol variants: [] description: List of SNMPv3 trap receivers required: false diff --git a/specs/objects/profiles/decryption-profile.yaml b/specs/objects/profiles/decryption-profile.yaml index d5b93f29..8ce16461 100644 --- a/specs/objects/profiles/decryption-profile.yaml +++ b/specs/objects/profiles/decryption-profile.yaml @@ -107,17 +107,87 @@ entries: validators: [] spec: params: - - name: description - type: string + - name: disable-override + type: enum profiles: - xpath: - - description + - disable-override validators: - - type: length + - type: values spec: - min: 0 - max: 255 + values: + - 'yes' + - 'no' + spec: + default: 'no' + values: + - value: 'yes' + - value: 'no' + description: disable object override in child device groups + required: false + - name: forwarded-only + type: bool + profiles: + - xpath: + - forwarded-only + validators: [] + spec: {} + description: mirror after security policy allow + required: false + - name: interface + type: string + profiles: + - xpath: + - interface + validators: [] spec: {} + description: decrypt mirror port + required: false + - name: ssh-proxy + type: object + profiles: + - xpath: + - ssh-proxy + validators: [] + spec: + params: + - name: block-if-no-resource + type: bool + profiles: + - xpath: + - block-if-no-resource + validators: [] + spec: {} + description: whether to block sessions if device has no enough resources + required: false + - name: block-ssh-errors + type: bool + profiles: + - xpath: + - block-ssh-errors + validators: [] + spec: {} + description: whether to block sessions if ssh errors are encountered + required: false + - name: block-unsupported-alg + type: bool + profiles: + - xpath: + - block-unsupported-alg + validators: [] + spec: {} + description: whether to block sessions if ssh algorithm is not supported + required: false + - name: block-unsupported-version + type: bool + profiles: + - xpath: + - block-unsupported-version + validators: [] + spec: {} + description: whether to block sessions if ssh version is not supported + required: false + variants: [] description: '' required: false - name: ssl-forward-proxy @@ -135,7 +205,8 @@ spec: - auto-include-altname validators: [] spec: {} - description: Automatically include the alternative name of the certificate + description: whether to automatically append SAN to impersonating certificate + if server certificate is missing SAN required: false - name: block-client-cert type: bool @@ -155,6 +226,36 @@ spec: spec: {} description: Block sessions with expired certificates required: false + - name: block-if-hsm-unavailable + type: bool + profiles: + - xpath: + - block-if-hsm-unavailable + validators: [] + spec: {} + description: whether to block sessions if HSM is unavailable + required: false + - name: block-if-no-resource + type: bool + profiles: + - xpath: + - block-if-no-resource + validators: [] + spec: {} + description: whether to block sessions if device has no enough resources + required: false + - name: block-if-sni-mismatch + type: bool + profiles: + - xpath: + - block-if-sni-mismatch + min_version: 11.0.2 + max_version: 11.0.3 + validators: [] + spec: {} + description: whether to block a session when certificate's subject name or + SAN doesn't match SNI + required: false - name: block-timeout-cert type: bool profiles: @@ -162,7 +263,17 @@ spec: - block-timeout-cert validators: [] spec: {} - description: Block sessions if certificate status cannot be retrieved within timeout + description: Block sessions if certificate status cannot be retrieved within + timeout + required: false + - name: block-tls13-downgrade-no-resource + type: bool + profiles: + - xpath: + - block-tls13-downgrade-no-resource + validators: [] + spec: {} + description: whether to downgrade from tls1.3 if device has not enough resources required: false - name: block-unknown-cert type: bool @@ -200,15 +311,6 @@ spec: spec: {} description: Block sessions with untrusted certificate issuers required: false - - name: client-cert-auth - type: bool - profiles: - - xpath: - - client-cert-auth - validators: [] - spec: {} - description: Enable client certificate authentication - required: false - name: restrict-cert-exts type: bool profiles: @@ -238,50 +340,50 @@ spec: validators: [] spec: params: - - name: block-if-no-resource + - name: block-if-hsm-unavailable type: bool profiles: - xpath: - - block-if-no-resource + - block-if-hsm-unavailable validators: [] spec: {} - description: Block sessions when decryption resources are not available + description: Block sessions when HSM is unavailable required: false - - name: block-unsupported-cipher + - name: block-if-no-resource type: bool profiles: - xpath: - - block-unsupported-cipher + - block-if-no-resource validators: [] spec: {} - description: Block sessions with unsupported cipher suites + description: Block sessions when decryption resources are not available required: false - - name: block-unsupported-version + - name: block-tls13-downgrade-no-resource type: bool profiles: - xpath: - - block-unsupported-version + - block-tls13-downgrade-no-resource validators: [] spec: {} - description: Block sessions with unsupported protocol versions + description: Block TLS 1.3 downgrade when no resources are available required: false - - name: block-if-hsm-unavailable + - name: block-unsupported-cipher type: bool profiles: - xpath: - - block-if-hsm-unavailable + - block-unsupported-cipher validators: [] spec: {} - description: Block sessions when HSM is unavailable + description: Block sessions with unsupported cipher suites required: false - - name: block-tls13-downgrade-no-resource + - name: block-unsupported-version type: bool profiles: - xpath: - - block-tls13-downgrade-no-resource + - block-unsupported-version validators: [] spec: {} - description: Block TLS 1.3 downgrade when no resources are available + description: Block sessions with unsupported protocol versions required: false variants: [] description: SSL inbound proxy decryption settings @@ -323,56 +425,6 @@ spec: validators: [] spec: params: - - name: min-version - type: enum - profiles: - - xpath: - - min-version - validators: - - type: values - spec: - values: - - sslv3 - - tls1-0 - - tls1-1 - - tls1-2 - - tls1-3 - spec: - default: tls1-0 - values: - - value: sslv3 - - value: tls1-0 - - value: tls1-1 - - value: tls1-2 - - value: tls1-3 - description: Minimum SSL/TLS protocol version - required: false - - name: max-version - type: enum - profiles: - - xpath: - - max-version - validators: - - type: values - spec: - values: - - sslv3 - - tls1-0 - - tls1-1 - - tls1-2 - - tls1-3 - - max - spec: - default: max - values: - - value: sslv3 - - value: tls1-0 - - value: tls1-1 - - value: tls1-2 - - value: tls1-3 - - value: max - description: Maximum SSL/TLS protocol version - required: false - name: auth-algo-md5 type: bool profiles: @@ -418,23 +470,23 @@ spec: spec: {} description: Allow 3DES encryption algorithm required: false - - name: enc-algo-rc4 + - name: enc-algo-aes-128-cbc type: bool profiles: - xpath: - - enc-algo-rc4 + - enc-algo-aes-128-cbc validators: [] spec: {} - description: Allow RC4 encryption algorithm + description: Allow AES-128-CBC encryption algorithm required: false - - name: enc-algo-aes-128-cbc + - name: enc-algo-aes-128-gcm type: bool profiles: - xpath: - - enc-algo-aes-128-cbc + - enc-algo-aes-128-gcm validators: [] spec: {} - description: Allow AES-128-CBC encryption algorithm + description: Allow AES-128-GCM encryption algorithm required: false - name: enc-algo-aes-256-cbc type: bool @@ -445,23 +497,32 @@ spec: spec: {} description: Allow AES-256-CBC encryption algorithm required: false - - name: enc-algo-aes-128-gcm + - name: enc-algo-aes-256-gcm type: bool profiles: - xpath: - - enc-algo-aes-128-gcm + - enc-algo-aes-256-gcm validators: [] spec: {} - description: Allow AES-128-GCM encryption algorithm + description: Allow AES-256-GCM encryption algorithm required: false - - name: enc-algo-aes-256-gcm + - name: enc-algo-chacha20-poly1305 type: bool profiles: - xpath: - - enc-algo-aes-256-gcm + - enc-algo-chacha20-poly1305 validators: [] spec: {} - description: Allow AES-256-GCM encryption algorithm + description: Allow algorithm chacha20-poly1305 + required: false + - name: enc-algo-rc4 + type: bool + profiles: + - xpath: + - enc-algo-rc4 + validators: [] + spec: {} + description: Allow RC4 encryption algorithm required: false - name: keyxchg-algo-dhe type: bool @@ -490,6 +551,56 @@ spec: spec: {} description: Allow RSA key exchange algorithm required: false + - name: max-version + type: enum + profiles: + - xpath: + - max-version + validators: + - type: values + spec: + values: + - sslv3 + - tls1-0 + - tls1-1 + - tls1-2 + - tls1-3 + - max + spec: + default: tls1-2 + values: + - value: sslv3 + - value: tls1-0 + - value: tls1-1 + - value: tls1-2 + - value: tls1-3 + - value: max + description: Maximum SSL/TLS protocol version + required: false + - name: min-version + type: enum + profiles: + - xpath: + - min-version + validators: + - type: values + spec: + values: + - sslv3 + - tls1-0 + - tls1-1 + - tls1-2 + - tls1-3 + spec: + default: tls1-0 + values: + - value: sslv3 + - value: tls1-0 + - value: tls1-1 + - value: tls1-2 + - value: tls1-3 + description: Minimum SSL/TLS protocol version + required: false variants: [] description: SSL/TLS protocol settings required: false From 9ff9465114a1b65c5ff6e9475a73abca696e5a97 Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Wed, 20 May 2026 15:05:04 +0530 Subject: [PATCH 05/10] fix(specs): Remove sslv3 from decryption profile ssl-protocol-settings sslv3 is rejected by PAN-OS 11.2.8 with 'not an allowed keyword' for both min-version and max-version fields. Confirmed via acceptance tests. Co-Authored-By: Claude Sonnet 4.6 --- specs/objects/profiles/decryption-profile.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/specs/objects/profiles/decryption-profile.yaml b/specs/objects/profiles/decryption-profile.yaml index 8ce16461..c2f1dfe0 100644 --- a/specs/objects/profiles/decryption-profile.yaml +++ b/specs/objects/profiles/decryption-profile.yaml @@ -560,7 +560,6 @@ spec: - type: values spec: values: - - sslv3 - tls1-0 - tls1-1 - tls1-2 @@ -569,7 +568,6 @@ spec: spec: default: tls1-2 values: - - value: sslv3 - value: tls1-0 - value: tls1-1 - value: tls1-2 @@ -586,7 +584,6 @@ spec: - type: values spec: values: - - sslv3 - tls1-0 - tls1-1 - tls1-2 @@ -594,7 +591,6 @@ spec: spec: default: tls1-0 values: - - value: sslv3 - value: tls1-0 - value: tls1-1 - value: tls1-2 From 5e18c0cb5e44fbf5c18a4bcafad0f507e4d1b285 Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Wed, 20 May 2026 15:41:42 +0530 Subject: [PATCH 06/10] fix(specs): Revert data-filtering profile rename and remove unverified locations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert suffix back to data_filtering_profile to match what was already merged on main - Remove vsys, template, and template-stack locations — cannot be verified from actual Panorama config; only shared and device-group are confirmed Co-Authored-By: Claude Sonnet 4.6 --- .../panos_data_filtering_profile/resource.tf | 2 +- specs/device/profiles/data-filtering.yaml | 190 +----------------- 2 files changed, 3 insertions(+), 189 deletions(-) diff --git a/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf b/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf index 525e683b..a2aa38e5 100644 --- a/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf +++ b/assets/terraform/examples/resources/panos_data_filtering_profile/resource.tf @@ -22,7 +22,7 @@ resource "panos_custom_data_object" "example" { } } -resource "panos_data_filtering_security_profile" "example" { +resource "panos_data_filtering_profile" "example" { location = { device_group = panos_device_group.example.name } diff --git a/specs/device/profiles/data-filtering.yaml b/specs/device/profiles/data-filtering.yaml index 165758ca..99e3f9b5 100644 --- a/specs/device/profiles/data-filtering.yaml +++ b/specs/device/profiles/data-filtering.yaml @@ -1,12 +1,12 @@ name: data-filtering-profile terraform_provider_config: - description: Data Filtering Security Profile + description: Data Filtering Profile skip_resource: false skip_datasource: false resource_type: entry resource_variants: - singular - suffix: data_filtering_security_profile + suffix: data_filtering_profile plural_suffix: '' plural_name: '' plural_description: '' @@ -36,38 +36,6 @@ locations: 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: device-group xpath: path: @@ -101,160 +69,6 @@ locations: 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 stack - 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 stack, device and vsys. - devices: - - panorama - - ngfw - validators: [] - required: false - read_only: false entries: - name: name description: '' From 929c2ff5876977fd15755af2bc79d0a31339d0a0 Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Wed, 20 May 2026 16:45:55 +0530 Subject: [PATCH 07/10] fix(examples): Remove unsupported description field from decryption profile example Co-Authored-By: Claude Sonnet 4.6 --- .../examples/resources/panos_decryption_profile/resource.tf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assets/terraform/examples/resources/panos_decryption_profile/resource.tf b/assets/terraform/examples/resources/panos_decryption_profile/resource.tf index fc02c6cd..119278ee 100644 --- a/assets/terraform/examples/resources/panos_decryption_profile/resource.tf +++ b/assets/terraform/examples/resources/panos_decryption_profile/resource.tf @@ -2,8 +2,7 @@ resource "panos_decryption_profile" "example" { location = { shared = {} } - name = "my-decryption-profile" - description = "Example decryption profile" + name = "my-decryption-profile" ssl_forward_proxy = { block_expired_certificate = true From 8b8207177cb6f650ecb9c3c4f79f0009e272a43f Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Wed, 20 May 2026 16:55:10 +0530 Subject: [PATCH 08/10] fix(examples): Rename snmp trap profile example to match generated resource type Co-Authored-By: Claude Sonnet 4.6 --- .../resource.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename assets/terraform/examples/resources/{panos_snmp_trap_profile => panos_snmptrap_profile}/resource.tf (83%) diff --git a/assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf b/assets/terraform/examples/resources/panos_snmptrap_profile/resource.tf similarity index 83% rename from assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf rename to assets/terraform/examples/resources/panos_snmptrap_profile/resource.tf index 45c594b6..713e7346 100644 --- a/assets/terraform/examples/resources/panos_snmp_trap_profile/resource.tf +++ b/assets/terraform/examples/resources/panos_snmptrap_profile/resource.tf @@ -1,4 +1,4 @@ -resource "panos_snmp_trap_profile" "example" { +resource "panos_snmptrap_profile" "example" { location = { vsys = { name = "vsys1" From b2392833bed18b4604c1f5102a24648204942a9e Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Fri, 22 May 2026 16:24:54 +0530 Subject: [PATCH 09/10] feat(specs): Pull administrator spec and tests updates from reviewer branch Updates administrator.yaml to use client-side hashing for password field and adds comprehensive acceptance tests for administrator resource. Co-Authored-By: Claude Sonnet 4.6 --- .../test/resource_administrators_test.go | 1003 +++++++++++++++++ specs/device/administrator.yaml | 805 +++++++++++-- 2 files changed, 1736 insertions(+), 72 deletions(-) create mode 100644 assets/terraform/test/resource_administrators_test.go diff --git a/assets/terraform/test/resource_administrators_test.go b/assets/terraform/test/resource_administrators_test.go new file mode 100644 index 00000000..2f226ca5 --- /dev/null +++ b/assets/terraform/test/resource_administrators_test.go @@ -0,0 +1,1003 @@ +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 TestAccAdministrator_Password_Hashing(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: panosAdministrators_Password_Hashing_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + "password": config.StringVariable("initial"), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("password"), + knownvalue.StringExact("initial"), + ), + }, + }, + { + Config: panosAdministrators_Password_Hashing_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + "password": config.StringVariable("updated"), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("password"), + knownvalue.StringExact("updated"), + ), + }, + }, + }, + }) +} + +const panosAdministrators_Password_Hashing_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } +variable "password" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = { panorama = {} } + + name = var.prefix + + password = var.password +} +` + +func TestAccAdministrator_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: panosAdministrators_Basic_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("name"), + knownvalue.StringExact(prefix), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("client_certificate_only"), + knownvalue.Bool(false), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("disable_dns"), + knownvalue.Bool(true), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("traffic").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Example Query"), + "query": knownvalue.StringExact("addr.src in 10.0.0.0/8"), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrators_Basic_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + + name = var.prefix + password = "admin123" + + client_certificate_only = false + + preferences = { + disable_dns = true + saved_log_query = { + traffic = [ + { + name = "Example Query" + query = "addr.src in 10.0.0.0/8" + } + ] + } + } +} +` + +func TestAccAdministrator_RoleBased_Custom(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: panosAdministrators_RoleBased_Custom_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("custom").AtMapKey("profile"), + knownvalue.StringExact(prefix), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_Custom_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_admin_role" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + role = { + vsys = { + cli = "vsysreader" + } + } +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + custom = { + profile = panos_admin_role.example.name + } + } + } +} +` + +func TestAccAdministrator_RoleBased_DeviceAdmin(t *testing.T) { + t.Parallel() + t.Skip("requires valid device references") + + 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: panosAdministrators_RoleBased_DeviceAdmin_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("device_admins"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("device1"), + knownvalue.StringExact("device2"), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_DeviceAdmin_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + device_admins = ["device1", "device2"] + } + } +} +` + +func TestAccAdministrator_RoleBased_DeviceReader(t *testing.T) { + t.Parallel() + t.Skip("requires valid device references") + + 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: panosAdministrators_RoleBased_DeviceReader_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("devicereader"), + knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("device1"), + knownvalue.StringExact("device2"), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_DeviceReader_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + devicereader = ["device1", "device2"] + } + } +} +` + +func TestAccAdministrator_RoleBased_PanoramaAdmin(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: panosAdministrators_RoleBased_PanoramaAdmin_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("panorama_admin"), + knownvalue.StringExact("yes"), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_PanoramaAdmin_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + panorama_admin = "yes" + } + } +} +` + +func TestAccAdministrator_RoleBased_SuperReader(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: panosAdministrators_RoleBased_SuperReader_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("superreader"), + knownvalue.StringExact("yes"), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_SuperReader_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + superreader = "yes" + } + } +} +` + +func TestAccAdministrator_RoleBased_SuperUser(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: panosAdministrators_RoleBased_SuperUser_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("superuser"), + knownvalue.StringExact("yes"), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_SuperUser_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" example { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + superuser = "yes" + } + } +} +` + +func TestAccAdministrator_RoleBased_VsysAdmin(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: panosAdministrators_RoleBased_VsysAdmin_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("vsys_admins").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("localhost.localdomain"), + "vsys": knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("vsys1"), + }), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_VsysAdmin_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = { template = { name = "test-tmpl-commit" } } + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + vsys_admins = [ + { + name = "localhost.localdomain" + vsys = ["vsys1"] + } + ] + } + } +} +` + +func TestAccAdministrator_RoleBased_VsysReader(t *testing.T) { + t.Parallel() + t.Skip("requires valid device references") + + 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: panosAdministrators_RoleBased_VsysReader_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("permissions").AtMapKey("role_based").AtMapKey("vsys_readers").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("localhost.localdomain"), + "vsys": knownvalue.ListExact([]knownvalue.Check{ + knownvalue.StringExact("vsys1"), + }), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrators_RoleBased_VsysReader_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + + name = var.prefix +} + + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + permissions = { + role_based = { + vsys_readers = [ + { + name = "localhost.localdomain" + vsys = ["vsys1"] + } + ] + } + } +} +` + +func TestAccAdministrator_AuthenticationProfile(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: panosAdministrator_AuthenticationProfile_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("authentication_profile"), + knownvalue.StringExact("auth-profile"), + ), + }, + }, + }, + }) +} + +const panosAdministrator_AuthenticationProfile_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_authentication_profile" "auth_profile" { + depends_on = [panos_template.example] + location = var.location + name = "auth-profile" + user_domain = "example.com" +} + +resource "panos_administrator" "example" { + depends_on = [panos_authentication_profile.auth_profile] + location = var.location + name = var.prefix + password = "admin123" + + authentication_profile = panos_authentication_profile.auth_profile.name +} +` + +func TestAccAdministrator_PasswordProfile(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: panosAdministrator_PasswordProfile_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("password_profile"), + knownvalue.StringExact("password-profile"), + ), + }, + }, + }, + }) +} + +const panosAdministrator_PasswordProfile_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_password_profile" "pwd_profile" { + depends_on = [panos_template.example] + location = var.location + name = "password-profile" + + password_change = { + expiration_period = 90 + expiration_warning_period = 7 + post_expiration_admin_login_count = 3 + post_expiration_grace_period = 5 + } +} + +resource "panos_administrator" "example" { + depends_on = [panos_password_profile.pwd_profile] + location = var.location + name = var.prefix + password = "admin123" + + password_profile = panos_password_profile.pwd_profile.name +} +` + +func TestAccAdministrator_PublicKey(t *testing.T) { + t.Parallel() + t.Skip("requires valid SSH public key") + + 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), + }), + }) + + publicKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKqKT5TZ3Z example@example.com" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testAccProviders, + Steps: []resource.TestStep{ + { + Config: panosAdministrator_PublicKey_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + "public_key": config.StringVariable(publicKey), + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("public_key"), + knownvalue.StringExact(publicKey), + ), + }, + }, + }, + }) +} + +const panosAdministrator_PublicKey_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } +variable "public_key" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + public_key = var.public_key +} +` + +func TestAccAdministrator_Preferences_SavedLogQuery(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: panosAdministrator_Preferences_SavedLogQuery_Tmpl, + ConfigVariables: map[string]config.Variable{ + "prefix": config.StringVariable(prefix), + "location": location, + }, + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("alarm").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Alarm Query"), + "query": knownvalue.StringExact("severity eq critical"), + }), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("auth").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Auth Query"), + "query": knownvalue.StringExact("( authproto eq 'RADIUS' )"), + }), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("config").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Config Query"), + "query": knownvalue.StringExact("( cmd eq 'set' )"), + }), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("threat").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Threat Query"), + "query": knownvalue.StringExact("severity eq high"), + }), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("decryption").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("Decryption Query"), + "query": knownvalue.StringExact("( policy_name eq 'SSL-Decrypt' )"), + }), + ), + statecheck.ExpectKnownValue( + "panos_administrator.example", + tfjsonpath.New("preferences").AtMapKey("saved_log_query").AtMapKey("system").AtSliceIndex(0), + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "name": knownvalue.StringExact("System Query"), + "query": knownvalue.StringExact("( eventid eq 'general' )"), + }), + ), + }, + }, + }, + }) +} + +const panosAdministrator_Preferences_SavedLogQuery_Tmpl = ` +variable "location" { type = any } +variable "prefix" { type = string } + +resource "panos_template" "example" { + location = { panorama = {} } + name = var.prefix +} + +resource "panos_administrator" "example" { + depends_on = [panos_template.example] + location = var.location + name = var.prefix + password = "admin123" + + preferences = { + saved_log_query = { + alarm = [ + { + name = "Alarm Query" + query = "severity eq critical" + } + ] + auth = [ + { + name = "Auth Query" + query = "( authproto eq 'RADIUS' )" + } + ] + config = [ + { + name = "Config Query" + query = "( cmd eq 'set' )" + } + ] + threat = [ + { + name = "Threat Query" + query = "severity eq high" + } + ] + decryption = [ + { + name = "Decryption Query" + query = "( policy_name eq 'SSL-Decrypt' )" + } + ] + system = [ + { + name = "System Query" + query = "( eventid eq 'general' )" + } + ] + } + } +} +` diff --git a/specs/device/administrator.yaml b/specs/device/administrator.yaml index 305a7e5a..c6302f13 100644 --- a/specs/device/administrator.yaml +++ b/specs/device/administrator.yaml @@ -1,10 +1,11 @@ name: administrator terraform_provider_config: - description: Administrator Account + description: Administrator skip_resource: false skip_datasource: false resource_type: entry - resource_variants: [] + resource_variants: + - singular suffix: administrator plural_suffix: '' plural_name: '' @@ -17,7 +18,6 @@ go_sdk_config: - administrator panos_xpath: path: - - mgt-config - users vars: [] locations: @@ -25,10 +25,21 @@ locations: xpath: path: - config + - mgt-config vars: [] - description: Panorama administrator + description: Located in panorama. + validators: [] + required: false + read_only: false +- name: ngfw + xpath: + path: + - config + - mgt-config + vars: [] + description: Located within device-level configuration devices: - - panorama + - ngfw validators: [] required: false read_only: false @@ -41,6 +52,7 @@ locations: - template - $template - config + - mgt-config vars: - name: panorama_device description: Specific Panorama device @@ -53,7 +65,7 @@ locations: required: true validators: [] type: entry - description: Administrator pushed via a Panorama template + description: A management configuration object located within a specific template devices: - panorama validators: [] @@ -68,6 +80,7 @@ locations: - template-stack - $template_stack - config + - mgt-config vars: - name: panorama_device description: Specific Panorama device @@ -80,7 +93,7 @@ locations: required: true validators: [] type: entry - description: Administrator pushed via a Panorama template stack + description: A management configuration object located within a specific template devices: - panorama validators: [] @@ -97,40 +110,28 @@ spec: profiles: - xpath: - authentication-profile - validators: - - type: length - spec: - max: 255 + validators: [] spec: {} description: Authentication profile for this administrator required: false - - name: public-key - type: string + - name: client-certificate-only + type: bool profiles: - xpath: - - public-key - validators: - - type: length - spec: - max: 4096 + - client-certificate-only + validators: [] spec: {} - description: SSH public key for certificate-based authentication + description: Is client certificate authentication enough? required: false - - name: phash + - name: password-profile type: string profiles: - xpath: - - phash + - password-profile validators: [] spec: {} - description: Hashed administrator password + description: '' required: false - codegen_overrides: - terraform: - name: password - sensitive: true - hashing: - type: solo - name: permissions type: object profiles: @@ -138,7 +139,8 @@ spec: - permissions validators: [] spec: - params: + params: [] + variants: - name: role-based type: object profiles: @@ -146,88 +148,747 @@ spec: - role-based validators: [] spec: - params: - - name: superuser - type: bool - profiles: - - xpath: - - superuser - validators: [] - spec: {} - description: Full system access - required: false - - name: superreader - type: bool + params: [] + variants: + - name: custom + type: object profiles: - xpath: - - superreader + - custom validators: [] - spec: {} - description: Read-only access to entire system + spec: + params: + - name: profile + type: string + profiles: + - xpath: + - profile + validators: + - type: length + spec: + max: 63 + spec: {} + description: Custom admin role profile name + required: false + - name: vsys + type: list + profiles: + - xpath: + - vsys + type: member + validators: [] + spec: + type: string + items: + type: string + description: '' + required: false + variants: [] + description: Custom role based on an admin role profile required: false - name: deviceadmin - type: bool + type: list profiles: - xpath: - deviceadmin + type: member validators: [] - spec: {} + spec: + type: string + items: + type: string description: Device administrator access (all vsys) required: false + codegen_overrides: + terraform: + name: device_admins - name: devicereader - type: bool + type: list profiles: - xpath: - devicereader + type: member validators: [] - spec: {} + spec: + type: string + items: + type: string description: Device read-only access (all vsys) required: false + codegen_overrides: + terraform: + name: device_readers + - name: panorama-admin + type: enum + profiles: + - xpath: + - panorama-admin + validators: + - type: values + spec: + values: + - 'yes' + spec: + values: + - value: 'yes' + description: '' + required: false + - name: superreader + type: enum + profiles: + - xpath: + - superreader + validators: + - type: values + spec: + values: + - 'yes' + spec: + values: + - value: 'yes' + description: Read-only access to entire system + required: false + - name: superuser + type: enum + profiles: + - xpath: + - superuser + validators: + - type: values + spec: + values: + - 'yes' + spec: + values: + - value: 'yes' + description: Full system access + required: false - name: vsysadmin - type: bool + type: list profiles: - xpath: - vsysadmin + - entry + type: entry validators: [] - spec: {} + spec: + type: object + items: + type: object + spec: + params: + - name: vsys + type: list + profiles: + - xpath: + - vsys + type: member + validators: [] + spec: + type: string + items: + type: string + description: '' + required: false + variants: [] description: Virtual system administrator access required: false + codegen_overrides: + terraform: + name: vsys_admins - name: vsysreader - type: bool + type: list profiles: - xpath: - vsysreader + - entry + type: entry validators: [] - spec: {} + spec: + type: object + items: + type: object + spec: + params: + - name: vsys + type: list + profiles: + - xpath: + - vsys + type: member + validators: [] + spec: + type: string + items: + type: string + description: '' + required: false + variants: [] description: Virtual system read-only access required: false - - name: custom - type: object + codegen_overrides: + terraform: + name: vsys_readers + variant_check: Disabled + description: Role-based access control + required: false + description: Administrator permissions and role assignment + required: false + - name: phash + type: string + profiles: + - xpath: + - phash + validators: + - type: length + spec: + max: 63 + spec: {} + description: Hashed administrator password + required: false + codegen_overrides: + terraform: + name: password + hashing: + type: client + spec: + hashing_func: + name: administratorCreatePasswordHash + - name: preferences + type: object + profiles: + - xpath: + - preferences + validators: [] + spec: + params: + - name: disable-dns + type: bool + profiles: + - xpath: + - disable-dns + validators: [] + spec: {} + description: '' + required: false + - name: saved-log-query + type: object + profiles: + - xpath: + - saved-log-query + validators: [] + spec: + params: + - name: alarm + type: list profiles: - xpath: - - custom + - alarm + - entry + type: entry validators: [] spec: - params: - - name: profile - type: string - profiles: - - xpath: - - profile - validators: - - type: length - spec: - max: 255 - spec: {} - description: Custom admin role profile name - required: false - variants: [] - description: Custom role based on an admin role profile + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: auth + type: list + profiles: + - xpath: + - auth + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: config + type: list + profiles: + - xpath: + - config + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: corr + type: list + profiles: + - xpath: + - corr + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: data + type: list + profiles: + - xpath: + - data + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: decryption + type: list + profiles: + - xpath: + - decryption + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: globalprotect + type: list + profiles: + - xpath: + - globalprotect + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: gtp + type: list + profiles: + - xpath: + - gtp + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: hipmatch + type: list + profiles: + - xpath: + - hipmatch + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: system + type: list + profiles: + - xpath: + - system + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: threat + type: list + profiles: + - xpath: + - threat + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: traffic + type: list + profiles: + - xpath: + - traffic + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: tunnel + type: list + profiles: + - xpath: + - tunnel + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: unified + type: list + profiles: + - xpath: + - unified + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: url + type: list + profiles: + - xpath: + - url + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: userid + type: list + profiles: + - xpath: + - userid + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' + required: false + - name: wildfire + type: list + profiles: + - xpath: + - wildfire + - entry + type: entry + validators: [] + spec: + type: object + items: + type: object + spec: + params: + - name: query + type: string + profiles: + - xpath: + - query + validators: + - type: length + spec: + max: 2048 + spec: {} + description: '' + required: false + variants: [] + description: '' required: false variants: [] - description: Role-based access control + description: '' required: false variants: [] - description: Administrator permissions and role assignment + description: '' + required: false + - name: public-key + type: string + profiles: + - xpath: + - public-key + validators: + - type: length + spec: + min: 1 + max: 4096 + spec: {} + description: SSH public key for certificate-based authentication required: false variants: [] From 905edcbd24e95b6ca7c3f40921e944628be0d2af Mon Sep 17 00:00:00 2001 From: repl-dheeraj-v Date: Fri, 22 May 2026 16:50:20 +0530 Subject: [PATCH 10/10] feat(provider): Add administrator custom password hashing implementation Co-Authored-By: Claude Sonnet 4.6 --- .../internal/provider/administrator_custom.go | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 assets/terraform/internal/provider/administrator_custom.go diff --git a/assets/terraform/internal/provider/administrator_custom.go b/assets/terraform/internal/provider/administrator_custom.go new file mode 100644 index 00000000..cd944746 --- /dev/null +++ b/assets/terraform/internal/provider/administrator_custom.go @@ -0,0 +1,11 @@ +package provider + +import ( + "context" + + "github.com/PaloAltoNetworks/pango/util" +) + +func administratorCreatePasswordHash(ctx context.Context, client util.PangoClient, password string) (string, error) { + return client.RequestPasswordHash(ctx, password) +}