diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 96fc4fe1..4c09066b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -207,75 +207,75 @@ jobs: cmd/inext discard go test --timeout 20m -v -cover ./internal/resources/tests/ cmd/inext discard - test-preprod: - name: Test PreProd - needs: build - environment: - name: PreProd - url: https://q.portal.checkpoint.com - runs-on: ubuntu-latest - timeout-minutes: 100 - concurrency: acctests-${{ github.event_name }}-preprod - strategy: - max-parallel: 1 - fail-fast: true - matrix: - # list whatever Terraform versions here you would like to support - terraform: - - '0.13.*' - - '0.14.*' - - '0.15.*' - - '1.0.*' - - '1.1.*' - steps: - - name: Set up Go - uses: actions/setup-go@v3 - with: - go-version: '1.18' - id: go - - - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: ${{ matrix.terraform }} - terraform_wrapper: false - - - name: Check out code into the Go module directory - uses: actions/checkout@v3 - - - name: Get dependencies - run: | - go mod download - - - name: Build CLI - run: | - cd cmd - go build -o inext -v . - - - name: TF acceptance tests push - if: ${{ github.event_name == 'push' }} - timeout-minutes: 20 - env: - INEXT_CLIENT_ID: ${{ secrets.INEXT_CLIENT_ID_PUSH }} - INEXT_ACCESS_KEY: ${{ secrets.INEXT_ACCESS_KEY_PUSH }} - INEXT_REGION: preprod - TF_ACC: "1" - run: | - cmd/inext discard - go test --timeout 20m -v -cover ./internal/resources/tests/ - cmd/inext discard - - - name: TF acceptance tests pull request - if: ${{ github.event_name == 'pull_request' }} - timeout-minutes: 20 - env: - INEXT_CLIENT_ID: ${{ secrets.INEXT_CLIENT_ID_PR }} - INEXT_ACCESS_KEY: ${{ secrets.INEXT_ACCESS_KEY_PR }} - INEXT_REGION: preprod - TF_ACC: "1" - run: | - cmd/inext discard - go test --timeout 20m -v -cover ./internal/resources/tests/ - cmd/inext discard +# test-preprod: +# name: Test PreProd +# needs: build +# environment: +# name: PreProd +# url: https://q.portal.checkpoint.com +# runs-on: ubuntu-latest +# timeout-minutes: 100 +# concurrency: acctests-${{ github.event_name }}-preprod +# strategy: +# max-parallel: 1 +# fail-fast: true +# matrix: +# # list whatever Terraform versions here you would like to support +# terraform: +# - '0.13.*' +# - '0.14.*' +# - '0.15.*' +# - '1.0.*' +# - '1.1.*' +# steps: +# - name: Set up Go +# uses: actions/setup-go@v3 +# with: +# go-version: '1.18' +# id: go +# +# - uses: hashicorp/setup-terraform@v2 +# with: +# terraform_version: ${{ matrix.terraform }} +# terraform_wrapper: false +# +# - name: Check out code into the Go module directory +# uses: actions/checkout@v3 +# +# - name: Get dependencies +# run: | +# go mod download +# +# - name: Build CLI +# run: | +# cd cmd +# go build -o inext -v . +# +# - name: TF acceptance tests push +# if: ${{ github.event_name == 'push' }} +# timeout-minutes: 20 +# env: +# INEXT_CLIENT_ID: ${{ secrets.INEXT_CLIENT_ID_PUSH }} +# INEXT_ACCESS_KEY: ${{ secrets.INEXT_ACCESS_KEY_PUSH }} +# INEXT_REGION: preprod +# TF_ACC: "1" +# run: | +# cmd/inext discard +# go test --timeout 20m -v -cover ./internal/resources/tests/ +# cmd/inext discard +# +# - name: TF acceptance tests pull request +# if: ${{ github.event_name == 'pull_request' }} +# timeout-minutes: 20 +# env: +# INEXT_CLIENT_ID: ${{ secrets.INEXT_CLIENT_ID_PR }} +# INEXT_ACCESS_KEY: ${{ secrets.INEXT_ACCESS_KEY_PR }} +# INEXT_REGION: preprod +# TF_ACC: "1" +# run: | +# cmd/inext discard +# go test --timeout 20m -v -cover ./internal/resources/tests/ +# cmd/inext discard # - name: TF acceptance tests schedule # if: ${{ github.event_name == 'schedule' }} diff --git a/docs/resources/inext_appsec_gateway_profile.md b/docs/resources/inext_appsec_gateway_profile.md index ef4b68ef..e8d6482a 100644 --- a/docs/resources/inext_appsec_gateway_profile.md +++ b/docs/resources/inext_appsec_gateway_profile.md @@ -3,12 +3,12 @@ page_title: "inext_appsec_gateway_profile Resource - terraform-provider-infinity-next" subcategory: "" description: |- - CloudGuard Application Security Gateway profile is deployed as a VM that runs on a Check Point Gaia OS with a reverse proxy and Check Point Nano-Agent + CloudGuard Application Security Gateway profile is deployed as a VM that runs on a Check Point Gaia OS with a reverse proxy and Check Point Nano-Agent. --- # inext_appsec_gateway_profile (Resource) -CloudGuard Application Security Gateway profile is deployed as a VM that runs on a Check Point Gaia OS with a reverse proxy and Check Point Nano-Agent +CloudGuard Application Security Gateway profile is deployed as a VM that runs on a Check Point Gaia OS with a reverse proxy and Check Point Nano-Agent. ## Example Usage @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -65,9 +65,10 @@ resource "inext_appsec_gateway_profile" "my-appsec-gateway-profile" { - `reverseproxy_upstream_timeout` (Number) Sets the reverse proxy upstream timeout in seconds - `upgrade_mode` (String) The upgrade mode of the profile: Automatic, Manual or Scheduled. The default is Automatic +- `upgrade_time_days` (Set of Number) The days of the month of the upgrade time schedule - `upgrade_time_duration` (Number) The duration of the upgrade in hours - `upgrade_time_hour` (String) The hour of the upgrade time start, for example: 10:00 or 20:00 -- `upgrade_time_schedule_type` (String) The schedule type in case upgrade mode is scheduled: DaysInWeek +- `upgrade_time_schedule_type` (String) The schedule type in case upgrade mode is scheduled: DaysInWeek, DaysInMonth or Daily - `upgrade_time_week_days` (Set of String) The week days of the upgrade time schedule: Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ### Read-Only diff --git a/docs/resources/inext_docker_profile.md b/docs/resources/inext_docker_profile.md index 7eedd64b..21be6e3c 100644 --- a/docs/resources/inext_docker_profile.md +++ b/docs/resources/inext_docker_profile.md @@ -16,8 +16,8 @@ Docker profile terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } diff --git a/docs/resources/inext_embedded_profile.md b/docs/resources/inext_embedded_profile.md index 3f183356..38106df8 100644 --- a/docs/resources/inext_embedded_profile.md +++ b/docs/resources/inext_embedded_profile.md @@ -16,8 +16,8 @@ Embedded profile terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } @@ -58,9 +58,10 @@ resource "inext_embedded_profile" "my-embedded-profile" { - `max_number_of_agents` (Number) Sets the maximum number of agents that can be connected to this profile - `upgrade_mode` (String) The upgrade mode of the profile: Automatic, Manual or Scheduled. The default is Automatic +- `upgrade_time_days` (Set of Number) The days of the month of the upgrade time schedule - `upgrade_time_duration` (Number) The duration of the upgrade in hours - `upgrade_time_hour` (String) The hour of the upgrade time start, for example: 10:00 or 20:00 -- `upgrade_time_schedule_type` (String) The schedule type in case upgrade mode is scheduled: DaysInWeek +- `upgrade_time_schedule_type` (String) The schedule type in case upgrade mode is scheduled: DaysInWeek, DaysInMonth or Daily - `upgrade_time_week_days` (Set of String) The week days of the upgrade time schedule: Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday ### Read-Only diff --git a/docs/resources/inext_exceptions.md b/docs/resources/inext_exceptions.md index 0bb25805..87bcb0bf 100644 --- a/docs/resources/inext_exceptions.md +++ b/docs/resources/inext_exceptions.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "~>1.1.1" } } } @@ -62,6 +62,7 @@ resource "inext_exceptions" "my-exceptions-behavior" { ### Optional - `exception` (Block Set) Overrides AppSec ML engine decision based on match and action (see [below for nested schema](#nestedblock--exception)) +- `visibility` (String) The visibility of the exception: Shared or Local ### Read-Only diff --git a/docs/resources/inext_kubernetes_profile.md b/docs/resources/inext_kubernetes_profile.md index 1df10ad2..56821230 100644 --- a/docs/resources/inext_kubernetes_profile.md +++ b/docs/resources/inext_kubernetes_profile.md @@ -16,8 +16,8 @@ Kubernetes profile terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } @@ -46,7 +46,7 @@ resource "inext_kubernetes_profile" "my-kubernetes-profile" { ### Required - `name` (String) The name of the resource, also acts as its unique ID -- `profile_sub_type` (String) +- `profile_sub_type` (String) The sub type of the profile (AppSec, AccessControl, Kong, Istio) ### Optional diff --git a/docs/resources/inext_log_trigger.md b/docs/resources/inext_log_trigger.md index cd97b96c..e2dfb6a2 100644 --- a/docs/resources/inext_log_trigger.md +++ b/docs/resources/inext_log_trigger.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "~>1.1.1" } } } @@ -47,9 +47,11 @@ resource "inext_log_trigger" "mytrigger" { log_to_cef = false cef_ip_address = "10.0.0.1" cef_port_num = 2000 + cef_protocol = "TCP" # enum of ["TCP", "UDP"] log_to_cloud = true log_to_syslog = true syslog_ip_address = "10.10.10.10" + syslog_protocol = "TCP" # enum of ["TCP", "UDP"] syslog_port_num = 5004 compliance_violations = true compliance_warnings = true @@ -70,6 +72,9 @@ resource "inext_log_trigger" "mytrigger" { - `access_control_drop_events` (Boolean) Log Access Control drops - `cef_ip_address` (String) - `cef_port` (Number) +- `cef_protocol` (String) CEF protocol: UDP or TCP +- `compliance_violations` (Boolean) +- `compliance_warnings` (Boolean) - `extend_logging` (Boolean) - `extend_logging_min_severity` (String) Minimum severity of events that will trigger extended logging: High or Critical - `log_to_agent` (Boolean) @@ -80,6 +85,7 @@ resource "inext_log_trigger" "mytrigger" { - `response_code` (Boolean) Add response code to log if true - `syslog_ip_address` (String) - `syslog_port` (Number) +- `syslog_protocol` (String) Syslog protocol: UDP or TCP - `threat_prevention_detect_events` (Boolean) Log Threat Prevention Prevents - `threat_prevention_prevent_events` (Boolean) Log Threat Prevention Detects - `verbosity` (String) The verbosity of the log: Standard, Minimal or Extended diff --git a/docs/resources/inext_trusted_sources.md b/docs/resources/inext_trusted_sources.md index aa7153a7..b72e03c4 100644 --- a/docs/resources/inext_trusted_sources.md +++ b/docs/resources/inext_trusted_sources.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -30,6 +30,7 @@ provider "inext" { resource "inext_trusted_sources" "my-trusted-source-behavior" { name = "some name" + visibility = "Shared" min_num_of_sources = 1 sources_identifiers = ["identifier1", "identifier2"] } @@ -46,6 +47,7 @@ resource "inext_trusted_sources" "my-trusted-source-behavior" { ### Optional - `sources_identifiers` (Set of String) The trusted sources identifier values +- `visibility` (String) The visibility of the resource - Shared or Local ### Read-Only diff --git a/docs/resources/inext_web_api_asset.md b/docs/resources/inext_web_api_asset.md index c057eeb7..ffa5d0c6 100644 --- a/docs/resources/inext_web_api_asset.md +++ b/docs/resources/inext_web_api_asset.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -29,11 +29,11 @@ provider "inext" { } resource "inext_web_api_asset" "my-webapi-asset" { - name = "some name" - profiles = [inext_appsec_gateway_profile.my-appsec-gateway-profile.id, inext_docker_profile.my-docker-profile.id, inext_embedded_profile.my-embedded-profile.id, inext_kubernetes_profile.my-kubernetes-profile.id] - trusted_sources = [inext_trusted_sources.my-trusted-source-behavior.id] - upstream_url = "some url" - urls = ["some url"] + name = "some name" + profiles = [inext_appsec_gateway_profile.my-appsec-gateway-profile.id, inext_docker_profile.my-docker-profile.id, inext_embedded_profile.my-embedded-profile.id, inext_kubernetes_profile.my-kubernetes-profile.id] + behaviors = [inext_trusted_sources.my-trusted-source-behavior.id, inext_exceptions.my-exceptions-behavior.id] + upstream_url = "some url" + urls = ["some url"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -41,9 +41,8 @@ resource "inext_web_api_asset" "my-webapi-asset" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_api_practice.my-webapi-practice.id # required - triggers = [inext_log_trigger.mytrigger.id] - exceptions = [inext_exceptions.my-exceptions-behavior.id] + id = inext_web_api_practice.my-webapi-practice.id # required + triggers = [inext_log_trigger.mytrigger.id] } proxy_setting { key = "some key" @@ -53,6 +52,17 @@ resource "inext_web_api_asset" "my-webapi-asset" { identifier = "XForwardedFor" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value1", "value2"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = "cert data" + type = "client" + enable = true + } } ``` @@ -66,12 +76,14 @@ resource "inext_web_api_asset" "my-webapi-asset" { ### Optional +- `behaviors` (Set of String) behaviors used by the asset +- `mtls` (Block Set) The MTLS settings (see [below for nested schema](#nestedblock--mtls)) - `practice` (Block Set) The practices used by the asset (see [below for nested schema](#nestedblock--practice)) - `profiles` (Set of String) Profiles linked to the asset - `proxy_setting` (Block Set) Settings for the proxy (see [below for nested schema](#nestedblock--proxy_setting)) -- `source_identifier` (Block Set) Defines how the source identifier valuess of the asset are retrieved (see [below for nested schema](#nestedblock--source_identifier)) +- `source_identifier` (Block Set) Defines how the source identifier values of the asset are retrieved (see [below for nested schema](#nestedblock--source_identifier)) - `state` (String) -- `trusted_sources` (Set of String) Trusted sources behavior used by the asset +- `tags` (Block Set) The tags used by the asset (see [below for nested schema](#nestedblock--tags)) - `upstream_url` (String) The URL of the application's backend server to which the reverse proxy redirects the relevant traffic sent to the exposed URL ### Read-Only @@ -83,6 +95,7 @@ resource "inext_web_api_asset" "my-webapi-asset" { - `group` (String) - `id` (String, Sensitive) The ID of this resource. - `intelligence_tags` (String) +- `is_shares_urls` (Boolean) - `kind` (String) - `main_attributes` (String) - `order` (String) @@ -90,6 +103,27 @@ resource "inext_web_api_asset" "my-webapi-asset" { - `sources` (String) - `urls_ids` (Set of String) + +### Nested Schema for `mtls` + +Required: + +- `type` (String) The type of the mTLS - server or client + +Optional: + +- `certificate_type` (String) The type of the certificate file - .pem, .crt, .der, .p12, .pfx, .p7b, .p7c, .cer +- `data` (String, Sensitive) The certificate data +- `enable` (Boolean) Whether the mTLS is enabled +- `filename` (String) The name of the certificate file + +Read-Only: + +- `data_id` (String) +- `enable_id` (String) +- `filename_id` (String) + + ### Nested Schema for `practice` @@ -100,7 +134,6 @@ Required: Optional: -- `exceptions` (Set of String) The exceptions used with the practice - `practice_wrapper_id` (String) - `sub_practices_modes` (Map of String) The name of the sub practice as the key and its mode as the value. Allowed modes: Detect, Prevent, Inactive, AccordingToPractice, Disabled, Learn or Active - `triggers` (Set of String) The triggers used with the practice @@ -124,7 +157,7 @@ Read-Only: Optional: -- `identifier` (String) The identifier of the source: SourceIP, XForwardedFor, HeaderKey or Cookie +- `identifier` (String) The identifier of the source: SourceIP, XForwardedFor, HeaderKey, Cookie or JWTKey - `values` (Set of String) Read-Only: @@ -133,3 +166,16 @@ Read-Only: - `values_ids` (Set of String) + +### Nested Schema for `tags` + +Required: + +- `key` (String) +- `value` (String) + +Read-Only: + +- `id` (String) The ID of this resource. + + diff --git a/docs/resources/inext_web_api_practice.md b/docs/resources/inext_web_api_practice.md index e8d172aa..01c6f9a3 100644 --- a/docs/resources/inext_web_api_practice.md +++ b/docs/resources/inext_web_api_practice.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -29,14 +29,15 @@ provider "inext" { } resource "inext_web_api_practice" "my-webapi-practice" { - name = "some name" + name = "some name" + visibility = "Shared" # enum of ["Shared", "Local"] ips { - performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] - severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] - protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Prevent" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive"] + performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } api_attacks { minimum_severity = "Critical" # enum of ["Critical", "High", "Medium"] @@ -52,6 +53,23 @@ resource "inext_web_api_practice" "my-webapi-practice" { filename = basename(data.local_file.schema_validation_file.filename) data = data.local_file.schema_validation_file.content } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } ``` @@ -65,8 +83,10 @@ resource "inext_web_api_practice" "my-webapi-practice" { ### Optional - `api_attacks` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--api_attacks)) +- `file_security` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--file_security)) - `ips` (Block Set, Max: 1) IPS protection (see [below for nested schema](#nestedblock--ips)) - `schema_validation` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--schema_validation)) +- `visibility` (String) The visibility of the resource, Shared or Local ### Read-Only @@ -104,15 +124,41 @@ Read-Only: + +### Nested Schema for `file_security` + +Optional: + +- `allow_an_unopened_archive` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_archive_within_archive` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_file_size_limit` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_file_type` (Boolean) +- `archive_file_size_limit` (Number) +- `archive_file_size_limit_unit` (String) Bytes, KB, MB or GB +- `file_size_limit` (Number) +- `file_size_limit_unit` (String) Bytes, KB, MB or GB +- `files_without_name` (String) Detect, Prevent, Inactive or AccordingToPractice +- `high_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `low_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `medium_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `required_archive_extraction` (Boolean) +- `required_threat_emulation` (Boolean) +- `severity_level` (String) LowOrAbove, MediumOrAbove, HighOrAbove or Critical + +Read-Only: + +- `id` (String) The ID of this resource. + + ### Nested Schema for `ips` Optional: -- `high_confidence` (String) Detect, Prevent or Inactive -- `low_confidence` (String) Detect, Prevent or Inactive -- `medium_confidence` (String) Detect, Prevent or Inactive -- `performance_impact` (String) The performance impact: LowOrLower, MediumOrLower or HighOrLower +- `high_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `low_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `medium_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `performance_impact` (String) The performance impact: VeryLow, LowOrLower, MediumOrLower or HighOrLower - `protections_from_year` (String) The year to apply protections from: 1999, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 - `severity_level` (String) The severity level: LowOrAbove, MediumOrAbove, HighOrAbove or Critical @@ -127,7 +173,12 @@ Read-Only: Required: - `data` (String, Sensitive) -- `filename` (String) +- `name` (String) + +Optional: + +- `is_file_exist` (Boolean) +- `size` (Number) Read-Only: diff --git a/docs/resources/inext_web_app_asset.md b/docs/resources/inext_web_app_asset.md index cf6855b8..a121b24d 100644 --- a/docs/resources/inext_web_app_asset.md +++ b/docs/resources/inext_web_app_asset.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -52,6 +52,17 @@ resource "inext_web_app_asset" "my-webapp-asset" { identifier = "HeaderKey" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = " cert data" + type = "client" + enable = true + } } ``` @@ -66,10 +77,13 @@ resource "inext_web_app_asset" "my-webapp-asset" { ### Optional - `behaviors` (Set of String) behaviors used by the asset +- `mtls` (Block Set) The mutual TLS settings (see [below for nested schema](#nestedblock--mtls)) - `practice` (Block Set) The practices used by the asset (see [below for nested schema](#nestedblock--practice)) - `profiles` (Set of String) Profiles linked to the asset - `proxy_setting` (Block Set) Settings for the proxy (see [below for nested schema](#nestedblock--proxy_setting)) -- `source_identifier` (Block Set) Defines how the source identifier valuess of the asset are retrieved (see [below for nested schema](#nestedblock--source_identifier)) +- `source_identifier` (Block Set) Defines how the source identifier values of the asset are retrieved (see [below for nested schema](#nestedblock--source_identifier)) +- `state` (String) +- `tags` (Block Set) The tags used by the asset (see [below for nested schema](#nestedblock--tags)) - `upstream_url` (String) The URL of the application's backend server to which the reverse proxy redirects the relevant traffic sent to the exposed URL ### Read-Only @@ -81,6 +95,7 @@ resource "inext_web_app_asset" "my-webapp-asset" { - `group` (String) - `id` (String, Sensitive) The ID of this resource. - `intelligence_tags` (String) +- `is_shares_urls` (Boolean) - `kind` (String) - `main_attributes` (String) - `order` (String) @@ -88,6 +103,27 @@ resource "inext_web_app_asset" "my-webapp-asset" { - `sources` (String) - `urls_ids` (Set of String) + +### Nested Schema for `mtls` + +Required: + +- `type` (String) The type of the mTLS - server or client + +Optional: + +- `certificate_type` (String) The type of the certificate file - .pem, .crt, .der, .p12, .pfx, .p7b, .p7c, .cer +- `data` (String, Sensitive) The certificate data +- `enable` (Boolean) Whether the mTLS is enabled +- `filename` (String) The name of the certificate file + +Read-Only: + +- `data_id` (String) +- `enable_id` (String) +- `filename_id` (String) + + ### Nested Schema for `practice` @@ -124,7 +160,7 @@ Read-Only: Optional: -- `identifier` (String) The identifier of the source: SourceIP, XForwardedFor, HeaderKey or Cookie +- `identifier` (String) The identifier of the source: SourceIP, XForwardedFor, HeaderKey Cookie or JWTKey - `values` (Set of String) Read-Only: @@ -133,3 +169,16 @@ Read-Only: - `values_ids` (Set of String) + +### Nested Schema for `tags` + +Required: + +- `key` (String) +- `value` (String) + +Read-Only: + +- `id` (String) The ID of this resource. + + diff --git a/docs/resources/inext_web_app_practice.md b/docs/resources/inext_web_app_practice.md index b79c509e..1d8af12c 100644 --- a/docs/resources/inext_web_app_practice.md +++ b/docs/resources/inext_web_app_practice.md @@ -17,7 +17,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -29,14 +29,15 @@ provider "inext" { } resource "inext_web_app_practice" "my-webapp-practice" { - name = "some name" + name = "some name" + visibility = "Shared" # enum of ["Shared", "Local"] ips { performance_impact = "VeryLow" # enum of ["VeryLow", "LowOrLower", "MediumOrLower", "HighOrLower"] severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] + high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } web_attacks { minimum_severity = "Critical" # enum of ["Critical", "High", "Medium"] @@ -55,6 +56,23 @@ resource "inext_web_app_practice" "my-webapp-practice" { inject_uris = ["url1", "url2"] valid_uris = ["url1", "url2"] } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } ``` @@ -67,7 +85,9 @@ resource "inext_web_app_practice" "my-webapp-practice" { ### Optional +- `file_security` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--file_security)) - `ips` (Block Set, Max: 1) IPS protection (see [below for nested schema](#nestedblock--ips)) +- `visibility` (String) The visibility of the resource, Shared or Local - `web_attacks` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--web_attacks)) - `web_bot` (Block Set, Max: 1) (see [below for nested schema](#nestedblock--web_bot)) @@ -78,16 +98,42 @@ resource "inext_web_app_practice" "my-webapp-practice" { - `id` (String) The ID of this resource. - `practice_type` (String) + +### Nested Schema for `file_security` + +Optional: + +- `allow_an_unopened_archive` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_archive_within_archive` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_file_size_limit` (String) Detect, Prevent, Inactive or AccordingToPractice +- `allow_file_type` (Boolean) +- `archive_file_size_limit` (Number) +- `archive_file_size_limit_unit` (String) Bytes, KB, MB or GB +- `file_size_limit` (Number) +- `file_size_limit_unit` (String) Bytes, KB, MB or GB +- `files_without_name` (String) Detect, Prevent, Inactive or AccordingToPractice +- `high_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `low_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `medium_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `required_archive_extraction` (Boolean) +- `required_threat_emulation` (Boolean) +- `severity_level` (String) LowOrAbove, MediumOrAbove, HighOrAbove or Critical + +Read-Only: + +- `id` (String) The ID of this resource. + + ### Nested Schema for `ips` Optional: -- `high_confidence` (String) Detect, Prevent or Inactive +- `high_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice - `id` (String) The ID of this resource. -- `low_confidence` (String) Detect, Prevent or Inactive -- `medium_confidence` (String) Detect, Prevent or Inactive -- `performance_impact` (String) The performance impact: LowOrLower, MediumOrLower or HighOrLower +- `low_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `medium_confidence` (String) Detect, Prevent, Inactive or AccordingToPractice +- `performance_impact` (String) The performance impact: VeryLow, LowOrLower, MediumOrLower or HighOrLower - `protections_from_year` (String) The year to apply protections from: 1999, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 - `severity_level` (String) The severity level: LowOrAbove, MediumOrAbove, HighOrAbove or Critical diff --git a/docs/resources/inext_web_user_response.md b/docs/resources/inext_web_user_response.md index eaf8c27f..1d95ea3b 100644 --- a/docs/resources/inext_web_user_response.md +++ b/docs/resources/inext_web_user_response.md @@ -13,8 +13,24 @@ Determine the response returned to the client who initiated a blocked traffic.Th ## Example Usage ```terraform +terraform { + required_providers { + inext = { + source = "CheckPointSW/infinity-next" + version = "1.1.1" + } + } +} + +provider "inext" { + region = "eu" + # client_id = "" // can be set with env var INEXT_CLIENT_ID + # access_key = "" // can be set with env var INEXT_ACCESS_KEY +} + resource "inext_web_user_response" "web-user-response-blockpage" { name = "web-user-response" + visibility = "Shared" # enum of ["Shared", "Local"] mode = "BlockPage" http_response_code = 403 message_title = "some message title" @@ -49,6 +65,7 @@ resource "inext_web_user_response" "web-user-response-responsecodeonly" { - `message_body` (String) The body of the message to be shown to the user - `message_title` (String) The title of the web page to be shown to the user sending the malicious traffic - `redirect_url` (String) The client will be redirected to the provided URL where you can provide any customized web page +- `visibility` (String) The visibility of the web user response object - `x_event_id` (Boolean) When selected the redirect message will include this header with a value that provides an internal reference ID that will match a security log generated by the incident, if log triggers are configured ### Read-Only diff --git a/examples/appsec/appsec.tf b/examples/appsec/appsec.tf index fd02ca4e..68efeb67 100644 --- a/examples/appsec/appsec.tf +++ b/examples/appsec/appsec.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -29,7 +29,6 @@ resource "inext_web_app_asset" "prod_eu_acme" { } id = inext_web_app_practice.eu_acme_protection.id # required triggers = [inext_log_trigger.log_trigger.id] - } source_identifier { identifier = "HeaderKey" diff --git a/examples/provider/appsec-gateway-profile.tf b/examples/provider/appsec-gateway-profile.tf index 5795fbf6..5a7b0015 100644 --- a/examples/provider/appsec-gateway-profile.tf +++ b/examples/provider/appsec-gateway-profile.tf @@ -36,4 +36,24 @@ resource "inext_appsec_gateway_profile" "test" { Key1 = "Value1" Key2 = "Value2" } +} + +resource "inext_appsec_gateway_profile" "test3" { + name = "inext_appsec_gateway_profile-test3" + profile_sub_type = "Aws" # enum of ["Aws", "Azure", "VMware", "HyperV"] + upgrade_mode = "Automatic" # enum of ["Automatic", "Manual", "Scheduled"] + upgrade_time_schedule_type = "DaysInMonth" # enum of ["DaysInMonth", "DaysInWeek", "Daily"] + upgrade_time_hour = "12:00" + upgrade_time_duration = 10 + upgrade_time_days = [1, 2, 3, 4, 5, 6, 7] + reverseproxy_upstream_timeout = 3600 + reverseproxy_additional_settings = { + Key3 = "Value5" + Key4 = "Value4" + } + max_number_of_agents = 100 + additional_settings = { + Key1 = "Value1" + Key2 = "Value2" + } } \ No newline at end of file diff --git a/examples/provider/log-trigger.tf b/examples/provider/log-trigger.tf index 224b08fc..dd148e8d 100644 --- a/examples/provider/log-trigger.tf +++ b/examples/provider/log-trigger.tf @@ -1,10 +1,13 @@ resource "inext_log_trigger" "test" { name = "inext_log_trigger-test3" verbosity = "Extended" # enum of ["Minimal", "Standard", "Extended"] + compliance_violations = true + compliance_warnings = true access_control_allow_events = true access_control_drop_events = true cef_ip_address = "10.0.0.1" cef_port = 81 + cef_protocol = "TCP" # enum of ["TCP", "UDP"] extend_logging = true extend_logging_min_severity = "Critical" # enum of ["High", "Critical"] log_to_agent = true @@ -14,6 +17,7 @@ resource "inext_log_trigger" "test" { response_body = true response_code = true syslog_ip_address = "10.0.0.2" + sys_log_protocol = "TCP" # enum of ["TCP", "UDP"] syslog_port = 82 threat_prevention_detect_events = true threat_prevention_prevent_events = true diff --git a/examples/provider/web-api-asset.tf b/examples/provider/web-api-asset.tf index b6072ff9..fd180ef0 100644 --- a/examples/provider/web-api-asset.tf +++ b/examples/provider/web-api-asset.tf @@ -1,19 +1,19 @@ resource "inext_web_api_asset" "test" { - name = "inext_web_api_asset-test1" - profiles = [inext_appsec_gateway_profile.test2.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url 5" - urls = ["http://host5/path"] + name = "inext_web_api_asset-test1" + profiles = [inext_appsec_gateway_profile.test2.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url 5" + urls = ["http://host5/path"] practice { main_mode = "Prevent" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { - IPS = "AccordingToPractice" - WebBot = "AccordingToPractice" - Snort = "Disabled" + IPS = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] + WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] + Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] + } - id = inext_web_api_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_api_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { @@ -29,15 +29,30 @@ resource "inext_web_api_asset" "test" { value = "last value" } source_identifier { - identifier = "SourceIP" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] + identifier = "SourceIP" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie", "JWTKey"] values = ["value3"] } source_identifier { - identifier = "XForwardedFor" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] + identifier = "XForwardedFor" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie", "JWTKey"] values = ["value2"] } source_identifier { - identifier = "HeaderKey" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] + identifier = "HeaderKey" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie", "JWTKey"] values = ["value1"] } + tags { + key = "tagkey1" + value = "tagvalue1" + } + tags { + key = "tagkey2" + value = "tagvalue2" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = "cert data" + type = "client" + enable = true + } } \ No newline at end of file diff --git a/examples/provider/web-api-practice.tf b/examples/provider/web-api-practice.tf index e5b535ef..62cbc8c2 100644 --- a/examples/provider/web-api-practice.tf +++ b/examples/provider/web-api-practice.tf @@ -1,12 +1,12 @@ resource "inext_web_api_practice" "test" { name = "inext_web_api_practice-test1" ips { - performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] - severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] - protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Prevent" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive"] + performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } api_attacks { minimum_severity = "Critical" # enum of ["Critical", "High", "Medium"] @@ -22,4 +22,21 @@ resource "inext_web_api_practice" "test" { filename = basename(data.local_file.schema_validation_file.filename) data = data.local_file.schema_validation_file.content } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } \ No newline at end of file diff --git a/examples/provider/web-app-asset.tf b/examples/provider/web-app-asset.tf index 53f48f62..f1574f0d 100644 --- a/examples/provider/web-app-asset.tf +++ b/examples/provider/web-app-asset.tf @@ -22,14 +22,25 @@ resource "inext_web_app_asset" "test1" { identifier = "SourceIP" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = " cert data" + type = "client" + enable = true + } } resource "inext_web_app_asset" "test2" { - name = "inext_web_app_asset-test2" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url6" - urls = ["http://host/path6"] + name = "inext_web_app_asset-test2" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url6" + urls = ["http://host/path6"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -37,9 +48,8 @@ resource "inext_web_app_asset" "test2" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" @@ -49,14 +59,25 @@ resource "inext_web_app_asset" "test2" { identifier = "SourceIP" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert2.der" + certificate_type = ".der" + data = " cert data2" + type = "server" + enable = true + } } resource "inext_web_app_asset" "test3" { - name = "inext_web_app_asset-test3" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url7" - urls = ["http://host/path7"] + name = "inext_web_app_asset-test3" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url7" + urls = ["http://host/path7"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -64,9 +85,8 @@ resource "inext_web_app_asset" "test3" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" @@ -79,11 +99,11 @@ resource "inext_web_app_asset" "test3" { } resource "inext_web_app_asset" "test4" { - name = "inext_web_app_asset-test4" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url8" - urls = ["http://host/path8"] + name = "inext_web_app_asset-test4" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url8" + urls = ["http://host/path8"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -91,9 +111,8 @@ resource "inext_web_app_asset" "test4" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" @@ -106,11 +125,11 @@ resource "inext_web_app_asset" "test4" { } resource "inext_web_app_asset" "test5" { - name = "inext_web_app_asset-test5" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url9" - urls = ["http://host/path9"] + name = "inext_web_app_asset-test5" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url9" + urls = ["http://host/path9"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -118,9 +137,8 @@ resource "inext_web_app_asset" "test5" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" @@ -133,11 +151,11 @@ resource "inext_web_app_asset" "test5" { } resource "inext_web_app_asset" "test6" { - name = "inext_web_app_asset-test6" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url10" - urls = ["http://host/path10"] + name = "inext_web_app_asset-test6" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url10" + urls = ["http://host/path10"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -145,9 +163,8 @@ resource "inext_web_app_asset" "test6" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" @@ -160,11 +177,11 @@ resource "inext_web_app_asset" "test6" { } resource "inext_web_app_asset" "test7" { - name = "inext_web_app_asset-test7" - profiles = [inext_appsec_gateway_profile.test.id] - trusted_sources = [inext_trusted_sources.test.id] - upstream_url = "some url11" - urls = ["http://host/path11"] + name = "inext_web_app_asset-test7" + profiles = [inext_appsec_gateway_profile.test.id] + behaviors = [inext_trusted_sources.test.id, inext_exceptions.test.id] + upstream_url = "some url11" + urls = ["http://host/path11"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -172,9 +189,8 @@ resource "inext_web_app_asset" "test7" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_app_practice.test.id # required - triggers = [inext_log_trigger.test.id] - exceptions = [inext_exceptions.test.id] + id = inext_web_app_practice.test.id # required + triggers = [inext_log_trigger.test.id] } proxy_setting { key = "some key" diff --git a/examples/provider/web-app-practice.tf b/examples/provider/web-app-practice.tf index 7e875b6c..6692ff43 100644 --- a/examples/provider/web-app-practice.tf +++ b/examples/provider/web-app-practice.tf @@ -4,9 +4,9 @@ resource "inext_web_app_practice" "test" { performance_impact = "LowOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] protections_from_year = "2016" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] + high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } web_attacks { minimum_severity = "High" # enum of ["Critical", "High", "Medium"] @@ -25,4 +25,21 @@ resource "inext_web_app_practice" "test" { inject_uris = ["url1", "url2"] valid_uris = ["url1", "url2"] } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } \ No newline at end of file diff --git a/examples/resources/inext_appsec_gateway_profile/resource.tf b/examples/resources/inext_appsec_gateway_profile/resource.tf index a4d306ac..e4e8b674 100644 --- a/examples/resources/inext_appsec_gateway_profile/resource.tf +++ b/examples/resources/inext_appsec_gateway_profile/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } diff --git a/examples/resources/inext_docker_profile/resource.tf b/examples/resources/inext_docker_profile/resource.tf index 019bf698..591f742f 100644 --- a/examples/resources/inext_docker_profile/resource.tf +++ b/examples/resources/inext_docker_profile/resource.tf @@ -1,8 +1,8 @@ terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } diff --git a/examples/resources/inext_embedded_profile/resource.tf b/examples/resources/inext_embedded_profile/resource.tf index 7960b265..f28352e5 100644 --- a/examples/resources/inext_embedded_profile/resource.tf +++ b/examples/resources/inext_embedded_profile/resource.tf @@ -1,8 +1,8 @@ terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } diff --git a/examples/resources/inext_exceptions/resource.tf b/examples/resources/inext_exceptions/resource.tf index 4ecc7c5e..df581c33 100644 --- a/examples/resources/inext_exceptions/resource.tf +++ b/examples/resources/inext_exceptions/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "~>1.1.1" } } } diff --git a/examples/resources/inext_kubernetes_profile/resource.tf b/examples/resources/inext_kubernetes_profile/resource.tf index e385b1ef..d239c848 100644 --- a/examples/resources/inext_kubernetes_profile/resource.tf +++ b/examples/resources/inext_kubernetes_profile/resource.tf @@ -1,8 +1,8 @@ terraform { required_providers { inext = { - version = "~> 1.0.0" - source = "checkpointsw/infinitynext" + source = "CheckPointSW/infinity-next" + version = "~>1.1.1" } } } diff --git a/examples/resources/inext_log_trigger/resource.tf b/examples/resources/inext_log_trigger/resource.tf index 623ed006..d8d2762f 100644 --- a/examples/resources/inext_log_trigger/resource.tf +++ b/examples/resources/inext_log_trigger/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "~>1.1.1" } } } @@ -32,9 +32,11 @@ resource "inext_log_trigger" "mytrigger" { log_to_cef = false cef_ip_address = "10.0.0.1" cef_port_num = 2000 + cef_protocol = "TCP" # enum of ["TCP", "UDP"] log_to_cloud = true log_to_syslog = true syslog_ip_address = "10.10.10.10" + syslog_protocol = "TCP" # enum of ["TCP", "UDP"] syslog_port_num = 5004 compliance_violations = true compliance_warnings = true diff --git a/examples/resources/inext_trusted_sources/resource.tf b/examples/resources/inext_trusted_sources/resource.tf index e5316e10..8c3786f7 100644 --- a/examples/resources/inext_trusted_sources/resource.tf +++ b/examples/resources/inext_trusted_sources/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -15,6 +15,7 @@ provider "inext" { resource "inext_trusted_sources" "my-trusted-source-behavior" { name = "some name" + visibility = "Shared" min_num_of_sources = 1 sources_identifiers = ["identifier1", "identifier2"] } diff --git a/examples/resources/inext_web_api_asset/resource.tf b/examples/resources/inext_web_api_asset/resource.tf index ff064f9d..2515c2cd 100644 --- a/examples/resources/inext_web_api_asset/resource.tf +++ b/examples/resources/inext_web_api_asset/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -14,11 +14,11 @@ provider "inext" { } resource "inext_web_api_asset" "my-webapi-asset" { - name = "some name" - profiles = [inext_appsec_gateway_profile.my-appsec-gateway-profile.id, inext_docker_profile.my-docker-profile.id, inext_embedded_profile.my-embedded-profile.id, inext_kubernetes_profile.my-kubernetes-profile.id] - trusted_sources = [inext_trusted_sources.my-trusted-source-behavior.id] - upstream_url = "some url" - urls = ["some url"] + name = "some name" + profiles = [inext_appsec_gateway_profile.my-appsec-gateway-profile.id, inext_docker_profile.my-docker-profile.id, inext_embedded_profile.my-embedded-profile.id, inext_kubernetes_profile.my-kubernetes-profile.id] + behaviors = [inext_trusted_sources.my-trusted-source-behavior.id, inext_exceptions.my-exceptions-behavior.id] + upstream_url = "some url" + urls = ["some url"] practice { main_mode = "Learn" # enum of ["Prevent", "Inactive", "Disabled", "Learn"] sub_practices_modes = { @@ -26,9 +26,8 @@ resource "inext_web_api_asset" "my-webapi-asset" { WebBot = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] Snort = "Disabled" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice", "Disabled", "Learn", "Active"] } - id = inext_web_api_practice.my-webapi-practice.id # required - triggers = [inext_log_trigger.mytrigger.id] - exceptions = [inext_exceptions.my-exceptions-behavior.id] + id = inext_web_api_practice.my-webapi-practice.id # required + triggers = [inext_log_trigger.mytrigger.id] } proxy_setting { key = "some key" @@ -38,4 +37,15 @@ resource "inext_web_api_asset" "my-webapi-asset" { identifier = "XForwardedFor" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value1", "value2"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = "cert data" + type = "client" + enable = true + } } diff --git a/examples/resources/inext_web_api_practice/resource.tf b/examples/resources/inext_web_api_practice/resource.tf index fec56bcd..0123b564 100644 --- a/examples/resources/inext_web_api_practice/resource.tf +++ b/examples/resources/inext_web_api_practice/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -14,14 +14,15 @@ provider "inext" { } resource "inext_web_api_practice" "my-webapi-practice" { - name = "some name" + name = "some name" + visibility = "Shared" # enum of ["Shared", "Local"] ips { - performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] - severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] - protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Prevent" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive"] + performance_impact = "MediumOrLower" # enum of ["LowOrLower", "MediumOrLower", "HighOrLower"] + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } api_attacks { minimum_severity = "Critical" # enum of ["Critical", "High", "Medium"] @@ -37,4 +38,21 @@ resource "inext_web_api_practice" "my-webapi-practice" { filename = basename(data.local_file.schema_validation_file.filename) data = data.local_file.schema_validation_file.content } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } diff --git a/examples/resources/inext_web_app_asset/resource.tf b/examples/resources/inext_web_app_asset/resource.tf index 8c7042e9..ae7e630e 100644 --- a/examples/resources/inext_web_app_asset/resource.tf +++ b/examples/resources/inext_web_app_asset/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -37,4 +37,15 @@ resource "inext_web_app_asset" "my-webapp-asset" { identifier = "HeaderKey" # enum of ["SourceIP", "XForwardedFor", "HeaderKey", "Cookie"] values = ["value"] } + tags { + key = "tagkey" + value = "tagvalue" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = " cert data" + type = "client" + enable = true + } } diff --git a/examples/resources/inext_web_app_practice/resource.tf b/examples/resources/inext_web_app_practice/resource.tf index e446a9bc..b01d0737 100644 --- a/examples/resources/inext_web_app_practice/resource.tf +++ b/examples/resources/inext_web_app_practice/resource.tf @@ -2,7 +2,7 @@ terraform { required_providers { inext = { source = "CheckPointSW/infinity-next" - version = "1.0.3" + version = "1.1.1" } } } @@ -14,14 +14,15 @@ provider "inext" { } resource "inext_web_app_practice" "my-webapp-practice" { - name = "some name" + name = "some name" + visibility = "Shared" # enum of ["Shared", "Local"] ips { performance_impact = "VeryLow" # enum of ["VeryLow", "LowOrLower", "MediumOrLower", "HighOrLower"] severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] protections_from_year = "2020" # enum of ["1999", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020"] - high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] - low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive"] + high_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] } web_attacks { minimum_severity = "Critical" # enum of ["Critical", "High", "Medium"] @@ -40,4 +41,21 @@ resource "inext_web_app_practice" "my-webapp-practice" { inject_uris = ["url1", "url2"] valid_uris = ["url1", "url2"] } + file_security { + severity_level = "LowOrAbove" # enum of ["LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"] + high_confidence = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + medium_confidence = "Detect" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + low_confidence = "Inactive" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_size_limit = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + file_size_limit = 10 + file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + file_without_name = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + required_archive_extraction = true + archive_file_size_limit = 100 + archive_file_size_limit_unit = "MB" # enum of ["Bytes","KB", "MB", "GB"] + allow_archive_within_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_an_unopened_archive = "AccordingToPractice" # enum of ["Detect", "Prevent", "Inactive", "AccordingToPractice"] + allow_file_type = true + required_threat_emulation = true + } } diff --git a/examples/resources/inext_web_user_response/resource.tf b/examples/resources/inext_web_user_response/resource.tf index 206b70cb..e9c9e9f7 100644 --- a/examples/resources/inext_web_user_response/resource.tf +++ b/examples/resources/inext_web_user_response/resource.tf @@ -1,5 +1,21 @@ +terraform { + required_providers { + inext = { + source = "CheckPointSW/infinity-next" + version = "1.1.1" + } + } +} + +provider "inext" { + region = "eu" + # client_id = "" // can be set with env var INEXT_CLIENT_ID + # access_key = "" // can be set with env var INEXT_ACCESS_KEY +} + resource "inext_web_user_response" "web-user-response-blockpage" { name = "web-user-response" + visibility = "Shared" # enum of ["Shared", "Local"] mode = "BlockPage" http_response_code = 403 message_title = "some message title" diff --git a/internal/models/appsec-gateway-profile/input.go b/internal/models/appsec-gateway-profile/input.go index 2a7abd6c..9c83895c 100644 --- a/internal/models/appsec-gateway-profile/input.go +++ b/internal/models/appsec-gateway-profile/input.go @@ -14,6 +14,7 @@ type UpgradeTimeInput struct { Time string `json:"time,omitempty"` WeekDays []string `json:"weekDays,omitempty"` Duration int `json:"duration,omitempty"` + Days []int `json:"days,omitempty"` } type CreateCloudGuardAppSecGatewayProfileInput struct { diff --git a/internal/models/appsec-gateway-profile/profile.go b/internal/models/appsec-gateway-profile/profile.go index 288fad92..49883a0c 100644 --- a/internal/models/appsec-gateway-profile/profile.go +++ b/internal/models/appsec-gateway-profile/profile.go @@ -5,6 +5,7 @@ type UpgradeTime struct { Time string `json:"time,omitempty"` WeekDays []string `json:"weekDays,omitempty"` Duration int `json:"duration,omitempty"` + Days []int `json:"days,omitempty"` } type KeyValue struct { diff --git a/internal/models/appsec-gateway-profile/update.go b/internal/models/appsec-gateway-profile/update.go index 4ece0b01..3ee2bca5 100644 --- a/internal/models/appsec-gateway-profile/update.go +++ b/internal/models/appsec-gateway-profile/update.go @@ -5,6 +5,7 @@ type UpdateUpgradeTimeInput struct { Time string `json:"time,omitempty"` WeekDays []string `json:"weekDays,omitempty"` Duration int `json:"duration,omitempty"` + Days []int `json:"days,omitempty"` } type UpdateKeyValue struct { diff --git a/internal/models/embedded-profile/input.go b/internal/models/embedded-profile/input.go index 07f737c9..caa418b9 100644 --- a/internal/models/embedded-profile/input.go +++ b/internal/models/embedded-profile/input.go @@ -14,6 +14,7 @@ type ScheduleTimeInput struct { Time string `json:"time,omitempty"` WeekDays []string `json:"weekDays,omitempty"` Duration int `json:"duration,omitempty"` + Days []int `json:"days,omitempty"` } type CreateEmbeddedProfileInput struct { diff --git a/internal/models/embedded-profile/profile.go b/internal/models/embedded-profile/profile.go index 0cd9bfaa..0ac34e0d 100644 --- a/internal/models/embedded-profile/profile.go +++ b/internal/models/embedded-profile/profile.go @@ -5,6 +5,7 @@ type ScheduleTime struct { Time string `json:"time,omitempty"` WeekDays []string `json:"weekDays,omitempty"` Duration int `json:"duration,omitempty"` + Days []int `json:"days,omitempty"` } type KeyValue struct { diff --git a/internal/models/exceptions/exceptions.go b/internal/models/exceptions/exceptions.go index 126ee57f..9132490b 100644 --- a/internal/models/exceptions/exceptions.go +++ b/internal/models/exceptions/exceptions.go @@ -23,6 +23,7 @@ type ExceptionsObjects []ExceptionObject type ExceptionBehavior struct { ID string `json:"id"` Name string `json:"name"` + Visibility string `json:"visibility"` Exceptions ExceptionsObjects `json:"exceptions"` } diff --git a/internal/models/exceptions/input.go b/internal/models/exceptions/input.go index b07e37be..0cdcd1e1 100644 --- a/internal/models/exceptions/input.go +++ b/internal/models/exceptions/input.go @@ -20,9 +20,11 @@ type ExceptionObjectInput struct { Comment string `json:"comment,omitempty"` } +type ExceptionObjectInputs []ExceptionObjectInput + // CreateExceptionBehaviorInput represents the api input for creating an Exception behavior object type CreateExceptionBehaviorInput struct { - Name string `json:"name,omitempty"` - Visibility string `json:"visibility,omitempty"` - Exceptions []ExceptionObjectInput `json:"exceptions,omitempty"` + Name string `json:"name,omitempty"` + Visibility string `json:"visibility,omitempty"` + Exceptions ExceptionObjectInputs `json:"exceptions,omitempty"` } diff --git a/internal/models/exceptions/update.go b/internal/models/exceptions/update.go index 8cdf0e92..44439371 100644 --- a/internal/models/exceptions/update.go +++ b/internal/models/exceptions/update.go @@ -6,8 +6,28 @@ type AddExceptionObjectInput struct { Comment string `json:"comment,omitempty"` } +type UpdateExceptionObjectActionInput struct { + ID string `json:"id"` + Action string `json:"action"` +} + +type UpdateExceptionsObjectInputs []UpdateExceptionObjectActionInput + +type ExceptionObjectActionUpdate struct { + ID string `json:"id,omitempty"` + Match string `json:"match,omitempty"` + AddActions []string `json:"addActions,omitempty"` + RemoveActions []string `json:"removeActions,omitempty"` + UpdateActions UpdateExceptionsObjectInputs `json:"updateActions,omitempty"` + Comment string `json:"comment,omitempty"` +} + +type ExceptionObjectActionsUpdate []ExceptionObjectActionUpdate + type UpdateExceptionBehaviorInput struct { - Name string `json:"name,omitempty"` - AddExceptions []AddExceptionObjectInput `json:"addExceptions,omitempty"` - RemoveExceptions []string `json:"removeExceptions,omitempty"` + Name string `json:"name,omitempty"` + Visibility string `json:"visibility,omitempty"` + AddExceptions []AddExceptionObjectInput `json:"addExceptions,omitempty"` + RemoveExceptions []string `json:"removeExceptions,omitempty"` + UpdateExceptions ExceptionObjectActionsUpdate `json:"updateExceptions,omitempty"` } diff --git a/internal/models/log-trigger/input.go b/internal/models/log-trigger/input.go index 5b5df89c..4a111c32 100644 --- a/internal/models/log-trigger/input.go +++ b/internal/models/log-trigger/input.go @@ -1,27 +1,31 @@ package models type CreateLogTriggerInput struct { - Name string `json:"name"` - Verbosity string `json:"verbosity"` - AccessControlAllowEvents bool `json:"acAllow"` - AccessControlDropEvents bool `json:"acDrop"` - ThreaPreventionDetectEvents bool `json:"tpDetect"` - ThreaPreventionPreventEvents bool `json:"tpPrevent"` - WebRequests bool `json:"webRequests"` - WebURLPath bool `json:"webUrlPath"` - WebURLQuery bool `json:"webUrlQuery"` - WebHeaders bool `json:"webHeaders"` - WebBody bool `json:"webBody"` - LogToCloud bool `json:"logToCloud"` - LogToAgent bool `json:"logToAgent"` - ExtendLogging bool `json:"extendLogging"` - ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` - ResponseBody bool `json:"responseBody"` - ResponseCode bool `json:"responseCode"` - LogToSyslog bool `json:"logToSyslog"` - SyslogIPAddress string `json:"syslogIpAddress,omitempty"` - SyslogPort int `json:"syslogPortNum,omitempty"` - LogToCEF bool `json:"logToCef"` - CEFIPAddress string `json:"cefIpAddress,omitempty"` - CEFPort int `json:"cefPortNum,omitempty"` + Name string `json:"name"` + Verbosity string `json:"verbosity"` + AccessControlAllowEvents bool `json:"acAllow"` + AccessControlDropEvents bool `json:"acDrop"` + ThreatPreventionDetectEvents bool `json:"tpDetect"` + ThreatPreventionPreventEvents bool `json:"tpPrevent"` + WebRequests bool `json:"webRequests"` + WebURLPath bool `json:"webUrlPath"` + WebURLQuery bool `json:"webUrlQuery"` + WebHeaders bool `json:"webHeaders"` + WebBody bool `json:"webBody"` + LogToCloud bool `json:"logToCloud"` + LogToAgent bool `json:"logToAgent"` + ExtendLogging bool `json:"extendLogging"` + ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` + ResponseBody bool `json:"responseBody"` + ResponseCode bool `json:"responseCode"` + LogToSyslog bool `json:"logToSyslog"` + SyslogIPAddress string `json:"syslogIpAddress,omitempty"` + SyslogProtocol string `json:"syslogProtocol,omitempty"` + SyslogPort int `json:"syslogPortNum,omitempty"` + LogToCEF bool `json:"logToCef"` + CEFIPAddress string `json:"cefIpAddress,omitempty"` + CEFPort int `json:"cefPortNum,omitempty"` + CEFProtocol string `json:"cefProtocol,omitempty"` + ComplianceWarnings bool `json:"complianceWarnings,omitempty"` + ComplianceViolations bool `json:"complianceViolations,omitempty"` } diff --git a/internal/models/log-trigger/trigger.go b/internal/models/log-trigger/trigger.go index f593efe7..c80c5017 100644 --- a/internal/models/log-trigger/trigger.go +++ b/internal/models/log-trigger/trigger.go @@ -1,28 +1,35 @@ package models type LogTrigger struct { - ID string `json:"id"` - Name string `json:"name"` - Verbosity string `json:"verbosity"` - AccessControlAllowEvents bool `json:"acAllow"` - AccessControlDropEvents bool `json:"acDrop"` - ThreaPreventionDetectEvents bool `json:"tpDetect"` - ThreaPreventionPreventEvents bool `json:"tpPrevent"` - WebRequests bool `json:"webRequests"` - WebURLPath bool `json:"webUrlPath"` - WebURLQuery bool `json:"webUrlQuery"` - WebHeaders bool `json:"webHeaders"` - WebBody bool `json:"webBody"` - LogToCloud bool `json:"logToCloud"` - LogToAgent bool `json:"logToAgent"` - ExtendLogging bool `json:"extendLogging"` - ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` - ResponseBody bool `json:"responseBody"` - ResponseCode bool `json:"responseCode"` - LogToSyslog bool `json:"logToSyslog"` - SyslogIPAddress string `json:"syslogIpAddress,omitempty"` - SyslogPort int `json:"syslogPortNum,omitempty"` - LogToCEF bool `json:"logToCef"` - CEFIPAddress string `json:"cefIpAddress,omitempty"` - CEFPort int `json:"cefPortNum,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + Verbosity string `json:"verbosity"` + AccessControlAllowEvents bool `json:"acAllow"` + AccessControlDropEvents bool `json:"acDrop"` + ThreatPreventionDetectEvents bool `json:"tpDetect"` + ThreatPreventionPreventEvents bool `json:"tpPrevent"` + WebRequests bool `json:"webRequests"` + WebURLPath bool `json:"webUrlPath"` + WebURLQuery bool `json:"webUrlQuery"` + WebHeaders bool `json:"webHeaders"` + WebBody bool `json:"webBody"` + LogToCloud bool `json:"logToCloud"` + LogToAgent bool `json:"logToAgent"` + ExtendLogging bool `json:"extendLogging"` + ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` + ResponseBody bool `json:"responseBody"` + ResponseCode bool `json:"responseCode"` + LogToSyslog bool `json:"logToSyslog"` + SyslogIPAddress string `json:"syslogIpAddress,omitempty"` + SyslogProtocol string `json:"syslogProtocol,omitempty"` + SyslogPort int `json:"syslogPortNum,omitempty"` + LogToCEF bool `json:"logToCef"` + CEFIPAddress string `json:"cefIpAddress,omitempty"` + CEFPort int `json:"cefPortNum,omitempty"` + CEFProtocol string `json:"cefProtocol,omitempty"` + ObjectStatus string `json:"objectStatus,omitempty"` + TriggerType string `json:"triggerType"` + UsedBy int `json:"usedBy"` + ComplianceWarnings bool `json:"complianceWarnings"` + ComplianceViolations bool `json:"complianceViolations"` } diff --git a/internal/models/log-trigger/update.go b/internal/models/log-trigger/update.go index ce43a9c7..85e2a2bf 100644 --- a/internal/models/log-trigger/update.go +++ b/internal/models/log-trigger/update.go @@ -1,27 +1,31 @@ package models type UpdateLogTriggerInput struct { - Name string `json:"name"` - Verbosity string `json:"verbosity"` - AccessControlAllowEvents bool `json:"acAllow"` - AccessControlDropEvents bool `json:"acDrop"` - ThreaPreventionDetectEvents bool `json:"tpDetect"` - ThreaPreventionPreventEvents bool `json:"tpPrevent"` - WebRequests bool `json:"webRequests"` - WebURLPath bool `json:"webUrlPath"` - WebURLQuery bool `json:"webUrlQuery"` - WebHeaders bool `json:"webHeaders"` - WebBody bool `json:"webBody"` - LogToCloud bool `json:"logToCloud"` - LogToAgent bool `json:"logToAgent"` - ExtendLogging bool `json:"extendLogging"` - ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` - ResponseBody bool `json:"responseBody"` - ResponseCode bool `json:"responseCode"` - LogToSyslog bool `json:"logToSyslog"` - SyslogIPAddress string `json:"syslogIpAddress,omitempty"` - SyslogPort int `json:"syslogPortNum,omitempty"` - LogToCEF bool `json:"logToCef"` - CEFIPAddress string `json:"cefIpAddress,omitempty"` - CEFPort int `json:"cefPortNum,omitempty"` + Name string `json:"name"` + Verbosity string `json:"verbosity"` + ComplianceWarnings bool `json:"complianceWarnings"` + ComplianceViolations bool `json:"complianceViolations"` + AccessControlAllowEvents bool `json:"acAllow"` + AccessControlDropEvents bool `json:"acDrop"` + ThreatPreventionDetectEvents bool `json:"tpDetect"` + ThreatPreventionPreventEvents bool `json:"tpPrevent"` + WebRequests bool `json:"webRequests"` + WebURLPath bool `json:"webUrlPath"` + WebURLQuery bool `json:"webUrlQuery"` + WebHeaders bool `json:"webHeaders"` + WebBody bool `json:"webBody"` + LogToCloud bool `json:"logToCloud"` + LogToAgent bool `json:"logToAgent"` + ExtendLogging bool `json:"extendLogging"` + ExtendLoggingMinSeverity string `json:"extendLoggingMinSeverity,omitempty"` + ResponseBody bool `json:"responseBody"` + ResponseCode bool `json:"responseCode"` + LogToSyslog bool `json:"logToSyslog"` + SyslogIPAddress string `json:"syslogIpAddress,omitempty"` + SyslogProtocol string `json:"syslogProtocol,omitempty"` + SyslogPort int `json:"syslogPortNum,omitempty"` + LogToCEF bool `json:"logToCef"` + CEFIPAddress string `json:"cefIpAddress,omitempty"` + CEFPort int `json:"cefPortNum,omitempty"` + CEFProtocol string `json:"cefProtocol,omitempty"` } diff --git a/internal/models/trusted-sources/behavior.go b/internal/models/trusted-sources/behavior.go index c834ab0b..8a658761 100644 --- a/internal/models/trusted-sources/behavior.go +++ b/internal/models/trusted-sources/behavior.go @@ -14,6 +14,7 @@ type TrustedSourceSource struct { type TrustedSourceBehavior struct { ID string `json:"id"` Name string `json:"name"` + Visibility string `json:"visibility"` NumOfSources int `json:"numOfSources"` SourcesIdentifiers []TrustedSourceSource `json:"sourcesIdentifiers,omitempty"` } diff --git a/internal/models/trusted-sources/update.go b/internal/models/trusted-sources/update.go index d9723741..89fed50a 100644 --- a/internal/models/trusted-sources/update.go +++ b/internal/models/trusted-sources/update.go @@ -1,8 +1,15 @@ package models +type TrustedSourceUpdateInput struct { + ID string `json:"id"` + Source string `json:"source"` +} + type UpdateTrustedSourceBehaviorInput struct { - Name string `json:"name,omitempty"` - NumOfSources int `json:"numOfSources,omitempty"` - AddSourcesIdentifiers []string `json:"addSourcesIdentifiers,omitempty"` - RemoveSourcesIdentifiersIDs []string `json:"removeSourcesIdentifiers,omitempty"` + Name string `json:"name,omitempty"` + Visibility string `json:"visibility,omitempty"` + NumOfSources int `json:"numOfSources,omitempty"` + AddSourcesIdentifiers []string `json:"addSourcesIdentifiers,omitempty"` + RemoveSourcesIdentifiersIDs []string `json:"removeSourcesIdentifiers,omitempty"` + UpdateSourcesIdentifiers []TrustedSourceUpdateInput `json:"updateSourcesIdentifiers,omitempty"` } diff --git a/internal/models/web-api-asset/asset.go b/internal/models/web-api-asset/asset.go index 17e71630..294fc9fc 100644 --- a/internal/models/web-api-asset/asset.go +++ b/internal/models/web-api-asset/asset.go @@ -36,7 +36,6 @@ type PracticeWrapper struct { MainMode string `json:"mainMode,omitempty"` SubPracticeModes []PracticeMode `json:"subPracticeModes,omitempty"` Triggers []Trigger `json:"triggers,omitempty"` - Behaviors []Behavior `json:"behaviors,omitempty"` Practice Practice `json:"practice"` } @@ -72,7 +71,7 @@ type ProxySetting struct { type ProxySettings []ProxySetting -// URL represents an URL object returned from mgmt +// URL represents a URL object returned from mgmt // url field is defined by the user // id field is a unique uuid generated by mgmt type URL struct { @@ -89,6 +88,14 @@ type Profile struct { type Profiles []Profile +type Tag struct { + ID string `json:"id"` + Key string `json:"key"` + Value string `json:"value"` +} + +type Tags []Tag + // WebAPIAsset represents the response from mgmt after creating the asset type WebAPIAsset struct { ID string `json:"id"` @@ -111,7 +118,9 @@ type WebAPIAsset struct { Behaviors Behaviors `json:"behaviors,omitempty"` Profiles Profiles `json:"profiles,omitempty"` Practices PracticesWrappers `json:"practices,omitempty"` + Tags Tags `json:"tags,omitempty"` ReadOnly bool `json:"readOnly"` + IsSharesURLs bool `json:"isSharesURLs"` } // ToSchema returns a slice of profiles IDs to be saved in the state file @@ -132,6 +141,22 @@ func (behaviors Behaviors) ToSchema() []string { return utils.Map(behaviors, mapFunc) } +func (tags Tags) ToSchema() []SchemaTag { + mapFunc := func(tag Tag) SchemaTag { + return tag.ToSchema() + } + + return utils.Map(tags, mapFunc) +} + +func (tag Tag) ToSchema() SchemaTag { + return SchemaTag{ + ID: tag.ID, + Key: tag.Key, + Value: tag.Value, + } +} + // ToSchema converts the URLs as returned from the APi to 2 slices of strings to be saved in the state file: // 1. IDs slice // 2. URLs slice @@ -163,7 +188,7 @@ func (sourceIdentifiers SourceIdentifiers) ToSchema() []SchemaSourceIdentifier { return utils.Map(sourceIdentifiers, mapFunc) } -// toSchema converts a single SourceIdentifier as returned from the API to a single +// ToSchema converts a single SourceIdentifier as returned from the API to a single // SchemaSourceIdentifier to be saved in the state file func (sourceIdentifier SourceIdentifier) ToSchema() SchemaSourceIdentifier { values := make([]string, len(sourceIdentifier.Values)) @@ -181,7 +206,7 @@ func (sourceIdentifier SourceIdentifier) ToSchema() SchemaSourceIdentifier { } } -// ToSchema converts the paractices field as returned from the API to a slice of +// ToSchema converts the practices field as returned from the API to a slice of // SchemaPracticeWrapper to be saved in the state file func (wrappers PracticesWrappers) ToSchema() []SchemaPracticeWrapper { mapFunc := func(wrapper PracticeWrapper) SchemaPracticeWrapper { @@ -199,11 +224,6 @@ func (practiceWrapper PracticeWrapper) ToSchema() SchemaPracticeWrapper { triggers[j] = trigger.ID } - behaviors := make([]string, len(practiceWrapper.Behaviors)) - for j, behavior := range practiceWrapper.Behaviors { - behaviors[j] = behavior.ID - } - subPracticeModes := make(map[string]string) for _, mode := range practiceWrapper.SubPracticeModes { subPracticeModes[mode.SubPractice] = mode.Mode @@ -215,6 +235,5 @@ func (practiceWrapper PracticeWrapper) ToSchema() SchemaPracticeWrapper { MainMode: practiceWrapper.MainMode, SubPracticeModes: subPracticeModes, Triggers: triggers, - Behaviors: behaviors, } } diff --git a/internal/models/web-api-asset/input.go b/internal/models/web-api-asset/input.go index d4106cb2..5f182fd1 100644 --- a/internal/models/web-api-asset/input.go +++ b/internal/models/web-api-asset/input.go @@ -30,7 +30,7 @@ type PracticeModeInput struct { SubPractice string `json:"subPractice,omitempty"` } -// practiceWrapperMap represents the api input for creating a practice field in the web API asset +// PracticeWrapperInput represents the api input for creating a practice field in the web API asset type PracticeWrapperInput struct { PracticeWrapperID string `json:"practiceWrapperId,omitempty"` PracticeID string `json:"practiceId"` @@ -42,17 +42,27 @@ type PracticeWrapperInput struct { type PracticeWrappersInputs []PracticeWrapperInput +type TagInput struct { + Key string `json:"key"` + Value string `json:"value"` + ID string `json:"ID,omitempty"` +} + +type TagsInputs []TagInput + // CreateWebAPIAssetInput represents the api input for creating a web API asset type CreateWebAPIAssetInput struct { Name string `json:"name"` PracticeWrappers PracticeWrappersInputs `json:"practices,omitempty"` Profiles []string `json:"profiles,omitempty"` Behaviors []string `json:"behaviors,omitempty"` + Tags TagsInputs `json:"tags,omitempty"` State string `json:"state,omitempty"` ProxySettings ProxySettingInputs `json:"proxySetting,omitempty"` UpstreamURL string `json:"upstreamURL,omitempty"` URLs []string `json:"URLs,omitempty"` SourceIdentifiers SourceIdentifiersInputs `json:"sourceIdentifiers,omitempty"` + IsSharesURLs bool `json:"isSharesURLs,omitempty"` } // ToIndicatorsMap converts a ProxySettingInputs to a map from a proxy setting key to the proxy setting struct itself @@ -84,3 +94,21 @@ func (ids ValuesIDs) ToIndicatorsMap() map[string]string { return ret } + +func (inputs TagsInputs) ToIndicatorsMap() map[string]TagInput { + ret := make(map[string]TagInput) + for _, input := range inputs { + ret[input.Key] = input + } + + return ret +} + +func (mtlsInputs MTLSSchemas) ToIndicatorMap() map[string]MTLSSchema { + mTLSs := make(map[string]MTLSSchema) + for _, mTLS := range mtlsInputs { + mTLSs[mTLS.Type] = mTLS + } + + return mTLSs +} diff --git a/internal/models/web-api-asset/schema.go b/internal/models/web-api-asset/schema.go index d492d0e4..590a14b7 100644 --- a/internal/models/web-api-asset/schema.go +++ b/internal/models/web-api-asset/schema.go @@ -1,7 +1,28 @@ package models +import ( + "encoding/base64" + "fmt" +) + const ( SourceIdentifierValueIDSeparator = ";;;" + FileDataFormat = "data:%s;base64,%s" + + mTLSFileTypePEM = ".pem" + mTLSFileTypeCRT = ".crt" + mTLSFileTypeDER = ".der" + mTLSFileTypeP12 = ".p12" + mTLSFileTypePFX = ".pfx" + mTLSFileTypeP7B = ".p7b" + mTLSFileTypeP7C = ".p7c" + mTLSFileTypeCER = ".cer" + + mimeTypePEM = "application/octet-stream" + mimeTypeDER = "application/x-x509-ca-cert" + mimeTypeP12 = "application/x-pkcs12" + mimeTypeP7B = "application/x-pkcs7-certificates" + mimeTypeP7C = "application/pkcs7-mime" ) // SchemaPracticeMode represents a PracticeMode field of a practice field of a web API asset as it is saved in the state file @@ -19,7 +40,6 @@ type SchemaPracticeWrapper struct { MainMode string `json:"main_mode,omitempty"` SubPracticeModes map[string]string `json:"sub_practices_modes,omitempty"` Triggers []string `json:"triggers,omitempty"` - Behaviors []string `json:"exceptions,omitempty"` } // SchemaSourceIdentifier represents the SourceIdentifier field of a web APi asset as it is saved in the state file @@ -30,3 +50,76 @@ type SchemaSourceIdentifier struct { Values []string `json:"values"` ValuesIDs []string `json:"values_ids"` } + +type SchemaTag struct { + ID string `json:"id,omitempty"` + Key string `json:"key"` + Value string `json:"value"` +} + +// MTLSSchema represents a field of web API asset as it is saved in the state file +// this structure is aligned with the input schema (see web-api-asset.go file) +type MTLSSchema struct { + FilenameID string `json:"filename_id,omitempty"` + Filename string `json:"filename,omitempty"` + CertificateType string `json:"certificate_type,omitempty"` + DataID string `json:"data_id,omitempty"` + Data string `json:"data"` + Type string `json:"type,omitempty"` + EnableID string `json:"enable_id,omitempty"` + Enable bool `json:"enable,omitempty"` +} + +type MTLSSchemas []MTLSSchema + +// FileExtensionToMimeType returns the MIME type for a given file extension +// if the extension is not recognized, it returns "application/octet-stream" - a generic binary file MIME type +// the function is used to set the MIME type for the certificate type in the MTLSSchema +// the certificate types that are allowed displayed in the web-api-asset.go file +func FileExtensionToMimeType(extension string) string { + switch extension { + case mTLSFileTypePEM: + return mimeTypePEM + case mTLSFileTypeDER, mTLSFileTypeCER, mTLSFileTypeCRT: + return mimeTypeDER + case mTLSFileTypeP12, mTLSFileTypePFX: + return mimeTypeP12 + case mTLSFileTypeP7B: + return mimeTypeP7B + case mTLSFileTypeP7C: + return mimeTypeP7C + default: + return mimeTypePEM + } +} + +// MimeTypeToFileExtension returns the file extension for a given MIME type +// the function is used to set the certificate type in the MTLSSchema +func MimeTypeToFileExtension(mimeType string) string { + switch mimeType { + case mimeTypePEM: + return mTLSFileTypePEM + case mimeTypeDER: + return mTLSFileTypeDER + case mimeTypeP12: + return mTLSFileTypeP12 + case mimeTypeP7B: + return mTLSFileTypeP7B + case mimeTypeP7C: + return mTLSFileTypeP7C + default: + return mTLSFileTypePEM + } +} + +func NewFileSchemaEncode(filename, fileData, mTLSType, certificateType string, fileEnable bool) MTLSSchema { + b64Data := base64.StdEncoding.EncodeToString([]byte(fileData)) + data := fmt.Sprintf(FileDataFormat, FileExtensionToMimeType(certificateType), b64Data) + + return MTLSSchema{ + Filename: filename, + Data: data, + Type: mTLSType, + Enable: fileEnable, + } +} diff --git a/internal/models/web-api-asset/update.go b/internal/models/web-api-asset/update.go index 7b6cfea9..d9dc11a7 100644 --- a/internal/models/web-api-asset/update.go +++ b/internal/models/web-api-asset/update.go @@ -1,35 +1,37 @@ package models -// UpdateSourceIdentifier represents the input for updating an existing source identifier value -// in a source identifier field of an existing WebAPIAseet object +// UpdateSourceIdentifierValue represents the input for updating an existing source identifier value +// in a source identifier field of an existing WebAPIAsset object type UpdateSourceIdentifierValue struct { ID string `json:"id"` IdentifierValue string `json:"identifierValue"` } // UpdateSourceIdentifier represents the input for updating an existing proxy -// setting field of an existing WebAPIAseet object +// setting field of an existing WebAPIAsset object type UpdateSourceIdentifier struct { - ID string `json:"id"` - SourceIdentifier string `json:"sourceIdentifier"` - AddValues []string `json:"addValues"` - RemoveValues []string `json:"removeValues"` - UpdateValues []string `json:"updateValues"` + ID string `json:"id"` + SourceIdentifier string `json:"sourceIdentifier"` + AddValues []string `json:"addValues"` + RemoveValues []string `json:"removeValues"` + UpdateValues []UpdateSourceIdentifierValue `json:"updateValues"` } -// AddSourceIdentifier represents the input for adding a source identifier field to an existing WebAPIAseet object +type UpdateSourceIdentifiers []UpdateSourceIdentifier + +// AddSourceIdentifier represents the input for adding a source identifier field to an existing WebAPIAsset object type AddSourceIdentifier struct { SourceIdentifier string `json:"sourceIdentifier"` Values []string `json:"values"` } -// AddProxySetting represents the input for updating an existing url field of an existing WebAPIAseet object +// UpdateURL represents the input for updating an existing url field of an existing WebAPIAsset object type UpdateURL struct { ID string `json:"id"` URL string `json:"url"` } -// AddProxySetting represents the input for updating an existing proxy setting field of an existing WebAPIAseet object +// UpdateProxySetting represents the input for updating an existing proxy setting field of an existing WebAPIAsset object type UpdateProxySetting struct { ID string `json:"id"` Key string `json:"key"` @@ -43,7 +45,7 @@ type AddProxySetting struct { } // AddPracticeMode represents the api input for adding a practice mode (sub practice) in a practice to add -// to an existing WebAPIAseet object +// to an existing WebAPIAsset object type AddPracticeMode struct { Mode string `json:"mode"` SubPractice string `json:"subPractice,omitempty"` @@ -55,27 +57,46 @@ type AddPracticeWrapper struct { MainMode string `json:"mainMode"` SubPracticeModes []AddPracticeMode `json:"subPracticeModes,omitempty"` Triggers []string `json:"triggers,omitempty"` - Behaviors []string `json:"behaviors,omitempty"` } +// AddTag represent the input for adding a tag field to an existing WebApplicationAsset object +type AddTag struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type AddTags []AddTag + // UpdateWebAPIAssetInput represents the input for updating an existing WebAPIAseet object type UpdateWebAPIAssetInput struct { - Name string `json:"name,omitempty"` - AddPracticeWrappers []AddPracticeWrapper `json:"addPractices,omitempty"` - RemovePracticeWrappers []string `json:"removePractices,omitempty"` - AddProfiles []string `json:"addProfiles,omitempty"` - RemoveProfiles []string `json:"removeProfiles,omitempty"` - AddBehaviors []string `json:"addBehaviors,omitempty"` - RemoveBehaviors []string `json:"removeBehaviors,omitempty"` - State string `json:"state,omitempty"` - AddProxySetting []AddProxySetting `json:"addProxySetting,omitempty"` - RemoveProxySetting []string `json:"removeProxySetting,omitempty"` - UpdateProxySetting []UpdateProxySetting `json:"updateProxySetting,omitempty"` - UpstreamURL string `json:"upstreamURL,omitempty"` - AddURLs []string `json:"addURLs,omitempty"` - RemoveURLs []string `json:"removeURLs,omitempty"` - UpdateURLs []UpdateURL `json:"updateURLs,omitempty"` - AddSourceIdentifiers []AddSourceIdentifier `json:"addSourceIdentifiers,omitempty"` - RemoveSourceIdentifiers []string `json:"removeSourceIdentifiers,omitempty"` - UpdateSourceIdentifiers []UpdateSourceIdentifier `json:"updateSourceIdentifiers,omitempty"` + Name string `json:"name,omitempty"` + AddPracticeWrappers []AddPracticeWrapper `json:"addPractices,omitempty"` + RemovePracticeWrappers []string `json:"removePractices,omitempty"` + AddProfiles []string `json:"addProfiles,omitempty"` + RemoveProfiles []string `json:"removeProfiles,omitempty"` + AddBehaviors []string `json:"addBehaviors,omitempty"` + RemoveBehaviors []string `json:"removeBehaviors,omitempty"` + AddTags AddTags `json:"addTags,omitempty"` + RemoveTags []string `json:"removeTags,omitempty"` + State string `json:"state,omitempty"` + AddProxySetting []AddProxySetting `json:"addProxySetting,omitempty"` + RemoveProxySetting []string `json:"removeProxySetting,omitempty"` + UpdateProxySetting []UpdateProxySetting `json:"updateProxySetting,omitempty"` + UpstreamURL string `json:"upstreamURL,omitempty"` + AddURLs []string `json:"addURLs,omitempty"` + RemoveURLs []string `json:"removeURLs,omitempty"` + UpdateURLs []UpdateURL `json:"updateURLs,omitempty"` + AddSourceIdentifiers []AddSourceIdentifier `json:"addSourceIdentifiers,omitempty"` + RemoveSourceIdentifiers []string `json:"removeSourceIdentifiers,omitempty"` + UpdateSourceIdentifiers UpdateSourceIdentifiers `json:"updateSourceIdentifiers,omitempty"` + IsSharesURLs bool `json:"isSharesURLs,omitempty"` +} + +func (updates UpdateSourceIdentifiers) ToIndicatorsMap() map[string]UpdateSourceIdentifier { + ret := make(map[string]UpdateSourceIdentifier) + for _, update := range updates { + ret[update.ID] = update + } + + return ret } diff --git a/internal/models/web-api-practice/input.go b/internal/models/web-api-practice/input.go index 1ce4d7a2..d683097e 100644 --- a/internal/models/web-api-practice/input.go +++ b/internal/models/web-api-practice/input.go @@ -2,7 +2,7 @@ package models type SchemaValidationInput struct { ID string `json:"id,omitempty"` - OASSchema string `json:"OasSchema"` + OASSchema string `json:"OasSchema,omitempty"` } type AdvancedSettingInput struct { @@ -30,11 +30,31 @@ type IPSInput struct { LowConfidence string `json:"lowConfidence,omitempty"` } +type WebAPIFileSecurityInput struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severityLevel,omitempty"` + HighConfidence string `json:"highConfidence,omitempty"` + MediumConfidence string `json:"mediumConfidence,omitempty"` + LowConfidence string `json:"lowConfidence,omitempty"` + AllowFileSizeLimit string `json:"allowFileSizeLimit,omitempty"` + FileSizeLimit int `json:"fileSizeLimit,omitempty"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit,omitempty"` + FilesWithoutName string `json:"filesWithoutName,omitempty"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction,omitempty"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit,omitempty"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive,omitempty"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive,omitempty"` + AllowFileType bool `json:"allowFileType,omitempty"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation,omitempty"` +} + // CreateWebAPIPracticeInput represents the api input for creating a web API practice type CreateWebAPIPracticeInput struct { - Name string `json:"name"` - Visibility string `json:"visibility,omitempty"` - IPS IPSInput `json:"IPS,omitempty"` - APIAttacks APIAttacksInput `json:"APIAttacks,omitempty"` - SchemaValidation SchemaValidationInput `json:"SchemaValidation,omitempty"` + Name string `json:"name"` + Visibility string `json:"visibility,omitempty"` + IPS IPSInput `json:"IPS,omitempty"` + APIAttacks APIAttacksInput `json:"APIAttacks,omitempty"` + SchemaValidation SchemaValidationInput `json:"SchemaValidation,omitempty"` + FileSecurity WebAPIFileSecurityInput `json:"FileSecurity,omitempty"` } diff --git a/internal/models/web-api-practice/practice.go b/internal/models/web-api-practice/practice.go index c1ea33f3..c1927dfa 100644 --- a/internal/models/web-api-practice/practice.go +++ b/internal/models/web-api-practice/practice.go @@ -2,9 +2,10 @@ package models // FileWrapper represents the OASSchema field of the SchemaValidation field of the WebAPIPractice returned from the API type FileWrapper struct { - Data string `json:"data"` - Name string `json:"name"` - Size uint64 `json:"size"` + Data string `json:"data"` + Name string `json:"name"` + Size uint64 `json:"size"` + IsFileExist bool `json:"isFileExist"` } // SchemaValidation represents the SchemaValidation field of the WebAPIPractice returned from the API @@ -41,14 +42,35 @@ type IPS struct { LowConfidence string `json:"lowConfidence"` } +type WebApplicationFileSecurity struct { + ID string `json:"id"` + SeverityLevel string `json:"severityLevel"` + HighConfidence string `json:"highConfidence"` + MediumConfidence string `json:"mediumConfidence"` + LowConfidence string `json:"lowConfidence"` + AllowFileSizeLimit string `json:"allowFileSizeLimit"` + FileSizeLimit int `json:"fileSizeLimit"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit"` + FilesWithoutName string `json:"filesWithoutName"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive"` + AllowFileType bool `json:"allowFileType"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation"` +} + // WebAPIPractice represents the response from the API after creating the web API practice type WebAPIPractice struct { - ID string `json:"id"` - IPS IPS `json:"IPS"` - Name string `json:"name"` - Category string `json:"category"` - PracticeType string `json:"practiceType"` - APIAttacks APIAttacks `json:"APIAttacks"` - Default bool `json:"default"` - SchemaValidation SchemaValidation `json:"SchemaValidation"` + ID string `json:"id"` + IPS IPS `json:"IPS"` + Name string `json:"name"` + Category string `json:"category"` + PracticeType string `json:"practiceType"` + Visibility string `json:"visibility"` + APIAttacks APIAttacks `json:"APIAttacks"` + Default bool `json:"default"` + SchemaValidation SchemaValidation `json:"SchemaValidation"` + FileSecurity WebApplicationFileSecurity `json:"FileSecurity"` } diff --git a/internal/models/web-api-practice/schema.go b/internal/models/web-api-practice/schema.go index 7824eb7a..2700c30f 100644 --- a/internal/models/web-api-practice/schema.go +++ b/internal/models/web-api-practice/schema.go @@ -44,8 +44,28 @@ type SchemaIPS struct { type FileSchema struct { ID string `json:"id,omitempty"` - Filename string `json:"filename,omitempty"` + Filename string `json:"name,omitempty"` Data string `json:"data"` + Size uint64 `json:"size,omitempty"` +} + +type WebApplicationFileSecuritySchema struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severity_level,omitempty"` + HighConfidence string `json:"high_confidence,omitempty"` + MediumConfidence string `json:"medium_confidence,omitempty"` + LowConfidence string `json:"low_confidence,omitempty"` + AllowFileSizeLimit string `json:"allow_file_size_limit,omitempty"` + FileSizeLimit int `json:"file_size_limit,omitempty"` + FileSizeLimitUnit string `json:"file_size_limit_unit,omitempty"` + FilesWithoutName string `json:"files_without_name,omitempty"` + RequiredArchiveExtraction bool `json:"required_archive_extraction,omitempty"` + ArchiveFileSizeLimit int `json:"archive_file_size_limit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archive_file_size_limit_unit,omitempty"` + AllowArchiveWithinArchive string `json:"allow_archive_within_archive,omitempty"` + AllowAnUnopenedArchive string `json:"allow_an_unopened_archive,omitempty"` + AllowFileType bool `json:"allow_file_type,omitempty"` + RequiredThreatEmulation bool `json:"required_threat_emulation,omitempty"` } func NewFileSchemaEncode(filename, fileData string) FileSchema { diff --git a/internal/models/web-api-practice/update.go b/internal/models/web-api-practice/update.go index 73ff17f4..75701d97 100644 --- a/internal/models/web-api-practice/update.go +++ b/internal/models/web-api-practice/update.go @@ -21,10 +21,30 @@ type UpdateIPSInput struct { LowConfidence string `json:"lowConfidence,omitempty"` } +type UpdateWebApplicationFileSecurityInput struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severityLevel,omitempty"` + HighConfidence string `json:"highConfidence,omitempty"` + MediumConfidence string `json:"mediumConfidence,omitempty"` + LowConfidence string `json:"lowConfidence,omitempty"` + AllowFileSizeLimit string `json:"allowFileSizeLimit,omitempty"` + FileSizeLimit int `json:"fileSizeLimit,omitempty"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit,omitempty"` + FilesWithoutName string `json:"filesWithoutName,omitempty"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction,omitempty"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit,omitempty"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive,omitempty"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive,omitempty"` + AllowFileType bool `json:"allowFileType,omitempty"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation,omitempty"` +} + type UpdatePracticeInput struct { - Name string `json:"name,omitempty"` - Visibility string `json:"visibility,omitempty"` - IPS UpdateIPSInput `json:"IPS,omitempty"` - APIAttacks UpdateAPIAttacksInput `json:"APIAttacks,omitempty"` - SchemaValidation UpdateSchemaValidationInput `json:"SchemaValidation,omitempty"` + Name string `json:"name,omitempty"` + Visibility string `json:"visibility,omitempty"` + IPS UpdateIPSInput `json:"IPS,omitempty"` + APIAttacks UpdateAPIAttacksInput `json:"APIAttacks,omitempty"` + SchemaValidation UpdateSchemaValidationInput `json:"SchemaValidation,omitempty"` + FileSecurity UpdateWebApplicationFileSecurityInput `json:"FileSecurity,omitempty"` } diff --git a/internal/models/web-app-asset/asset.go b/internal/models/web-app-asset/asset.go index 7d52665f..d604f070 100644 --- a/internal/models/web-app-asset/asset.go +++ b/internal/models/web-app-asset/asset.go @@ -91,6 +91,15 @@ type Profile struct { type Profiles []Profile +// Tag represents a tag field of a web application asset as it is returned from mgmt +type Tag struct { + ID string `json:"id"` + Key string `json:"key"` + Value string `json:"value"` +} + +type Tags []Tag + // WebApplicationAsset represents a web application asset as it is returned from mgmt type WebApplicationAsset struct { ID string `json:"id"` @@ -113,7 +122,9 @@ type WebApplicationAsset struct { Behaviors Behaviors `json:"behaviors,omitempty"` Profiles Profiles `json:"profiles,omitempty"` Practices PracticesWrappers `json:"practices,omitempty"` + Tags Tags `json:"tags,omitempty"` ReadOnly bool `json:"readOnly"` + IsSharesURLs bool `json:"isSharesURLs,omitempty"` } // ToSchema returns a slice of profiles IDs to be saved in the state file @@ -134,6 +145,22 @@ func (behaviors Behaviors) ToSchema() []string { return utils.Map(behaviors, mapFunc) } +func (tags Tags) ToSchema() []SchemaTag { + mapFunc := func(tag Tag) SchemaTag { + return tag.ToSchema() + } + + return utils.Map(tags, mapFunc) +} + +func (tag Tag) ToSchema() SchemaTag { + return SchemaTag{ + ID: tag.ID, + Key: tag.Key, + Value: tag.Value, + } +} + // ToSchema converts the URLs as returned from the APi to 2 slices of strings to be saved in the state file: // 1. IDs slice // 2. URLs slice diff --git a/internal/models/web-app-asset/input.go b/internal/models/web-app-asset/input.go index 57f22d74..c5f2b7cc 100644 --- a/internal/models/web-app-asset/input.go +++ b/internal/models/web-app-asset/input.go @@ -1,6 +1,8 @@ package models -import "strings" +import ( + "strings" +) // PracticeModeInput represents the api input for creating a practice mode field // in the practice field of the web application asset @@ -9,6 +11,15 @@ type PracticeModeInput struct { SubPractice string `json:"subPractice,omitempty"` } +// TagInput represents the api input for creating a tag field in the web application asset +type TagInput struct { + Key string `json:"key"` + Value string `json:"value"` + ID string `json:"id,omitempty"` +} + +type TagsInputs []TagInput + // PracticeWrapperInput represents the api input for creating a practice field in the web application asset type PracticeWrapperInput struct { PracticeWrapperID string `json:"practiceWrapperId,omitempty"` @@ -47,10 +58,12 @@ type CreateWebApplicationAssetInput struct { PracticeWrappers PracticeWrappersInputs `json:"practices,omitempty"` Profiles []string `json:"profiles,omitempty"` Behaviors []string `json:"behaviors,omitempty"` + Tags TagsInputs `json:"tags,omitempty"` ProxySettings ProxySettingInputs `json:"proxySetting,omitempty"` UpstreamURL string `json:"upstreamURL,omitempty"` URLs []string `json:"URLs,omitempty"` SourceIdentifiers SourceIdentifiersInputs `json:"sourceIdentifiers,omitempty"` + IsSharesURLs bool `json:"isSharesURLs,omitempty"` } // ToIndicatorsMap converts a ProxySettingInputs to a map from a proxy setting key to the proxy setting struct itself @@ -82,3 +95,21 @@ func (ids ValuesIDs) ToIndicatorsMap() map[string]string { return ret } + +func (inputs TagsInputs) ToIndicatorsMap() map[string]TagInput { + ret := make(map[string]TagInput) + for _, input := range inputs { + ret[input.Key] = input + } + + return ret +} + +func (mtlsInputs MTLSSchemas) ToIndicatorMap() map[string]MTLSSchema { + mTLSs := make(map[string]MTLSSchema) + for _, mTLS := range mtlsInputs { + mTLSs[mTLS.Type] = mTLS + } + + return mTLSs +} diff --git a/internal/models/web-app-asset/schema.go b/internal/models/web-app-asset/schema.go index 5e223e60..e64ec8cd 100644 --- a/internal/models/web-app-asset/schema.go +++ b/internal/models/web-app-asset/schema.go @@ -1,7 +1,14 @@ package models +import ( + "encoding/base64" + "fmt" + webAPIAssetModels "github.com/CheckPointSW/terraform-provider-infinity-next/internal/models/web-api-asset" +) + const ( SourceIdentifierValueIDSeparator = ";;;" + FileDataFormat = "data:%s;base64,%s" ) // SchemaPracticeMode represents a PracticeMode field of a practice field of a @@ -30,3 +37,35 @@ type SchemaSourceIdentifier struct { Values []string `json:"values"` ValuesIDs []string `json:"values_ids"` } + +type SchemaTag struct { + ID string `json:"id,omitempty"` + Key string `json:"key"` + Value string `json:"value"` +} + +// MTLSSchema represents a field of web application asset as it is saved in the state file +// this structure is aligned with the input schema (see web-app-asset.go file) +type MTLSSchema struct { + FilenameID string `json:"filename_id,omitempty"` + Filename string `json:"filename,omitempty"` + CertificateType string `json:"certificate_type,omitempty"` + DataID string `json:"data_id,omitempty"` + Data string `json:"data"` + Type string `json:"type,omitempty"` + EnableID string `json:"enable_id,omitempty"` + Enable bool `json:"enable,omitempty"` +} + +type MTLSSchemas []MTLSSchema + +func NewFileSchemaEncode(filename, fileData, mTLSType, certificateType string, fileEnable bool) MTLSSchema { + b64Data := base64.StdEncoding.EncodeToString([]byte(fileData)) + data := fmt.Sprintf(FileDataFormat, webAPIAssetModels.FileExtensionToMimeType(certificateType), b64Data) + return MTLSSchema{ + Filename: filename, + Data: data, + Type: mTLSType, + Enable: fileEnable, + } +} diff --git a/internal/models/web-app-asset/update.go b/internal/models/web-app-asset/update.go index 8625f932..1c68e6b6 100644 --- a/internal/models/web-app-asset/update.go +++ b/internal/models/web-app-asset/update.go @@ -9,11 +9,11 @@ type UpdateSourceIdentifierValue struct { // UpdateSourceIdentifier represents the input for updating an existing proxy setting field of an existing WebApplicationAsset object type UpdateSourceIdentifier struct { - ID string `json:"id"` - SourceIdentifier string `json:"sourceIdentifier"` - AddValues []string `json:"addValues"` - RemoveValues []string `json:"removeValues"` - UpdateValues []string `json:"updateValues"` + ID string `json:"id"` + SourceIdentifier string `json:"sourceIdentifier"` + AddValues []string `json:"addValues"` + RemoveValues []string `json:"removeValues"` + UpdateValues []UpdateSourceIdentifierValue `json:"updateValues"` } // AddSourceIdentifier represents the input for adding a source identifier field to an existing WebApplicationAsset object @@ -56,6 +56,13 @@ type AddPracticeWrapper struct { Triggers []string `json:"triggers"` } +type AddTag struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type AddTags []AddTag + // UpdateWebApplicationAssetInput represents the input for updating an existing WebApplicationAsset object type UpdateWebApplicationAssetInput struct { Name string `json:"name,omitempty"` @@ -65,6 +72,8 @@ type UpdateWebApplicationAssetInput struct { RemoveProfiles []string `json:"removeProfiles,omitempty"` AddBehaviors []string `json:"addBehaviors,omitempty"` RemoveBehaviors []string `json:"removeBehaviors,omitempty"` + AddTags AddTags `json:"addTags,omitempty"` + RemoveTags []string `json:"removeTags,omitempty"` State string `json:"state,omitempty"` AddProxySetting []AddProxySetting `json:"addProxySetting,omitempty"` RemoveProxySetting []string `json:"removeProxySetting,omitempty"` @@ -76,4 +85,5 @@ type UpdateWebApplicationAssetInput struct { AddSourceIdentifiers []AddSourceIdentifier `json:"addSourceIdentifiers,omitempty"` RemoveSourceIdentifiers []string `json:"removeSourceIdentifiers,omitempty"` UpdateSourceIdentifiers []UpdateSourceIdentifier `json:"updateSourceIdentifiers,omitempty"` + IsSharesURLs bool `json:"isSharesURLs,omitempty"` } diff --git a/internal/models/web-app-practice/input.go b/internal/models/web-app-practice/input.go index 26cd8002..66db5876 100644 --- a/internal/models/web-app-practice/input.go +++ b/internal/models/web-app-practice/input.go @@ -24,7 +24,7 @@ type WebApplicationPracticeWebBotInput struct { ValidURIs []string `json:"validURIs,omitempty"` } -type WebApplicationPractcieIPSInput struct { +type WebApplicationPracticeIPSInput struct { ID string `json:"id,omitempty"` PerformanceImpact string `json:"performanceImpact,omitempty"` SeverityLevel string `json:"severityLevel,omitempty"` @@ -34,10 +34,30 @@ type WebApplicationPractcieIPSInput struct { LowConfidence string `json:"lowConfidence,omitempty"` } +type FileSecurityInput struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severityLevel,omitempty"` + HighConfidence string `json:"highConfidence,omitempty"` + MediumConfidence string `json:"mediumConfidence,omitempty"` + LowConfidence string `json:"lowConfidence,omitempty"` + AllowFileSizeLimit string `json:"allowFileSizeLimit,omitempty"` + FileSizeLimit int `json:"fileSizeLimit,omitempty"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit,omitempty"` + FilesWithoutName string `json:"filesWithoutName,omitempty"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction,omitempty"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit,omitempty"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive,omitempty"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive,omitempty"` + AllowFileType bool `json:"allowFileType,omitempty"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation,omitempty"` +} + type CreateWebApplicationPracticeInput struct { - Name string `json:"name"` - Visibility string `json:"visibility"` - IPS WebApplicationPractcieIPSInput `json:"IPS,omitempty"` - WebBot WebApplicationPracticeWebBotInput `json:"WebBot,omitempty"` - WebAttacks WebApplicationPracticeWebAttacksInput `json:"WebAttacks,omitempty"` + Name string `json:"name"` + Visibility string `json:"visibility"` + IPS WebApplicationPracticeIPSInput `json:"IPS,omitempty"` + WebBot WebApplicationPracticeWebBotInput `json:"WebBot,omitempty"` + WebAttacks WebApplicationPracticeWebAttacksInput `json:"WebAttacks,omitempty"` + FileSecurity FileSecurityInput `json:"FileSecurity,omitempty"` } diff --git a/internal/models/web-app-practice/practice.go b/internal/models/web-app-practice/practice.go index 24c7a4f3..630907bc 100644 --- a/internal/models/web-app-practice/practice.go +++ b/internal/models/web-app-practice/practice.go @@ -45,14 +45,35 @@ type WebApplicationIPS struct { LowConfidence string `json:"lowConfidence"` } +type FileSecurity struct { + ID string `json:"id"` + SeverityLevel string `json:"severityLevel"` + HighConfidence string `json:"highConfidence"` + MediumConfidence string `json:"mediumConfidence"` + LowConfidence string `json:"lowConfidence"` + AllowFileSizeLimit string `json:"allowFileSizeLimit"` + FileSizeLimit int `json:"fileSizeLimit"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit"` + FilesWithoutName string `json:"filesWithoutName"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive"` + AllowFileType bool `json:"allowFileType"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation"` +} + type WebApplicationPractice struct { ID string `json:"id"` Name string `json:"name"` Category string `json:"category"` PracticeType string `json:"practiceType"` + Visibility string `json:"visibility"` IPS WebApplicationIPS `json:"IPS"` WebBot WebApplicationWebBot `json:"WebBot"` WebAttacks WebApplicationWebAttacks `json:"WebAttacks"` + FileSecurity FileSecurity `json:"FileSecurity"` Default bool `json:"default"` } diff --git a/internal/models/web-app-practice/schema.go b/internal/models/web-app-practice/schema.go index 72176878..ae938f38 100644 --- a/internal/models/web-app-practice/schema.go +++ b/internal/models/web-app-practice/schema.go @@ -40,6 +40,25 @@ type WebApplicationPracticeWebAttacksSchema struct { AdvancedSetting []WebApplicationPracticeAdvancedSettingSchema `json:"advanced_setting,omitempty"` } +type FileSecuritySchema struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severity_level,omitempty"` + HighConfidence string `json:"high_confidence,omitempty"` + MediumConfidence string `json:"medium_confidence,omitempty"` + LowConfidence string `json:"low_confidence,omitempty"` + AllowFileSizeLimit string `json:"allow_file_size_limit,omitempty"` + FileSizeLimit int `json:"file_size_limit,omitempty"` + FileSizeLimitUnit string `json:"file_size_limit_unit,omitempty"` + FilesWithoutName string `json:"files_without_name,omitempty"` + RequiredArchiveExtraction bool `json:"required_archive_extraction,omitempty"` + ArchiveFileSizeLimit int `json:"archive_file_size_limit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archive_file_size_limit_unit,omitempty"` + AllowArchiveWithinArchive string `json:"allow_archive_within_archive,omitempty"` + AllowAnUnopenedArchive string `json:"allow_an_unopened_archive,omitempty"` + AllowFileType bool `json:"allow_file_type,omitempty"` + RequiredThreatEmulation bool `json:"required_threat_emulation,omitempty"` +} + func (schemaIDs IDs) ToIndicatorsMap() map[string]string { ret := make(map[string]string) for _, id := range schemaIDs { diff --git a/internal/models/web-app-practice/update.go b/internal/models/web-app-practice/update.go index f71f059b..99e5964e 100644 --- a/internal/models/web-app-practice/update.go +++ b/internal/models/web-app-practice/update.go @@ -1,11 +1,20 @@ package models +type UpdateURIInput struct { + ID string `json:"id"` + URI string `json:"uri"` +} + +type UpdateURIsInputs []UpdateURIInput + type UpdateWebApplicationPracticeWebBotInput struct { - ID string `json:"id"` - AddInjectURIs []string `json:"addInjectURIs,omitempty"` - RemoveInjectURIsIDs []string `json:"removeInjectURIs,omitempty"` - AddValidURIs []string `json:"addValidURIs,omitempty"` - RemoveValidURIsIDs []string `json:"removeValidURIs,omitempty"` + ID string `json:"id"` + AddInjectURIs []string `json:"addInjectURIs,omitempty"` + RemoveInjectURIsIDs []string `json:"removeInjectURIs,omitempty"` + UpdateInjectURIs UpdateURIsInputs `json:"updateInjectURIs,omitempty"` + AddValidURIs []string `json:"addValidURIs,omitempty"` + RemoveValidURIsIDs []string `json:"removeValidURIs,omitempty"` + UpdateValidURIs UpdateURIsInputs `json:"updateValidURIs,omitempty"` } type UpdateWebApplicationPracticeAdvancedSettingInput struct { @@ -36,9 +45,30 @@ type UpdateWebApplicationPracticeIPSInput struct { LowConfidence string `json:"lowConfidence,omitempty"` } +type UpdateFileSecurity struct { + ID string `json:"id,omitempty"` + SeverityLevel string `json:"severityLevel,omitempty"` + HighConfidence string `json:"highConfidence,omitempty"` + MediumConfidence string `json:"mediumConfidence,omitempty"` + LowConfidence string `json:"lowConfidence,omitempty"` + AllowFileSizeLimit string `json:"allowFileSizeLimit,omitempty"` + FileSizeLimit int `json:"fileSizeLimit,omitempty"` + FileSizeLimitUnit string `json:"fileSizeLimitUnit,omitempty"` + FilesWithoutName string `json:"filesWithoutName,omitempty"` + RequiredArchiveExtraction bool `json:"requiredArchiveExtraction,omitempty"` + ArchiveFileSizeLimit int `json:"archiveFileSizeLimit,omitempty"` + ArchiveFileSizeLimitUnit string `json:"archiveFileSizeLimitUnit,omitempty"` + AllowArchiveWithinArchive string `json:"allowArchiveWithinArchive,omitempty"` + AllowAnUnopenedArchive string `json:"allowAnUnopenedArchive,omitempty"` + AllowFileType bool `json:"allowFileType,omitempty"` + RequiredThreatEmulation bool `json:"requiredThreatEmulation,omitempty"` +} + type UpdateWebApplicationPracticeInput struct { - Name string `json:"name,omitempty"` - IPS UpdateWebApplicationPracticeIPSInput `json:"IPS,omitempty"` - WebAttacks UpdateWebApplicationPracticeWebAttacksInput `json:"WebAttacks,omitempty"` - WebBot UpdateWebApplicationPracticeWebBotInput `json:"WebBot,omitempty"` + Name string `json:"name,omitempty"` + Visibility string `json:"visibility,omitempty"` + IPS UpdateWebApplicationPracticeIPSInput `json:"IPS,omitempty"` + WebAttacks UpdateWebApplicationPracticeWebAttacksInput `json:"WebAttacks,omitempty"` + WebBot UpdateWebApplicationPracticeWebBotInput `json:"WebBot,omitempty"` + FileSecurity UpdateFileSecurity `json:"FileSecurity,omitempty"` } diff --git a/internal/models/web-user-response/behavior.go b/internal/models/web-user-response/behavior.go index 2a8bb61a..00d68e22 100644 --- a/internal/models/web-user-response/behavior.go +++ b/internal/models/web-user-response/behavior.go @@ -6,6 +6,7 @@ type WebUserResponseBehavior struct { Mode string `json:"mode"` MessageTitle string `json:"messageTitle"` MessageBody string `json:"messageBody"` + Visibility string `json:"visibility"` HTTPResponseCode int `json:"httpResponseCode"` RedirectURL string `json:"redirectURL"` XEventID bool `json:"xEventId"` diff --git a/internal/models/web-user-response/update.go b/internal/models/web-user-response/update.go index 277ecde3..87f65810 100644 --- a/internal/models/web-user-response/update.go +++ b/internal/models/web-user-response/update.go @@ -5,6 +5,7 @@ type UpdateWebUserResponseBehaviorInput struct { Mode string `json:"mode"` MessageTitle string `json:"messageTitle,omitempty"` MessageBody string `json:"messageBody,omitempty"` + Visibility string `json:"visibility,omitempty"` HTTPResponseCode int `json:"httpResponseCode,omitempty"` RedirectURL string `json:"redirectURL,omitempty"` XEventID bool `json:"xEventId"` diff --git a/internal/resources/appsec-gateway-profile.go b/internal/resources/appsec-gateway-profile.go index 90f48a08..5e71e79c 100644 --- a/internal/resources/appsec-gateway-profile.go +++ b/internal/resources/appsec-gateway-profile.go @@ -12,9 +12,12 @@ import ( ) func ResourceAppSecGatewayProfile() *schema.Resource { + validateSubType := validation.ToDiagFunc(validation.StringInSlice([]string{appsecgatewayprofile.ProfileSubTypeAws, appsecgatewayprofile.ProfileSubTypeAzure, appsecgatewayprofile.ProfileSubTypeVMware, appsecgatewayprofile.ProfileSubTypeHyperV}, false)) + validateUpgradeMode := validation.ToDiagFunc(validation.StringInSlice([]string{appsecgatewayprofile.UpgradeModeAutomatic, appsecgatewayprofile.UpgradeModeManual, appsecgatewayprofile.UpgradeModeScheduled}, false)) + validateUpgradeTimeType := validation.ToDiagFunc(validation.StringInSlice([]string{appsecgatewayprofile.ScheduleTypeDaily, appsecgatewayprofile.ScheduleTypeDaysInWeek, appsecgatewayprofile.ScheduleTypeDaysInMonth}, false)) return &schema.Resource{ Description: "CloudGuard Application Security Gateway profile is deployed as a VM that runs on a Check Point Gaia OS " + - "with a reverse proxy and Check Point Nano-Agent", + "with a reverse proxy and Check Point Nano-Agent.", CreateContext: resourceAppSecGatewayProfileCreate, ReadContext: resourceAppSecGatewayProfileRead, @@ -54,10 +57,10 @@ func ResourceAppSecGatewayProfile() *schema.Resource { Computed: true, }, "profile_sub_type": { - Type: schema.TypeString, - Description: "The environment of deployment for the AppSec VM: Aws, Azure, VMware or HyperV", - Required: true, - ValidateFunc: validation.StringInSlice([]string{appsecgatewayprofile.ProfileSubTypeAws, appsecgatewayprofile.ProfileSubTypeAzure, appsecgatewayprofile.ProfileSubTypeVMware, appsecgatewayprofile.ProfileSubTypeHyperV}, false), + Type: schema.TypeString, + Description: "The environment of deployment for the AppSec VM: Aws, Azure, VMware or HyperV", + Required: true, + ValidateDiagFunc: validateSubType, }, "additional_settings": { Type: schema.TypeMap, @@ -80,13 +83,13 @@ func ResourceAppSecGatewayProfile() *schema.Resource { "The default is Automatic", Optional: true, Default: appsecgatewayprofile.UpgradeModeAutomatic, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{appsecgatewayprofile.UpgradeModeAutomatic, appsecgatewayprofile.UpgradeModeManual, appsecgatewayprofile.UpgradeModeScheduled}, false)), + ValidateDiagFunc: validateUpgradeMode, }, "upgrade_time_schedule_type": { Type: schema.TypeString, - Description: "The schedule type in case upgrade mode is scheduled: DaysInWeek", + Description: "The schedule type in case upgrade mode is scheduled: DaysInWeek, DaysInMonth or Daily", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"DaysInWeek"}, false)), + ValidateDiagFunc: validateUpgradeTimeType, }, "upgrade_time_hour": { Type: schema.TypeString, @@ -106,6 +109,14 @@ func ResourceAppSecGatewayProfile() *schema.Resource { Type: schema.TypeString, }, }, + "upgrade_time_days": { + Type: schema.TypeSet, + Description: "The days of the month of the upgrade time schedule", + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, "reverseproxy_upstream_timeout": { Type: schema.TypeInt, Description: "Sets the reverse proxy upstream timeout in seconds", diff --git a/internal/resources/appsec-gateway-profile/create.go b/internal/resources/appsec-gateway-profile/create.go index f3f9e401..751663e2 100644 --- a/internal/resources/appsec-gateway-profile/create.go +++ b/internal/resources/appsec-gateway-profile/create.go @@ -72,6 +72,7 @@ func handleScheduledUpgradeMode(d *schema.ResourceData) models.UpgradeTimeInput res.Time = d.Get("upgrade_time_hour").(string) res.Duration = d.Get("upgrade_time_duration").(int) res.WeekDays = utils.MustResourceDataCollectionToSlice[string](d, "upgrade_time_week_days") + res.Days = utils.MustResourceDataCollectionToSlice[int](d, "upgrade_time_days") return res } @@ -104,6 +105,9 @@ func NewAppSecGatewayProfile(ctx context.Context, c *api.Client, input models.Cr ... on ScheduleDaysInWeek { weekDays } + ... on ScheduleDaysInMonth { + days + } } reverseProxyUpstreamTimeout reverseProxyAdditionalSettings { diff --git a/internal/resources/appsec-gateway-profile/read.go b/internal/resources/appsec-gateway-profile/read.go index d81609da..6098bbd0 100644 --- a/internal/resources/appsec-gateway-profile/read.go +++ b/internal/resources/appsec-gateway-profile/read.go @@ -25,6 +25,7 @@ func ReadCloudGuardAppSecGatewayProfileToResourceData(profile models.CloudGuardA d.Set("upgrade_time_hour", profile.UpgradeTime.Time) d.Set("upgrade_time_duration", profile.UpgradeTime.Duration) d.Set("upgrade_time_week_days", profile.UpgradeTime.WeekDays) + d.Set("upgrade_time_days", profile.UpgradeTime.Days) } d.Set("reverseproxy_upstream_timeout", profile.ReverseProxyUpstreamTimeout) @@ -82,6 +83,9 @@ func GetCloudGuardAppSecGatewayProfile(ctx context.Context, c *api.Client, id st ... on ScheduleDaysInWeek { weekDays } + ... on ScheduleDaysInMonth { + days + } } reverseProxyUpstreamTimeout reverseProxyAdditionalSettings { diff --git a/internal/resources/appsec-gateway-profile/update.go b/internal/resources/appsec-gateway-profile/update.go index a8671cad..efd5ca00 100644 --- a/internal/resources/appsec-gateway-profile/update.go +++ b/internal/resources/appsec-gateway-profile/update.go @@ -69,6 +69,10 @@ func UpdateCloudGuardAppSecGatewayProfileInputFromResourceData(d *schema.Resourc upgradeTime.WeekDays = newUpgradeTimeWeekDays } + if _, newUpgradeTime, hasChange := utils.MustGetChange[models.UpdateUpgradeTimeInput](d, "upgrade_time"); hasChange { + upgradeTime = newUpgradeTime + } + res.UpgradeTime = &upgradeTime } diff --git a/internal/resources/docker-profile/update.go b/internal/resources/docker-profile/update.go index 26eed705..115dcceb 100644 --- a/internal/resources/docker-profile/update.go +++ b/internal/resources/docker-profile/update.go @@ -51,14 +51,14 @@ func UpdateDockerProfileInputFromResourceData(d *schema.ResourceData) (models.Do return res, nil } -func handleUpdateAdditionalSetting(d *schema.ResourceData, settingsKey, setttingsIDsKey string) ([]models.KeyValueInput, []models.KeyValueUpdateInput, []string) { +func handleUpdateAdditionalSetting(d *schema.ResourceData, settingsKey, settingsIDsKey string) ([]models.KeyValueInput, []models.KeyValueUpdateInput, []string) { if oldSettingMap, newSettingMap, hasChange := utils.MustGetChange[map[string]any](d, settingsKey); hasChange { - // get reverse proxy additional settings ids - each in the format: "" + // get reverse proxy additional settings ids - each in the format: "" additionalSettingsIDsMap := make(map[string]string) - additionalSettingsIDsInterface := d.Get(setttingsIDsKey).(*schema.Set).List() - for _, intefaceUnparsedID := range additionalSettingsIDsInterface { + additionalSettingsIDsInterface := d.Get(settingsIDsKey).(*schema.Set).List() + for _, interfaceUnparsedID := range additionalSettingsIDsInterface { // parse ID - keyAndID := strings.Split(intefaceUnparsedID.(string), additonalSettingsIDSeparator) + keyAndID := strings.Split(interfaceUnparsedID.(string), additonalSettingsIDSeparator) key, settingID := keyAndID[0], keyAndID[1] additionalSettingsIDsMap[key] = settingID } diff --git a/internal/resources/embedded-profile.go b/internal/resources/embedded-profile.go index 2570a82a..0246f53a 100644 --- a/internal/resources/embedded-profile.go +++ b/internal/resources/embedded-profile.go @@ -12,6 +12,8 @@ import ( ) func ResourceEmbeddedProfile() *schema.Resource { + validateUpgradeMode := validation.ToDiagFunc(validation.StringInSlice([]string{embeddedprofile.UpgradeModeAutomatic, embeddedprofile.UpgradeModeManual, embeddedprofile.UpgradeModeScheduled}, false)) + validateUpgradeTimeType := validation.ToDiagFunc(validation.StringInSlice([]string{embeddedprofile.ScheduleTypeDaily, embeddedprofile.ScheduleTypeDaysInWeek, embeddedprofile.ScheduleTypeDaysInMonth}, false)) return &schema.Resource{ Description: "Embedded profile", @@ -70,13 +72,13 @@ func ResourceEmbeddedProfile() *schema.Resource { "The default is Automatic", Optional: true, Default: embeddedprofile.UpgradeModeAutomatic, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{embeddedprofile.UpgradeModeAutomatic, embeddedprofile.UpgradeModeManual, embeddedprofile.UpgradeModeScheduled}, false)), + ValidateDiagFunc: validateUpgradeMode, }, "upgrade_time_schedule_type": { Type: schema.TypeString, - Description: "The schedule type in case upgrade mode is scheduled: DaysInWeek", + Description: "The schedule type in case upgrade mode is scheduled: DaysInWeek, DaysInMonth or Daily", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"DaysInWeek"}, false)), + ValidateDiagFunc: validateUpgradeTimeType, }, "upgrade_time_hour": { Type: schema.TypeString, @@ -96,6 +98,14 @@ func ResourceEmbeddedProfile() *schema.Resource { Type: schema.TypeString, }, }, + "upgrade_time_days": { + Type: schema.TypeSet, + Description: "The days of the month of the upgrade time schedule", + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, "max_number_of_agents": { Type: schema.TypeInt, Description: "Sets the maximum number of agents that can be connected to this profile", diff --git a/internal/resources/embedded-profile/create.go b/internal/resources/embedded-profile/create.go index 5241454c..4ebf357a 100644 --- a/internal/resources/embedded-profile/create.go +++ b/internal/resources/embedded-profile/create.go @@ -74,6 +74,15 @@ func handleScheduledUpgradeMode(d *schema.ResourceData) models.ScheduleTimeInput } } + if v, ok := d.GetOk("upgrade_time_days"); ok { + days := v.(*schema.Set).List() + res.Days = make([]int, 0, len(days)) + for _, dayInterface := range days { + day := dayInterface.(int) + res.Days = append(res.Days, day) + } + } + return res } @@ -103,6 +112,9 @@ func NewEmbeddedProfile(ctx context.Context, c *api.Client, input models.CreateE ... on ScheduleDaysInWeek { weekDays } + ... on ScheduleDaysInMonth { + days + } } onlyDefinedApplications } diff --git a/internal/resources/embedded-profile/read.go b/internal/resources/embedded-profile/read.go index 6c4e5730..824da23f 100644 --- a/internal/resources/embedded-profile/read.go +++ b/internal/resources/embedded-profile/read.go @@ -25,6 +25,7 @@ func ReadEmbeddedProfileToResourceData(profile models.EmbeddedProfile, d *schema d.Set("upgrade_time_hour", profile.UpgradeTime.Time) d.Set("upgrade_time_duration", profile.UpgradeTime.Duration) d.Set("upgrade_time_week_days", profile.UpgradeTime.WeekDays) + d.Set("upgrade_time_days", profile.UpgradeTime.Days) } d.Set("max_number_of_agents", profile.Authentication.MaxNumberOfAgents) @@ -68,6 +69,9 @@ func GetEmbeddedProfile(ctx context.Context, c *api.Client, id string) (models.E ... on ScheduleDaysInWeek { weekDays } + ... on ScheduleDaysInMonth { + days + } } onlyDefinedApplications } diff --git a/internal/resources/embedded-profile/update.go b/internal/resources/embedded-profile/update.go index 598f1fb9..75e8f4cd 100644 --- a/internal/resources/embedded-profile/update.go +++ b/internal/resources/embedded-profile/update.go @@ -73,6 +73,10 @@ func UpdateEmbeddedProfileInputFromResourceData(d *schema.ResourceData) (models. upgradeTime.WeekDays = newUpgradeTimeWeekDays } + if _, newUpgradeTimeDays, hasChange := utils.GetChangeWithParse(d, "upgrade_time_days", utils.MustSchemaCollectionToSlice[int]); hasChange { + upgradeTime.Days = newUpgradeTimeDays + } + res.UpgradeTime = &upgradeTime } @@ -83,14 +87,14 @@ func UpdateEmbeddedProfileInputFromResourceData(d *schema.ResourceData) (models. return res, nil } -func handleUpdateAdditionalSetting(d *schema.ResourceData, settingsKey, setttingsIDsKey string) ([]models.KeyValueInput, []models.KeyValueUpdateInput, []string) { +func handleUpdateAdditionalSetting(d *schema.ResourceData, settingsKey, settingsIDsKey string) ([]models.KeyValueInput, []models.KeyValueUpdateInput, []string) { if oldSettingMap, newSettingMap, hasChange := utils.GetChangeWithParse(d, settingsKey, utils.MustValueAs[map[string]any]); hasChange { - // get reverse proxy additional settings ids - each in the format: "" + // get reverse proxy additional settings ids - each in the format: "" additionalSettingsIDsMap := make(map[string]string) - additionalSettingsIDsInterface := d.Get(setttingsIDsKey).(*schema.Set).List() - for _, intefaceUnparsedID := range additionalSettingsIDsInterface { + additionalSettingsIDsInterface := d.Get(settingsIDsKey).(*schema.Set).List() + for _, interfaceUnparsedID := range additionalSettingsIDsInterface { // parse ID - keyAndID := strings.Split(intefaceUnparsedID.(string), additonalSettingsIDSeparator) + keyAndID := strings.Split(interfaceUnparsedID.(string), additonalSettingsIDSeparator) key, settingID := keyAndID[0], keyAndID[1] additionalSettingsIDsMap[key] = settingID } diff --git a/internal/resources/exceptions.go b/internal/resources/exceptions.go index 7c8ddc1d..e6256221 100644 --- a/internal/resources/exceptions.go +++ b/internal/resources/exceptions.go @@ -2,7 +2,6 @@ package resources import ( "context" - "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/resources/exceptions" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/utils" @@ -77,6 +76,8 @@ func matchSchema(nestLevel int) *schema.Resource { } func ResourceExceptions() *schema.Resource { + validateVisibility := validation.ToDiagFunc( + validation.StringInSlice([]string{visibilityShared, visibilityLocal}, false)) return &schema.Resource{ Description: "Exceptions allows overriding the AppSec ML engine decision based on specific parameters", @@ -98,6 +99,13 @@ func ResourceExceptions() *schema.Resource { Description: "The name of the resource, also acts as its unique ID", Required: true, }, + "visibility": { + Type: schema.TypeString, + Description: "The visibility of the exception: Shared or Local", + Default: "Shared", + Optional: true, + ValidateDiagFunc: validateVisibility, + }, "exception": { Type: schema.TypeSet, Description: "Overrides AppSec ML engine decision based on match and action", diff --git a/internal/resources/exceptions/create.go b/internal/resources/exceptions/create.go index d6101a5b..b66027ae 100644 --- a/internal/resources/exceptions/create.go +++ b/internal/resources/exceptions/create.go @@ -71,9 +71,9 @@ func mapToExceptionObjectInput(exceptionMap map[string]any) models.ExceptionObje } ret.Actions = []string{string(actionBytes)} - matchExprssion := utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](exceptionMap["match"]), mapToSchemaMatchExpression) - if len(matchExprssion) > 0 { - inputMatch := ParseSchemaMatchToInput(matchExprssion[0]) + matchExpression := utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](exceptionMap["match"]), mapToSchemaMatchExpression) + if len(matchExpression) > 0 { + inputMatch := ParseSchemaMatchToInput(matchExpression[0]) matchBytes, err := json.Marshal(inputMatch) if err != nil { fmt.Printf("[WARN] failed to marshal MatchExpression struct: %+v", err) @@ -89,7 +89,7 @@ func CreateExceptionBehaviorInputFromResourceData(d *schema.ResourceData) (model var res models.CreateExceptionBehaviorInput res.Name = d.Get("name").(string) - res.Visibility = "Shared" + res.Visibility = d.Get("visibility").(string) res.Exceptions = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "exception"), mapToExceptionObjectInput) return res, nil @@ -103,6 +103,7 @@ func NewExceptionBehavior(ctx context.Context, c *api.Client, input models.Creat newExceptionBehavior(ownerId: $ownerId, practiceId: $practiceId, behaviorInput: $behaviorInput) { id name + visibility exceptions { id match diff --git a/internal/resources/exceptions/read.go b/internal/resources/exceptions/read.go index 6815e64b..2790fb40 100644 --- a/internal/resources/exceptions/read.go +++ b/internal/resources/exceptions/read.go @@ -16,6 +16,7 @@ func GetExceptionBehavior(ctx context.Context, c *api.Client, id string) (models getExceptionBehavior(id: "`+id+`") { id name + visibility exceptions { id match @@ -44,6 +45,7 @@ func GetExceptionBehavior(ctx context.Context, c *api.Client, id string) (models func ReadExceptionBehaviorToResourceData(behavior models.ExceptionBehavior, d *schema.ResourceData) error { d.SetId(behavior.ID) d.Set("name", behavior.Name) + d.Set("visibility", behavior.Visibility) schemaExceptions := behavior.Exceptions.ToSchema() schemaExceptionsMap, err := utils.UnmarshalAs[[]map[string]any](schemaExceptions) if err != nil { diff --git a/internal/resources/exceptions/update.go b/internal/resources/exceptions/update.go index 2a4b0ecd..9335a023 100644 --- a/internal/resources/exceptions/update.go +++ b/internal/resources/exceptions/update.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func parseSchemaExceptions(exceptionsFromResourceData any) []models.ExceptionObjectInput { +func parseSchemaExceptions(exceptionsFromResourceData any) models.ExceptionObjectInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](exceptionsFromResourceData), mapToExceptionObjectInput) } @@ -20,10 +20,15 @@ func UpdateExceptionBehaviorInputFromResourceData(d *schema.ResourceData) (model res.Name = newName } + if _, newVisibility, hasChange := utils.MustGetChange[string](d, "visibility"); hasChange { + res.Visibility = newVisibility + } + if oldExceptions, newExceptions, hasChange := utils.GetChangeWithParse(d, "exception", parseSchemaExceptions); hasChange { exceptionsToAdd, exceptionsToRemove := utils.SlicesDiff(oldExceptions, newExceptions) res.AddExceptions = utils.Map(exceptionsToAdd, utils.MustUnmarshalAs[models.AddExceptionObjectInput, models.ExceptionObjectInput]) res.RemoveExceptions = utils.Map(exceptionsToRemove, func(toRemove models.ExceptionObjectInput) string { return toRemove.ID }) + res.UpdateExceptions = models.ExceptionObjectActionsUpdate{} } return res, nil diff --git a/internal/resources/kubernetes-profile.go b/internal/resources/kubernetes-profile.go index ff0535d8..656f48d8 100644 --- a/internal/resources/kubernetes-profile.go +++ b/internal/resources/kubernetes-profile.go @@ -11,7 +11,16 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +const ( + profileSubTypeAppSec string = "AppSec" + profileSubTypeAccessControl string = "AccessControl" + profileSubTypeKong string = "Kong" + profileSubTypeIstio string = "Istio" +) + func ResourceKubernetesProfile() *schema.Resource { + validateSubType := validation.ToDiagFunc( + validation.StringInSlice([]string{profileSubTypeAppSec, profileSubTypeAccessControl, profileSubTypeKong, profileSubTypeIstio}, false)) return &schema.Resource{ Description: "Kubernetes profile", @@ -46,8 +55,9 @@ func ResourceKubernetesProfile() *schema.Resource { }, "profile_sub_type": { Type: schema.TypeString, + Description: "The sub type of the profile (AppSec, AccessControl, Kong, Istio)", Required: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"AccessControl", "AppSec"}, false)), + ValidateDiagFunc: validateSubType, }, "additional_settings": { Type: schema.TypeMap, diff --git a/internal/resources/log-trigger.go b/internal/resources/log-trigger.go index 7880d602..7b660ff3 100644 --- a/internal/resources/log-trigger.go +++ b/internal/resources/log-trigger.go @@ -37,6 +37,16 @@ func ResourceLogTrigger() *schema.Resource { Default: "Standard", ValidateFunc: validation.StringInSlice([]string{"Standard", "Minimal", "Extended"}, false), }, + "compliance_warnings": { + Type: schema.TypeBool, + Default: true, + Optional: true, + }, + "compliance_violations": { + Type: schema.TypeBool, + Default: true, + Optional: true, + }, "access_control_allow_events": { Description: "Log Access Control accepts", Type: schema.TypeBool, @@ -122,6 +132,13 @@ func ResourceLogTrigger() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "syslog_protocol": { + Description: "Syslog protocol: UDP or TCP", + Type: schema.TypeString, + Optional: true, + Default: "UDP", + ValidateFunc: validation.StringInSlice([]string{"UDP", "TCP"}, false), + }, "syslog_port": { Type: schema.TypeInt, Optional: true, @@ -138,6 +155,13 @@ func ResourceLogTrigger() *schema.Resource { Type: schema.TypeInt, Optional: true, }, + "cef_protocol": { + Description: "CEF protocol: UDP or TCP", + Type: schema.TypeString, + Optional: true, + Default: "UDP", + ValidateFunc: validation.StringInSlice([]string{"UDP", "TCP"}, false), + }, }, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, diff --git a/internal/resources/log-trigger/create.go b/internal/resources/log-trigger/create.go index aaacb200..bcf3ef82 100644 --- a/internal/resources/log-trigger/create.go +++ b/internal/resources/log-trigger/create.go @@ -16,8 +16,8 @@ func CreateLogTriggerInputFromResourceData(d *schema.ResourceData) (models.Creat res.Verbosity = d.Get("verbosity").(string) res.AccessControlAllowEvents = d.Get("access_control_allow_events").(bool) res.AccessControlDropEvents = d.Get("access_control_drop_events").(bool) - res.ThreaPreventionDetectEvents = d.Get("threat_prevention_detect_events").(bool) - res.ThreaPreventionPreventEvents = d.Get("threat_prevention_prevent_events").(bool) + res.ThreatPreventionDetectEvents = d.Get("threat_prevention_detect_events").(bool) + res.ThreatPreventionPreventEvents = d.Get("threat_prevention_prevent_events").(bool) res.WebRequests = d.Get("web_requests").(bool) res.WebURLPath = d.Get("web_url_path").(bool) res.WebURLQuery = d.Get("web_url_query").(bool) @@ -31,10 +31,14 @@ func CreateLogTriggerInputFromResourceData(d *schema.ResourceData) (models.Creat res.ResponseCode = d.Get("response_code").(bool) res.LogToSyslog = d.Get("log_to_syslog").(bool) res.SyslogIPAddress = d.Get("syslog_ip_address").(string) + res.SyslogProtocol = d.Get("syslog_protocol").(string) res.SyslogPort = d.Get("syslog_port").(int) res.LogToCEF = d.Get("log_to_cef").(bool) res.CEFIPAddress = d.Get("cef_ip_address").(string) res.CEFPort = d.Get("cef_port").(int) + res.CEFProtocol = d.Get("cef_protocol").(string) + res.ComplianceWarnings = d.Get("compliance_warnings").(bool) + res.ComplianceViolations = d.Get("compliance_violations").(bool) return res, nil } @@ -48,6 +52,8 @@ func NewLogTrigger(ctx context.Context, c *api.Client, triggerInput models.Creat id name verbosity + complianceWarnings + complianceViolations acAllow acDrop tpDetect @@ -65,10 +71,12 @@ func NewLogTrigger(ctx context.Context, c *api.Client, triggerInput models.Creat responseCode logToSyslog syslogIpAddress + syslogProtocol syslogPortNum logToCef cefIpAddress cefPortNum + cefProtocol } } `, "newLogTrigger", vars) diff --git a/internal/resources/log-trigger/read.go b/internal/resources/log-trigger/read.go index 8f054894..2b4df8d2 100644 --- a/internal/resources/log-trigger/read.go +++ b/internal/resources/log-trigger/read.go @@ -16,8 +16,8 @@ func ReadLogTriggerToResourceData(logTrigger models.LogTrigger, d *schema.Resour d.Set("verbosity", logTrigger.Verbosity) d.Set("access_control_allow_events", logTrigger.AccessControlAllowEvents) d.Set("access_control_drop_events", logTrigger.AccessControlDropEvents) - d.Set("threat_prevention_detect_events", logTrigger.ThreaPreventionDetectEvents) - d.Set("threat_prevention_prevent_events", logTrigger.ThreaPreventionPreventEvents) + d.Set("threat_prevention_detect_events", logTrigger.ThreatPreventionDetectEvents) + d.Set("threat_prevention_prevent_events", logTrigger.ThreatPreventionPreventEvents) d.Set("web_requests", logTrigger.WebRequests) d.Set("web_url_path", logTrigger.WebURLPath) d.Set("web_url_query", logTrigger.WebURLQuery) @@ -31,10 +31,14 @@ func ReadLogTriggerToResourceData(logTrigger models.LogTrigger, d *schema.Resour d.Set("response_code", logTrigger.ResponseCode) d.Set("log_to_syslog", logTrigger.LogToSyslog) d.Set("syslog_ip_address", logTrigger.SyslogIPAddress) + d.Set("syslog_protocol", logTrigger.SyslogProtocol) d.Set("syslog_port", logTrigger.SyslogPort) d.Set("log_to_cef", logTrigger.LogToCEF) d.Set("cef_ip_address", logTrigger.CEFIPAddress) d.Set("cef_port", logTrigger.CEFPort) + d.Set("cef_protocol", logTrigger.CEFProtocol) + d.Set("compliance_warnings", logTrigger.ComplianceWarnings) + d.Set("compliance_violations", logTrigger.ComplianceViolations) return nil } @@ -46,6 +50,8 @@ func GetLogTrigger(ctx context.Context, c *api.Client, id string) (models.LogTri id name verbosity + complianceWarnings + complianceViolations acAllow acDrop tpDetect @@ -63,10 +69,12 @@ func GetLogTrigger(ctx context.Context, c *api.Client, id string) (models.LogTri responseCode logToSyslog syslogIpAddress + syslogProtocol syslogPortNum logToCef cefIpAddress cefPortNum + cefProtocol } } `, "getLogTrigger") diff --git a/internal/resources/log-trigger/update.go b/internal/resources/log-trigger/update.go index f0a1cec6..772a69da 100644 --- a/internal/resources/log-trigger/update.go +++ b/internal/resources/log-trigger/update.go @@ -14,10 +14,12 @@ func UpdateLogTriggerInputFromResourceData(d *schema.ResourceData) (models.Updat var ret models.UpdateLogTriggerInput ret.Name = d.Get("name").(string) ret.Verbosity = d.Get("verbosity").(string) + ret.ComplianceWarnings = d.Get("compliance_warnings").(bool) + ret.ComplianceViolations = d.Get("compliance_violations").(bool) ret.AccessControlAllowEvents = d.Get("access_control_allow_events").(bool) ret.AccessControlDropEvents = d.Get("access_control_drop_events").(bool) - ret.ThreaPreventionDetectEvents = d.Get("threat_prevention_detect_events").(bool) - ret.ThreaPreventionPreventEvents = d.Get("threat_prevention_prevent_events").(bool) + ret.ThreatPreventionDetectEvents = d.Get("threat_prevention_detect_events").(bool) + ret.ThreatPreventionPreventEvents = d.Get("threat_prevention_prevent_events").(bool) ret.WebRequests = d.Get("web_requests").(bool) ret.WebURLPath = d.Get("web_url_path").(bool) ret.WebURLQuery = d.Get("web_url_query").(bool) @@ -39,6 +41,10 @@ func UpdateLogTriggerInputFromResourceData(d *schema.ResourceData) (models.Updat ret.SyslogIPAddress = syslogIPAddress } + if _, syslogProtocol, hasChange := utils.MustGetChange[string](d, "syslog_protocol"); hasChange { + ret.SyslogProtocol = syslogProtocol + } + if _, syslogPortNum, hasChange := utils.MustGetChange[int](d, "syslog_port"); hasChange { ret.SyslogPort = syslogPortNum } @@ -51,6 +57,10 @@ func UpdateLogTriggerInputFromResourceData(d *schema.ResourceData) (models.Updat ret.CEFPort = cefPortNum } + if _, cefProtocol, hasChange := utils.MustGetChange[string](d, "cef_protocol"); hasChange { + ret.CEFProtocol = cefProtocol + } + return ret, nil } diff --git a/internal/resources/tests/appsec-gateway-profile_test.go b/internal/resources/tests/appsec-gateway-profile_test.go index e39946d9..dd11aa06 100644 --- a/internal/resources/tests/appsec-gateway-profile_test.go +++ b/internal/resources/tests/appsec-gateway-profile_test.go @@ -20,8 +20,9 @@ func TestAccAppsecGatewayProfileBasic(t *testing.T) { Config: appsecGatewayProfileBasicConfig(nameAttribute), Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ - "name": nameAttribute, - "profile_sub_type": "Aws", + "name": nameAttribute, + "profile_sub_type": "Aws", + "max_number_of_agents": "10", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -46,7 +47,7 @@ func TestAccAppsecGatewayProfileBasic(t *testing.T) { "max_number_of_agents": "100", "reverseproxy_additional_settings_ids.#": "2", "additional_settings_ids.#": "2", - "%": "16", + "%": "17", "profile_type": "CloudGuardAppSecGateway", "additional_settings.%": "2", "upgrade_time_week_days.1": "Monday", @@ -97,7 +98,7 @@ func TestAccAppsecGatewayProfileFull(t *testing.T) { "max_number_of_agents": "100", "reverseproxy_additional_settings_ids.#": "2", "additional_settings_ids.#": "2", - "%": "16", + "%": "17", "profile_type": "CloudGuardAppSecGateway", "additional_settings.%": "2", "upgrade_time_week_days.1": "Monday", @@ -151,7 +152,7 @@ func TestAccAppsecGatewayProfileFull(t *testing.T) { "additional_settings_ids.#": "3", "additional_settings.Key2": "Value11", "additional_settings.Key5": "Value5", - "%": "16", + "%": "17", "upgrade_time_week_days.1": "Sunday", }), resource.TestCheckTypeSetElemAttr(resourceName, "upgrade_time_week_days.*", "Monday"), @@ -170,6 +171,7 @@ func appsecGatewayProfileBasicConfig(name string) string { resource "inext_appsec_gateway_profile" %[1]q { name = %[1]q profile_sub_type = "Aws" + max_number_of_agents = 10 } `, name) } diff --git a/internal/resources/tests/docker-profile_test.go b/internal/resources/tests/docker-profile_test.go index 7a89a635..58317fa2 100644 --- a/internal/resources/tests/docker-profile_test.go +++ b/internal/resources/tests/docker-profile_test.go @@ -20,7 +20,8 @@ func TestAccDockerProfileBasic(t *testing.T) { Config: dockerProfileBasicConfig(nameAttribute), Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ - "name": nameAttribute, + "name": nameAttribute, + "max_number_of_agents": "10", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -114,6 +115,7 @@ func dockerProfileBasicConfig(name string) string { return fmt.Sprintf(` resource "inext_docker_profile" %[1]q { name = %[1]q + max_number_of_agents = 10 } `, name) } diff --git a/internal/resources/tests/embedded-profile_test.go b/internal/resources/tests/embedded-profile_test.go index e0397427..fe8365fc 100644 --- a/internal/resources/tests/embedded-profile_test.go +++ b/internal/resources/tests/embedded-profile_test.go @@ -20,7 +20,8 @@ func TestAccEmbeddedProfileBasic(t *testing.T) { Config: embeddedProfileBasicConfig(nameAttribute), Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ - "name": nameAttribute, + "name": nameAttribute, + "max_number_of_agents": "10", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -42,7 +43,7 @@ func TestAccEmbeddedProfileBasic(t *testing.T) { "upgrade_time_week_days.#": "3", "max_number_of_agents": "100", "additional_settings_ids.#": "2", - "%": "13", + "%": "14", "profile_type": "Embedded", "additional_settings.%": "2", "upgrade_time_week_days.1": "Monday", @@ -85,7 +86,7 @@ func TestAccEmbeddedProfileFull(t *testing.T) { "upgrade_time_week_days.#": "3", "max_number_of_agents": "100", "additional_settings_ids.#": "2", - "%": "13", + "%": "14", "profile_type": "Embedded", "additional_settings.%": "2", "upgrade_time_week_days.1": "Monday", @@ -127,7 +128,7 @@ func TestAccEmbeddedProfileFull(t *testing.T) { "additional_settings_ids.#": "3", "additional_settings.Key2": "Value11", "additional_settings.Key5": "Value5", - "%": "13", + "%": "14", "upgrade_time_week_days.1": "Sunday", }), resource.TestCheckTypeSetElemAttr(resourceName, "upgrade_time_week_days.*", "Monday"), @@ -145,6 +146,7 @@ func embeddedProfileBasicConfig(name string) string { return fmt.Sprintf(` resource "inext_embedded_profile" %[1]q { name = %[1]q + max_number_of_agents = 10 } `, name) } diff --git a/internal/resources/tests/exceptions_test.go b/internal/resources/tests/exceptions_test.go index 691c1bec..dd722e19 100644 --- a/internal/resources/tests/exceptions_test.go +++ b/internal/resources/tests/exceptions_test.go @@ -21,7 +21,7 @@ func TestAccExceptionBasic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, - "%": "3", + "%": "4", "exception.#": "0", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., @@ -36,7 +36,7 @@ func TestAccExceptionBasic(t *testing.T) { "exception.0.match.0.value.#": "1", "exception.0.match.0.operator": "equals", "exception.0.comment": "", - "%": "3", + "%": "4", "exception.0.match.0.operand.#": "0", "exception.#": "1", "exception.0.match.0.value.0": "www.google.com", @@ -57,7 +57,7 @@ func TestAccExceptionBasic(t *testing.T) { append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, "exception.0.action": "skip", - "%": "3", + "%": "4", "exception.0.comment": "test comment", "exception.0.match.0.value.#": "0", "exception.0.match.0.operand.0.value.#": "1", @@ -109,7 +109,7 @@ func TestAccExceptionWithExceptionBlock(t *testing.T) { append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, "exception.0.action": "skip", - "%": "3", + "%": "4", "exception.0.comment": "test comment", "exception.0.match.0.value.#": "0", "exception.0.match.0.operand.0.value.#": "1", @@ -153,7 +153,7 @@ func TestAccExceptionWithExceptionBlock(t *testing.T) { "exception.1.match.0.operand.0.%": "4", "exception.1.match.#": "1", "exception.0.match.0.operand.0.value.#": "1", - "%": "3", + "%": "4", "exception.0.match.0.operand.0.key": "hostName", "exception.0.match.0.operand.1.operand.#": "0", "exception.0.match.0.operand.#": "3", @@ -231,7 +231,7 @@ func TestAccExceptionWithExceptionBlock(t *testing.T) { "exception.0.%": "5", "exception.0.match.0.operator": "and", "exception.0.match.0.%": "4", - "%": "3", + "%": "4", "exception.0.match.0.operand.0.operand.#": "0", "exception.0.match.0.operand.0.value.0": "www.facebook.com", "exception.0.match.0.operand.1.operand.#": "0", diff --git a/internal/resources/tests/kubernetes-profile_test.go b/internal/resources/tests/kubernetes-profile_test.go index 49f140c8..2eb9a12d 100644 --- a/internal/resources/tests/kubernetes-profile_test.go +++ b/internal/resources/tests/kubernetes-profile_test.go @@ -20,8 +20,9 @@ func TestAccKubernetesProfileBasic(t *testing.T) { Config: kubernetesProfileBasicConfig(nameAttribute), Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ - "name": nameAttribute, - "profile_sub_type": "AccessControl", + "name": nameAttribute, + "profile_sub_type": "AccessControl", + "max_number_of_agents": "10", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -119,6 +120,7 @@ func kubernetesProfileBasicConfig(name string) string { resource "inext_kubernetes_profile" %[1]q { name = %[1]q profile_sub_type = "AccessControl" + max_number_of_agents = 10 } `, name) } diff --git a/internal/resources/tests/log-trigger_test.go b/internal/resources/tests/log-trigger_test.go index bc41996f..e99f42df 100644 --- a/internal/resources/tests/log-trigger_test.go +++ b/internal/resources/tests/log-trigger_test.go @@ -29,6 +29,10 @@ func TestAccLogTriggerBasic(t *testing.T) { "extend_logging_min_severity": "High", "extend_logging": "true", "verbosity": "Standard", + "compliance_warnings": "true", + "compliance_violations": "true", + "syslog_protocol": "UDP", + "cef_protocol": "UDP", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -65,6 +69,10 @@ func TestAccLogTriggerBasic(t *testing.T) { "response_code": "true", "syslog_ip_address": "10.0.0.2", "syslog_port": "82", + "compliance_warnings": "false", + "compliance_violations": "false", + "syslog_protocol": "TCP", + "cef_protocol": "TCP", }), resource.TestCheckResourceAttrSet(resourceName, "id"))..., ), @@ -89,6 +97,9 @@ resource "inext_log_trigger" %[1]q { access_control_drop_events = true cef_ip_address = "10.0.0.1" cef_port = 81 + cef_protocol = "TCP" + compliance_violations = false + compliance_warnings = false extend_logging = false extend_logging_min_severity = "Critical" log_to_agent = true @@ -99,6 +110,7 @@ resource "inext_log_trigger" %[1]q { response_body = true response_code = true syslog_ip_address = "10.0.0.2" + syslog_protocol = "TCP" syslog_port = 82 threat_prevention_detect_events = false threat_prevention_prevent_events = false diff --git a/internal/resources/tests/trusted-sources_test.go b/internal/resources/tests/trusted-sources_test.go index 27b8ee4d..b764f762 100644 --- a/internal/resources/tests/trusted-sources_test.go +++ b/internal/resources/tests/trusted-sources_test.go @@ -22,6 +22,7 @@ func TestAccTrustedSourcesBasic(t *testing.T) { append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, "min_num_of_sources": "1", + "visibility": "Shared", }), resource.TestCheckResourceAttrSet(resourceName, "id"), )..., @@ -36,6 +37,7 @@ func TestAccTrustedSourcesBasic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Local", "min_num_of_sources": "2", "sources_identifiers.#": "3", "sources_identifiers_ids.#": "3", @@ -64,6 +66,7 @@ func TestAccTrustedSourcesFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Shared", "min_num_of_sources": "1", "sources_identifiers.#": "3", "sources_identifiers_ids.#": "3", @@ -84,6 +87,7 @@ func TestAccTrustedSourcesFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Local", "min_num_of_sources": "2", "sources_identifiers.#": "4", "sources_identifiers_ids.#": "4", @@ -113,6 +117,7 @@ func trustedSourcesWithIdentifiersConfig(name string) string { return fmt.Sprintf(` resource "inext_trusted_sources" %[1]q { name = %[1]q + visibility = "Shared" min_num_of_sources = 1 sources_identifiers = ["identifier1", "identifier2", "identifier3"] } @@ -123,6 +128,7 @@ func trustedSourcesUpdateCreateSourceIdentifiersConfig(name string) string { return fmt.Sprintf(` resource "inext_trusted_sources" %[1]q { name = %[1]q + visibility = "Local" min_num_of_sources = 2 sources_identifiers = ["identifier1", "identifier2", "identifier3"] } @@ -133,6 +139,7 @@ func trustedSourcesUpdateSourceIdentifiersConfig(name string) string { return fmt.Sprintf(` resource "inext_trusted_sources" %[1]q { name = %[1]q + visibility = "Local" min_num_of_sources = 2 sources_identifiers = ["identifier1", "identifier3", "identifier4", "identifier5"] } diff --git a/internal/resources/tests/web-api-asset_test.go b/internal/resources/tests/web-api-asset_test.go index 80c111af..30fcc3ef 100644 --- a/internal/resources/tests/web-api-asset_test.go +++ b/internal/resources/tests/web-api-asset_test.go @@ -34,7 +34,7 @@ func TestAccWebAPIAssetBasic(t *testing.T) { "name": assetNameAttribute, "urls.0": fmt.Sprintf("http://host/%s/path1", assetNameAttribute), "urls.#": "1", - "%": "22", + "%": "25", "urls_ids.#": "1", "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%s/path1\"}", assetNameAttribute), }), @@ -53,44 +53,51 @@ func TestAccWebAPIAssetBasic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "22", + "%": "25", "read_only": "false", "upstream_url": "some url 5", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "AccordingToPractice", "practice.0.sub_practices_modes.WebBot": "AccordingToPractice", "practice.0.sub_practices_modes.Snort": "Disabled", "practice.0.main_mode": "Prevent", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "1", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "1", - "source_identifier.1.values_ids.#": "1", - "source_identifier.1.values.#": "1", - "source_identifier.0.values.#": "1", - "source_identifier.0.values_ids.#": "1", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web API", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path2;http://host/%[1]s/path3\"}", assetNameAttribute), - "asset_type": "WebAPI", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "1", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "1", + "source_identifier.1.values_ids.#": "1", + "source_identifier.1.values.#": "1", + "source_identifier.0.values.#": "1", + "source_identifier.0.values_ids.#": "1", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web API", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path2;http://host/%[1]s/path3\"}", assetNameAttribute), + "asset_type": "WebAPI", + "intelligence_tags": "", + "tags.#": "1", + "tags.0.%": "3", + + "mtls.#": "1", + "mtls.0.filename": "cert.pem", + "mtls.0.certificate_type": ".pem", + "mtls.0.data": "cert data", + "mtls.0.type": "client", + "mtls.0.enable": "true", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -103,6 +110,10 @@ func TestAccWebAPIAssetBasic(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path2", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path3", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -145,44 +156,52 @@ func TestAccWebAPIAssetFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "22", + "%": "25", "read_only": "false", "upstream_url": "some url 5", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "AccordingToPractice", "practice.0.sub_practices_modes.WebBot": "AccordingToPractice", "practice.0.sub_practices_modes.Snort": "Disabled", "practice.0.main_mode": "Learn", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "1", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "1", - "source_identifier.1.values_ids.#": "1", - "source_identifier.1.values.#": "1", - "source_identifier.0.values.#": "1", - "source_identifier.0.values_ids.#": "1", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web API", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path1;http://host/%[1]s/path2\"}", assetNameAttribute), - "asset_type": "WebAPI", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "1", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "1", + "source_identifier.1.values_ids.#": "1", + "source_identifier.1.values.#": "1", + "source_identifier.0.values.#": "1", + "source_identifier.0.values_ids.#": "1", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web API", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path1;http://host/%[1]s/path2\"}", assetNameAttribute), + "asset_type": "WebAPI", + "intelligence_tags": "", + "tags.#": "2", + "tags.0.%": "3", + "tags.1.%": "3", + + "mtls.#": "1", + "mtls.0.filename": "cert.der", + "mtls.0.certificate_type": ".der", + "mtls.0.data": "cert data", + "mtls.0.type": "client", + "mtls.0.enable": "true", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -194,6 +213,11 @@ func TestAccWebAPIAssetFull(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "proxy_setting.2.id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path1", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path2", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.1.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -210,44 +234,58 @@ func TestAccWebAPIAssetFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "22", + "%": "25", "read_only": "false", "upstream_url": "some url 10", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "Learn", "practice.0.sub_practices_modes.WebBot": "Inactive", "practice.0.sub_practices_modes.Snort": "AccordingToPractice", "practice.0.main_mode": "Prevent", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "2", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "2", - "source_identifier.1.values_ids.#": "2", - "source_identifier.1.values.#": "2", - "source_identifier.0.values.#": "2", - "source_identifier.0.values_ids.#": "2", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web API", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path3;http://host/%[1]s/path4\"}", assetNameAttribute), - "asset_type": "WebAPI", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "2", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "2", + "source_identifier.1.values_ids.#": "2", + "source_identifier.1.values.#": "2", + "source_identifier.0.values.#": "2", + "source_identifier.0.values_ids.#": "2", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web API", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path3;http://host/%[1]s/path4\"}", assetNameAttribute), + "asset_type": "WebAPI", + "intelligence_tags": "", + "tags.#": "3", + "tags.0.%": "3", + "tags.1.%": "3", + "tags.2.%": "3", + + "mtls.#": "2", + "mtls.0.filename": "newfile.crt", + "mtls.0.certificate_type": ".der", + "mtls.0.data": "new cert data", + "mtls.0.type": "server", + "mtls.0.enable": "true", + "mtls.1.filename": "newfile2.p12", + "mtls.1.certificate_type": ".p12", + "mtls.1.data": "new cert data2", + "mtls.1.type": "client", + "mtls.1.enable": "false", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -259,6 +297,16 @@ func TestAccWebAPIAssetFull(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "proxy_setting.2.id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path3", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path4", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.1.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.2.id"), + + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -284,7 +332,6 @@ resource "inext_web_api_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path3", "http://host/%[1]s/path2"] profiles = [inext_appsec_gateway_profile.%[2]s.id] - trusted_sources = [inext_trusted_sources.%[3]s.id] upstream_url = "some url 5" practice { main_mode = "Prevent" @@ -295,7 +342,6 @@ resource "inext_web_api_asset" %[1]q { } id = inext_web_api_practice.%[4]s.id triggers = [inext_log_trigger.%[5]s.id] - exceptions = [inext_exceptions.%[6]s.id] } proxy_setting { key = "some key" @@ -321,6 +367,17 @@ resource "inext_web_api_asset" %[1]q { identifier = "HeaderKey" values = ["value1"] } + tags { + key = "tagkey1" + value = "tagvalue1" + } + mtls { + filename = "cert.pem" + certificate_type = ".pem" + data = "cert data" + type = "client" + enable = true + } } resource "inext_appsec_gateway_profile" %[2]q { @@ -417,7 +474,6 @@ resource "inext_web_api_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path1", "http://host/%[1]s/path2"] profiles = [inext_appsec_gateway_profile.%[2]s.id] - trusted_sources = [inext_trusted_sources.%[3]s.id] upstream_url = "some url 5" practice { main_mode = "Learn" @@ -428,7 +484,6 @@ resource "inext_web_api_asset" %[1]q { } id = inext_web_api_practice.%[4]s.id triggers = [inext_log_trigger.%[5]s.id] - exceptions = [inext_exceptions.%[6]s.id] } proxy_setting { @@ -455,6 +510,21 @@ resource "inext_web_api_asset" %[1]q { identifier = "HeaderKey" values = ["value1"] } + tags { + key = "tagkey1" + value = "tagvalue1" + } + tags { + key = "tagkey2" + value = "tagvalue2" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = "cert data" + type = "client" + enable = true + } } resource "inext_appsec_gateway_profile" %[2]q { @@ -585,7 +655,6 @@ resource "inext_web_api_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path3", "http://host/%[1]s/path4"] profiles = [inext_appsec_gateway_profile.%[7]s.id] - trusted_sources = [inext_trusted_sources.%[8]s.id] upstream_url = "some url 10" practice { main_mode = "Prevent" @@ -596,7 +665,6 @@ resource "inext_web_api_asset" %[1]q { } id = inext_web_api_practice.%[4]s.id triggers = [inext_log_trigger.%[9]s.id] - exceptions = [inext_exceptions.%[10]s.id] } proxy_setting { @@ -623,6 +691,32 @@ resource "inext_web_api_asset" %[1]q { identifier = "Cookie" values = ["value8", "value9"] } + tags { + key = "tagkey1" + value = "tagvalue2" + } + tags { + key = "tagkey2" + value = "tagvalue1" + } + tags { + key = "tagkey3" + value = "tagvalue3" + } + mtls { + filename = "newfile.crt" + certificate_type = ".der" + data = "new cert data" + type = "server" + enable = true + } + mtls { + filename = "newfile2.p12" + certificate_type = ".p12" + data = "new cert data2" + type = "client" + enable = false + } } resource "inext_appsec_gateway_profile" %[2]q { diff --git a/internal/resources/tests/web-api-practice_test.go b/internal/resources/tests/web-api-practice_test.go index 8ebb5b96..573ce5cd 100644 --- a/internal/resources/tests/web-api-practice_test.go +++ b/internal/resources/tests/web-api-practice_test.go @@ -41,29 +41,48 @@ func TestAccWebAPIPracticeBasic(t *testing.T) { "ips.0.low_confidence": "Detect", "ips.0.performance_impact": "MediumOrLower", "ips.0.%": "7", - "schema_validation.0.filename": "", + "schema_validation.0.name": "", "api_attacks.#": "1", "ips.0.severity_level": "MediumOrAbove", "schema_validation.0.data": "", "practice_type": "WebAPI", "default": "false", - "ips.0.medium_confidence": "Prevent", - "schema_validation.0.%": "3", + "ips.0.medium_confidence": "AccordingToPractice", + "schema_validation.0.%": "5", "category": "ThreatPrevention", "api_attacks.0.%": "3", - "ips.0.high_confidence": "Prevent", + "ips.0.high_confidence": "AccordingToPractice", "api_attacks.0.advanced_setting.0.body_size": "1000000", "api_attacks.0.advanced_setting.0.url_size": "32768", "api_attacks.0.advanced_setting.0.header_size": "102400", "api_attacks.0.advanced_setting.0.%": "6", "api_attacks.0.advanced_setting.0.max_object_depth": "40", "api_attacks.0.advanced_setting.0.illegal_http_methods": "false", + + "file_security.0.severity_level": "MediumOrAbove", + "file_security.0.high_confidence": "AccordingToPractice", + "file_security.0.medium_confidence": "AccordingToPractice", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "schema_validation.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.advanced_setting.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.id"), resource.TestCheckResourceAttrSet(resourceName, "ips.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -77,7 +96,7 @@ func TestAccWebAPIPracticeBasic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, - "schema_validation.0.filename": schemaValidationFilename, + "schema_validation.0.name": "New File", "schema_validation.0.data": schemaValidationData, "api_attacks.0.minimum_severity": "Critical", "ips.0.high_confidence": "Detect", @@ -97,17 +116,36 @@ func TestAccWebAPIPracticeBasic(t *testing.T) { "ips.0.low_confidence": "Detect", "ips.0.protections_from_year": "2016", "ips.0.%": "7", - "schema_validation.0.%": "3", + "schema_validation.0.%": "5", "api_attacks.#": "1", "ips.0.severity_level": "LowOrAbove", "ips.#": "1", "api_attacks.0.%": "3", + + "file_security.0.severity_level": "Critical", + "file_security.0.high_confidence": "Prevent", + "file_security.0.medium_confidence": "Prevent", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "schema_validation.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.id"), resource.TestCheckResourceAttrSet(resourceName, "ips.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -128,37 +166,56 @@ func TestAccWebAPIPracticeFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, - "schema_validation.0.filename": schemaValidationFilename, + "visibility": "Shared", + "schema_validation.0.name": "New File 1", "schema_validation.0.data": schemaValidationData, "api_attacks.0.minimum_severity": "Critical", - "ips.0.high_confidence": "Detect", + "ips.0.high_confidence": "AccordingToPractice", "practice_type": "WebAPI", "api_attacks.0.advanced_setting.0.url_size": "1000", "api_attacks.0.advanced_setting.0.%": "6", - "ips.0.medium_confidence": "Detect", + "ips.0.medium_confidence": "AccordingToPractice", "ips.0.performance_impact": "LowOrLower", "api_attacks.0.advanced_setting.0.header_size": "1000", "api_attacks.0.advanced_setting.0.illegal_http_methods": "true", "api_attacks.0.advanced_setting.0.body_size": "1000", "schema_validation.#": "1", "api_attacks.0.advanced_setting.0.max_object_depth": "1000", - "default": "false", - "api_attacks.0.advanced_setting.#": "1", - "category": "ThreatPrevention", - "ips.0.low_confidence": "Detect", - "ips.0.protections_from_year": "2016", - "ips.0.%": "7", - "schema_validation.0.%": "3", - "api_attacks.#": "1", - "ips.0.severity_level": "LowOrAbove", - "ips.#": "1", - "api_attacks.0.%": "3", + "default": "false", + "api_attacks.0.advanced_setting.#": "1", + "category": "ThreatPrevention", + "ips.0.low_confidence": "Detect", + "ips.0.protections_from_year": "2016", + "ips.0.%": "7", + "schema_validation.0.%": "5", + "api_attacks.#": "1", + "ips.0.severity_level": "LowOrAbove", + "ips.#": "1", + "api_attacks.0.%": "3", + "file_security.0.severity_level": "MediumOrAbove", + "file_security.0.high_confidence": "AccordingToPractice", + "file_security.0.medium_confidence": "AccordingToPractice", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "schema_validation.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.id"), resource.TestCheckResourceAttrSet(resourceName, "ips.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -171,15 +228,15 @@ func TestAccWebAPIPracticeFull(t *testing.T) { Config: webAPIPracticeUpdateFullConfig(nameAttribute, schemaValidationFilenameUpdate, schemaValidationDataUpdate), Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ - "name": nameAttribute, - "schema_validation.0.filename": schemaValidationFilenameUpdate, - "schema_validation.0.data": schemaValidationDataUpdate, - "api_attacks.#": "1", - "category": "ThreatPrevention", - "default": "false", - "ips.0.high_confidence": "Prevent", + "name": nameAttribute, + "schema_validation.0.name": "New File 2", + "schema_validation.0.data": schemaValidationDataUpdate, + "api_attacks.#": "1", + "category": "ThreatPrevention", + "default": "false", + "ips.0.high_confidence": "Prevent", "api_attacks.0.advanced_setting.0.body_size": "1001", - "schema_validation.0.%": "3", + "schema_validation.0.%": "5", "api_attacks.0.minimum_severity": "High", "ips.0.protections_from_year": "2020", "ips.0.severity_level": "Critical", @@ -197,12 +254,30 @@ func TestAccWebAPIPracticeFull(t *testing.T) { "schema_validation.#": "1", "api_attacks.0.advanced_setting.0.url_size": "1002", "api_attacks.0.advanced_setting.#": "1", + "file_security.0.severity_level": "LowOrAbove", + "file_security.0.high_confidence": "Detect", + "file_security.0.medium_confidence": "Inactive", + "file_security.0.low_confidence": "Inactive", + "file_security.0.allow_file_size_limit": "Prevent", + "file_security.0.file_size_limit": "1000", + "file_security.0.file_size_limit_unit": "GB", + "file_security.0.files_without_name": "Detect", + "file_security.0.required_archive_extraction": "true", + "file_security.0.archive_file_size_limit": "10000", + "file_security.0.archive_file_size_limit_unit": "KB", + "file_security.0.allow_archive_within_archive": "Prevent", + "file_security.0.allow_an_unopened_archive": "Detect", + "file_security.0.allow_file_type": "true", + "file_security.0.required_threat_emulation": "true", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "schema_validation.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.id"), resource.TestCheckResourceAttrSet(resourceName, "ips.0.id"), resource.TestCheckResourceAttrSet(resourceName, "api_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -214,6 +289,24 @@ func webAPIPracticeBasicConfig(name string) string { return fmt.Sprintf(` resource "inext_web_api_practice" %[1]q { name = %[1]q + ips { + performance_impact = "MediumOrLower" + severity_level = "MediumOrAbove" + protections_from_year = "2016" + high_confidence = "AccordingToPractice" + medium_confidence = "AccordingToPractice" + low_confidence = "Detect" + } + api_attacks { + minimum_severity = "High" + advanced_setting { + body_size = 1000000 + url_size = 32768 + header_size = 102400 + max_object_depth = 40 + illegal_http_methods = false + } + } } `, name) } @@ -241,9 +334,14 @@ resource "inext_web_api_practice" %[1]q { } } schema_validation { - filename = %[2]q + name = "New File" data = %[3]q } + file_security { + severity_level = "Critical" + high_confidence = "Prevent" + medium_confidence = "Prevent" + } } `, name, filename, data) } @@ -256,8 +354,8 @@ resource "inext_web_api_practice" %[1]q { performance_impact = "LowOrLower" severity_level = "LowOrAbove" protections_from_year = "2016" - high_confidence = "Detect" - medium_confidence = "Detect" + high_confidence = "AccordingToPractice" + medium_confidence = "AccordingToPractice" low_confidence = "Detect" } api_attacks { @@ -271,9 +369,26 @@ resource "inext_web_api_practice" %[1]q { } } schema_validation { - filename = %[2]q + name = "New File 1" data = %[3]q } + file_security { + severity_level = "MediumOrAbove" + high_confidence = "AccordingToPractice" + medium_confidence = "AccordingToPractice" + low_confidence = "Detect" + allow_file_size_limit = "AccordingToPractice" + file_size_limit = "10" + file_size_limit_unit = "MB" + files_without_name = "AccordingToPractice" + required_archive_extraction = "false" + archive_file_size_limit = "10" + archive_file_size_limit_unit = "MB" + allow_archive_within_archive = "AccordingToPractice" + allow_an_unopened_archive = "AccordingToPractice" + allow_file_type = "false" + required_threat_emulation = "false" + } } `, name, filename, data) } @@ -301,8 +416,25 @@ resource "inext_web_api_practice" %[1]q { } } schema_validation { - filename = %[2]q - data = %[3]q + data = %[3]q + name = "New File 2" + } + file_security { + severity_level = "LowOrAbove" + high_confidence = "Detect" + medium_confidence = "Inactive" + low_confidence = "Inactive" + allow_file_size_limit = "Prevent" + file_size_limit = "1000" + file_size_limit_unit = "GB" + files_without_name = "Detect" + required_archive_extraction = "true" + archive_file_size_limit = "10000" + archive_file_size_limit_unit = "KB" + allow_archive_within_archive = "Prevent" + allow_an_unopened_archive = "Detect" + allow_file_type = "true" + required_threat_emulation = "true" } } `, name, filename, data) diff --git a/internal/resources/tests/web-app-asset_test.go b/internal/resources/tests/web-app-asset_test.go index f954e4d9..69d8f255 100644 --- a/internal/resources/tests/web-app-asset_test.go +++ b/internal/resources/tests/web-app-asset_test.go @@ -34,7 +34,7 @@ func TestAccWebApplicationAssetBasic(t *testing.T) { "name": assetNameAttribute, "urls.0": fmt.Sprintf("http://host/%s/path1", assetNameAttribute), "urls.#": "1", - "%": "21", + "%": "25", "urls_ids.#": "1", "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%s/path1\"}", assetNameAttribute), }), @@ -53,44 +53,51 @@ func TestAccWebApplicationAssetBasic(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "21", + "%": "25", "read_only": "false", "upstream_url": "some url 5", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "AccordingToPractice", "practice.0.sub_practices_modes.WebBot": "AccordingToPractice", "practice.0.sub_practices_modes.Snort": "Disabled", "practice.0.main_mode": "Prevent", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "1", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "1", - "source_identifier.1.values_ids.#": "1", - "source_identifier.1.values.#": "1", - "source_identifier.0.values.#": "1", - "source_identifier.0.values_ids.#": "1", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web Application", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path2;http://host/%[1]s/path3\"}", assetNameAttribute), - "asset_type": "WebApplication", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "1", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "1", + "source_identifier.1.values_ids.#": "1", + "source_identifier.1.values.#": "1", + "source_identifier.0.values.#": "1", + "source_identifier.0.values_ids.#": "1", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web Application", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path2;http://host/%[1]s/path3\"}", assetNameAttribute), + "asset_type": "WebApplication", + "intelligence_tags": "", + "tags.#": "1", + "tags.0.%": "3", + + "mtls.#": "1", + "mtls.0.filename": "cert.pem", + "mtls.0.certificate_type": ".pem", + "mtls.0.data": "cert data", + "mtls.0.type": "client", + "mtls.0.enable": "true", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -103,6 +110,10 @@ func TestAccWebApplicationAssetBasic(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path2", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path3", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -145,44 +156,52 @@ func TestAccWebApplicationAssetFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "21", + "%": "25", "read_only": "false", "upstream_url": "some url 5", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "AccordingToPractice", "practice.0.sub_practices_modes.WebBot": "AccordingToPractice", "practice.0.sub_practices_modes.Snort": "Disabled", "practice.0.main_mode": "Learn", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "1", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "1", - "source_identifier.1.values_ids.#": "1", - "source_identifier.1.values.#": "1", - "source_identifier.0.values.#": "1", - "source_identifier.0.values_ids.#": "1", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web Application", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path1;http://host/%[1]s/path2\"}", assetNameAttribute), - "asset_type": "WebApplication", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "1", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "1", + "source_identifier.1.values_ids.#": "1", + "source_identifier.1.values.#": "1", + "source_identifier.0.values.#": "1", + "source_identifier.0.values_ids.#": "1", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web Application", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path1;http://host/%[1]s/path2\"}", assetNameAttribute), + "asset_type": "WebApplication", + "intelligence_tags": "", + "tags.#": "2", + "tags.0.%": "3", + "tags.1.%": "3", + + "mtls.#": "1", + "mtls.0.filename": "cert.der", + "mtls.0.certificate_type": ".der", + "mtls.0.data": "cert data", + "mtls.0.type": "client", + "mtls.0.enable": "true", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -194,6 +213,11 @@ func TestAccWebApplicationAssetFull(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "proxy_setting.2.id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path1", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path2", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.1.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -210,44 +234,58 @@ func TestAccWebApplicationAssetFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(assetResourceName, map[string]string{ "name": assetNameAttribute, - "%": "21", + "%": "25", "read_only": "false", "upstream_url": "some url 10", "urls.#": "2", "urls_ids.#": "2", "profiles.#": "1", "practice.#": "1", - "practice.0.%": "6", + "practice.0.%": "5", "practice.0.triggers.#": "1", "practice.0.sub_practices_modes.IPS": "Learn", "practice.0.sub_practices_modes.WebBot": "Inactive", "practice.0.sub_practices_modes.Snort": "AccordingToPractice", "practice.0.main_mode": "Prevent", - // "practice.0.exceptions.#": "1", - "source_identifier.0.%": "4", - "source_identifier.1.%": "4", - "source_identifier.2.%": "4", - "source_identifier.2.values.#": "2", - "source_identifier.#": "3", - "source_identifier.2.values_ids.#": "2", - "source_identifier.1.values_ids.#": "2", - "source_identifier.1.values.#": "2", - "source_identifier.0.values.#": "2", - "source_identifier.0.values_ids.#": "2", - "proxy_setting.#": "3", - "proxy_setting.0.%": "3", - "proxy_setting.1.%": "3", - "proxy_setting.2.%": "3", - "trusted_sources.#": "1", - "class": "workload", - "category": "cloud", - "group": "", - "order": "", - "kind": "", - "family": "Web Application", - "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path3;http://host/%[1]s/path4\"}", assetNameAttribute), - "asset_type": "WebApplication", - "intelligence_tags": "", + "source_identifier.0.%": "4", + "source_identifier.1.%": "4", + "source_identifier.2.%": "4", + "source_identifier.2.values.#": "2", + "source_identifier.#": "3", + "source_identifier.2.values_ids.#": "2", + "source_identifier.1.values_ids.#": "2", + "source_identifier.1.values.#": "2", + "source_identifier.0.values.#": "2", + "source_identifier.0.values_ids.#": "2", + "proxy_setting.#": "3", + "proxy_setting.0.%": "3", + "proxy_setting.1.%": "3", + "proxy_setting.2.%": "3", + "class": "workload", + "category": "cloud", + "group": "", + "order": "", + "kind": "", + "family": "Web Application", + "main_attributes": fmt.Sprintf("{\"applicationUrls\":\"http://host/%[1]s/path3;http://host/%[1]s/path4\"}", assetNameAttribute), + "asset_type": "WebApplication", + "intelligence_tags": "", + "tags.#": "3", + "tags.0.%": "3", + "tags.1.%": "3", + "tags.2.%": "3", + + "mtls.#": "2", + "mtls.0.filename": "newfile.crt", + "mtls.0.certificate_type": ".der", + "mtls.0.data": "new cert data", + "mtls.0.type": "server", + "mtls.0.enable": "true", + "mtls.1.filename": "newfile2.p12", + "mtls.1.certificate_type": ".p12", + "mtls.1.data": "new cert data2", + "mtls.1.type": "client", + "mtls.1.enable": "false", }), resource.TestCheckResourceAttrSet(assetResourceName, "id"), resource.TestCheckResourceAttrSet(assetResourceName, "practice.0.id"), @@ -259,6 +297,15 @@ func TestAccWebApplicationAssetFull(t *testing.T) { resource.TestCheckResourceAttrSet(assetResourceName, "proxy_setting.2.id"), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path3", assetNameAttribute)), resource.TestCheckTypeSetElemAttr(assetResourceName, "urls.*", fmt.Sprintf("http://host/%s/path4", assetNameAttribute)), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.0.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.1.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "tags.2.id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.0.enable_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.filename_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.data_id"), + resource.TestCheckResourceAttrSet(assetResourceName, "mtls.1.enable_id"), )..., ), ExpectNonEmptyPlan: true, @@ -284,7 +331,6 @@ resource "inext_web_app_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path3", "http://host/%[1]s/path2"] profiles = [inext_appsec_gateway_profile.%[2]s.id] - trusted_sources = [inext_trusted_sources.%[3]s.id] upstream_url = "some url 5" practice { main_mode = "Prevent" @@ -295,7 +341,6 @@ resource "inext_web_app_asset" %[1]q { } id = inext_web_app_practice.%[4]s.id triggers = [inext_log_trigger.%[5]s.id] - exceptions = [inext_exceptions.%[6]s.id] } proxy_setting { key = "some key" @@ -321,6 +366,17 @@ resource "inext_web_app_asset" %[1]q { identifier = "HeaderKey" values = ["value1"] } + tags { + key = "tagkey1" + value = "tagvalue1" + } + mtls { + filename = "cert.pem" + certificate_type = ".pem" + data = "cert data" + type = "client" + enable = true + } } resource "inext_appsec_gateway_profile" %[2]q { @@ -417,7 +473,6 @@ resource "inext_web_app_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path1", "http://host/%[1]s/path2"] profiles = [inext_appsec_gateway_profile.%[2]s.id] - trusted_sources = [inext_trusted_sources.%[3]s.id] upstream_url = "some url 5" practice { main_mode = "Learn" @@ -428,7 +483,6 @@ resource "inext_web_app_asset" %[1]q { } id = inext_web_app_practice.%[4]s.id triggers = [inext_log_trigger.%[5]s.id] - exceptions = [inext_exceptions.%[6]s.id] } proxy_setting { @@ -455,6 +509,21 @@ resource "inext_web_app_asset" %[1]q { identifier = "HeaderKey" values = ["value1"] } + tags { + key = "tagkey1" + value = "tagvalue1" + } + tags { + key = "tagkey2" + value = "tagvalue2" + } + mtls { + filename = "cert.der" + certificate_type = ".der" + data = "cert data" + type = "client" + enable = true + } } resource "inext_appsec_gateway_profile" %[2]q { @@ -585,7 +654,6 @@ resource "inext_web_app_asset" %[1]q { name = %[1]q urls = ["http://host/%[1]s/path3", "http://host/%[1]s/path4"] profiles = [inext_appsec_gateway_profile.%[7]s.id] - trusted_sources = [inext_trusted_sources.%[8]s.id] upstream_url = "some url 10" practice { main_mode = "Prevent" @@ -596,7 +664,6 @@ resource "inext_web_app_asset" %[1]q { } id = inext_web_app_practice.%[4]s.id triggers = [inext_log_trigger.%[9]s.id] - exceptions = [inext_exceptions.%[10]s.id] } proxy_setting { @@ -623,6 +690,32 @@ resource "inext_web_app_asset" %[1]q { identifier = "Cookie" values = ["value8", "value9"] } + tags { + key = "tagkey1" + value = "tagvalue2" + } + tags { + key = "tagkey2" + value = "tagvalue1" + } + tags { + key = "tagkey3" + value = "tagvalue3" + } + mtls { + filename = "newfile.crt" + certificate_type = ".der" + data = "new cert data" + type = "server" + enable = true + } + mtls { + filename = "newfile2.p12" + certificate_type = ".p12" + data = "new cert data2" + type = "client" + enable = false + } } resource "inext_appsec_gateway_profile" %[2]q { diff --git a/internal/resources/tests/web-app-practice_test.go b/internal/resources/tests/web-app-practice_test.go index 2bca8b26..ea35be82 100644 --- a/internal/resources/tests/web-app-practice_test.go +++ b/internal/resources/tests/web-app-practice_test.go @@ -45,18 +45,36 @@ func TestAccWebAppPracticeBasic(t *testing.T) { "web_attacks.0.advanced_setting.0.illegal_http_methods": "false", "web_attacks.0.advanced_setting.#": "1", "web_bot.0.inject_uris_ids.#": "0", - "ips.0.medium_confidence": "Prevent", + "ips.0.medium_confidence": "AccordingToPractice", "web_bot.0.valid_uris_ids.#": "0", "web_attacks.0.advanced_setting.0.header_size": "102400", "web_bot.0.inject_uris.#": "0", - "ips.0.high_confidence": "Prevent", + "ips.0.high_confidence": "AccordingToPractice", "practice_type": "WebApplication", + "file_security.0.severity_level": "MediumOrAbove", + "file_security.0.high_confidence": "AccordingToPractice", + "file_security.0.medium_confidence": "AccordingToPractice", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "ips.0.id"), resource.TestCheckResourceAttrSet(resourceName, "web_bot.0.id"), resource.TestCheckResourceAttrSet(resourceName, "web_attacks.0.id"), resource.TestCheckResourceAttrSet(resourceName, "web_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -91,7 +109,7 @@ func TestAccWebAppPracticeBasic(t *testing.T) { "web_bot.0.inject_uris_ids.#": "2", "web_bot.#": "1", "default": "false", - "%": "8", + "%": "10", "web_attacks.0.advanced_setting.0.illegal_http_methods": "true", "web_attacks.0.advanced_setting.0.url_size": "1000", "web_attacks.0.advanced_setting.0.body_size": "1000", @@ -101,6 +119,23 @@ func TestAccWebAppPracticeBasic(t *testing.T) { "web_attacks.0.advanced_setting.0.%": "9", "ips.#": "1", "practice_type": "WebApplication", + "file_security.0.severity_level": "Critical", + "file_security.0.high_confidence": "Prevent", + "file_security.0.medium_confidence": "Prevent", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "web_bot.0.id"), @@ -115,6 +150,7 @@ func TestAccWebAppPracticeBasic(t *testing.T) { resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url1"), resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url2"), resource.TestCheckResourceAttrSet(resourceName, "web_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -135,6 +171,7 @@ func TestAccWebAppPracticeFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Shared", "category": "ThreatPrevention", "ips.0.protections_from_year": "2016", "ips.0.performance_impact": "LowOrLower", @@ -145,14 +182,14 @@ func TestAccWebAppPracticeFull(t *testing.T) { "web_bot.0.valid_uris_ids.#": "2", "web_attacks.0.%": "3", "web_bot.0.%": "5", - "ips.0.high_confidence": "Detect", + "ips.0.high_confidence": "AccordingToPractice", "ips.0.low_confidence": "Detect", "ips.0.%": "7", "web_bot.0.inject_uris_ids.#": "2", "web_bot.#": "1", "default": "false", "ips.0.severity_level": "LowOrAbove", - "ips.0.medium_confidence": "Detect", + "ips.0.medium_confidence": "AccordingToPractice", "ips.#": "1", "practice_type": "WebApplication", "web_attacks.0.advanced_setting.0.csrf_protection": "Prevent", @@ -165,6 +202,23 @@ func TestAccWebAppPracticeFull(t *testing.T) { "web_attacks.0.advanced_setting.0.illegal_http_methods": "true", "web_attacks.0.advanced_setting.#": "1", "web_attacks.0.advanced_setting.0.header_size": "1000", + "file_security.0.severity_level": "MediumOrAbove", + "file_security.0.high_confidence": "AccordingToPractice", + "file_security.0.medium_confidence": "AccordingToPractice", + "file_security.0.low_confidence": "Detect", + "file_security.0.allow_file_size_limit": "AccordingToPractice", + "file_security.0.file_size_limit": "10", + "file_security.0.file_size_limit_unit": "MB", + "file_security.0.files_without_name": "AccordingToPractice", + "file_security.0.required_archive_extraction": "false", + "file_security.0.archive_file_size_limit": "10", + "file_security.0.archive_file_size_limit_unit": "MB", + "file_security.0.allow_archive_within_archive": "AccordingToPractice", + "file_security.0.allow_an_unopened_archive": "AccordingToPractice", + "file_security.0.allow_file_type": "false", + "file_security.0.required_threat_emulation": "false", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "web_bot.0.id"), @@ -179,6 +233,7 @@ func TestAccWebAppPracticeFull(t *testing.T) { resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url1"), resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url2"), resource.TestCheckResourceAttrSet(resourceName, "web_attacks.0.advanced_setting.0.id"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -222,6 +277,23 @@ func TestAccWebAppPracticeFull(t *testing.T) { "web_attacks.0.advanced_setting.0.illegal_http_methods": "false", "web_attacks.0.advanced_setting.#": "1", "web_attacks.0.advanced_setting.0.header_size": "1003", + "file_security.0.severity_level": "LowOrAbove", + "file_security.0.high_confidence": "Detect", + "file_security.0.medium_confidence": "Inactive", + "file_security.0.low_confidence": "Inactive", + "file_security.0.allow_file_size_limit": "Prevent", + "file_security.0.file_size_limit": "1000", + "file_security.0.file_size_limit_unit": "GB", + "file_security.0.files_without_name": "Detect", + "file_security.0.required_archive_extraction": "true", + "file_security.0.archive_file_size_limit": "10000", + "file_security.0.archive_file_size_limit_unit": "KB", + "file_security.0.allow_archive_within_archive": "Prevent", + "file_security.0.allow_an_unopened_archive": "Detect", + "file_security.0.allow_file_type": "true", + "file_security.0.required_threat_emulation": "true", + "file_security.0.%": "16", + "file_security.#": "1", }), resource.TestCheckResourceAttrSet(resourceName, "id"), resource.TestCheckResourceAttrSet(resourceName, "web_attacks.0.advanced_setting.0.id"), @@ -236,6 +308,7 @@ func TestAccWebAppPracticeFull(t *testing.T) { resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.valid_uris.*", "url4"), resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url3"), resource.TestCheckTypeSetElemAttr(resourceName, "web_bot.0.inject_uris.*", "url4"), + resource.TestCheckResourceAttrSet(resourceName, "file_security.0.id"), )..., ), }, @@ -247,6 +320,19 @@ func webAppPracticeBasicConfig(name string) string { return fmt.Sprintf(` resource "inext_web_app_practice" %[1]q { name = %[1]q + web_attacks { + minimum_severity = "High" + advanced_setting { + max_object_depth = 40 + body_size = 1000000 + url_size = 32768 + header_size = 102400 + illegal_http_methods = false + open_redirect = "Disabled" + error_disclosure = "Disabled" + csrf_protection = "Disabled" + } + } } `, name) } @@ -280,6 +366,11 @@ resource "inext_web_app_practice" %[1]q { inject_uris = ["url1", "url2"] valid_uris = ["url1", "url2"] } + file_security { + severity_level = "Critical" + high_confidence = "Prevent" + medium_confidence = "Prevent" + } } `, name) } @@ -292,8 +383,8 @@ resource "inext_web_app_practice" %[1]q { performance_impact = "LowOrLower" severity_level = "LowOrAbove" protections_from_year = "2016" - high_confidence = "Detect" - medium_confidence = "Detect" + high_confidence = "AccordingToPractice" + medium_confidence = "AccordingToPractice" low_confidence = "Detect" } web_attacks { @@ -313,6 +404,23 @@ resource "inext_web_app_practice" %[1]q { inject_uris = ["url1", "url2"] valid_uris = ["url1", "url2"] } + file_security { + severity_level = "MediumOrAbove" + high_confidence = "AccordingToPractice" + medium_confidence = "AccordingToPractice" + low_confidence = "Detect" + allow_file_size_limit = "AccordingToPractice" + file_size_limit = "10" + file_size_limit_unit = "MB" + files_without_name = "AccordingToPractice" + required_archive_extraction = "false" + archive_file_size_limit = "10" + archive_file_size_limit_unit = "MB" + allow_archive_within_archive = "AccordingToPractice" + allow_an_unopened_archive = "AccordingToPractice" + allow_file_type = "false" + required_threat_emulation = "false" + } } `, name) } @@ -346,6 +454,23 @@ resource "inext_web_app_practice" %[1]q { inject_uris = ["url3", "url4"] valid_uris = ["url3", "url4"] } + file_security { + severity_level = "LowOrAbove" + high_confidence = "Detect" + medium_confidence = "Inactive" + low_confidence = "Inactive" + allow_file_size_limit = "Prevent" + file_size_limit = "1000" + file_size_limit_unit = "GB" + files_without_name = "Detect" + required_archive_extraction = "true" + archive_file_size_limit = "10000" + archive_file_size_limit_unit = "KB" + allow_archive_within_archive = "Prevent" + allow_an_unopened_archive = "Detect" + allow_file_type = "true" + required_threat_emulation = "true" + } } `, name) } diff --git a/internal/resources/tests/web-user-response_test.go b/internal/resources/tests/web-user-response_test.go index 3c5a8ee4..1310308e 100644 --- a/internal/resources/tests/web-user-response_test.go +++ b/internal/resources/tests/web-user-response_test.go @@ -62,6 +62,7 @@ func TestAccWebUserResponseFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Shared", "mode": "BlockPage", "http_response_code": "403", "message_title": "some message title", @@ -80,6 +81,7 @@ func TestAccWebUserResponseFull(t *testing.T) { Check: resource.ComposeTestCheckFunc( append(acctest.ComposeTestCheckResourceAttrsFromMap(resourceName, map[string]string{ "name": nameAttribute, + "visibility": "Local", "mode": "Redirect", "redirect_url": "http://localhost:1234/test", "x_event_id": "true", @@ -129,6 +131,7 @@ func webUserResponseUpdateSourceIdentifiersConfig(name string) string { return fmt.Sprintf(` resource "inext_web_user_response" %[1]q { name = %[1]q + visibility = "Local" mode = "Redirect" redirect_url = "http://localhost:1234/test" x_event_id = true diff --git a/internal/resources/trusted-sources.go b/internal/resources/trusted-sources.go index f07e7268..3e5f3943 100644 --- a/internal/resources/trusted-sources.go +++ b/internal/resources/trusted-sources.go @@ -2,6 +2,7 @@ package resources import ( "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" trustedsources "github.com/CheckPointSW/terraform-provider-infinity-next/internal/resources/trusted-sources" @@ -11,6 +12,8 @@ import ( ) func ResourceTrustedSources() *schema.Resource { + validateVisibility := validation.ToDiagFunc( + validation.StringInSlice([]string{visibilityShared, visibilityLocal}, false)) return &schema.Resource{ Description: "Trusted sources that serve as a baseline for comparison for benign behavior, " + "and how many users or addresses must exhibit similar activity for it to be considered bengin by the learning model", @@ -39,6 +42,13 @@ func ResourceTrustedSources() *schema.Resource { Description: "The name of the resource, also acts as its unique ID", Required: true, }, + "visibility": { + Type: schema.TypeString, + Description: "The visibility of the resource - Shared or Local", + Default: "Shared", + Optional: true, + ValidateDiagFunc: validateVisibility, + }, "min_num_of_sources": { Type: schema.TypeInt, Description: "Minimum number of users or addresses that must exhibit similar activity for the behavior to be considered benign", diff --git a/internal/resources/trusted-sources/create.go b/internal/resources/trusted-sources/create.go index d7abf7e9..d1b37296 100644 --- a/internal/resources/trusted-sources/create.go +++ b/internal/resources/trusted-sources/create.go @@ -14,7 +14,7 @@ func CreateTrustedSourceBehaviorInputFromResourceData(d *schema.ResourceData) (m var input models.CreateTrustedSourceBehaviorInput input.Name = d.Get("name").(string) - input.Visibility = "Shared" + input.Visibility = d.Get("visibility").(string) input.NumOfSources = d.Get("min_num_of_sources").(int) input.SourcesIdentifiers = utils.MustResourceDataCollectionToSlice[string](d, "sources_identifiers") @@ -29,6 +29,7 @@ func NewTrustedSourceBehavior(ctx context.Context, c *api.Client, input models.C newTrustedSourceBehavior(ownerId: $ownerId, practiceId: $practiceId, behaviorInput: $behaviorInput) { id name + visibility behaviorType numOfSources sourcesIdentifiers { diff --git a/internal/resources/trusted-sources/read.go b/internal/resources/trusted-sources/read.go index 8d0e4fd2..510e3948 100644 --- a/internal/resources/trusted-sources/read.go +++ b/internal/resources/trusted-sources/read.go @@ -16,6 +16,7 @@ func GetTrustedSourceBehavior(ctx context.Context, c *api.Client, id string) (mo getTrustedSourceBehavior(id: "`+id+`") { id name + visibility behaviorType numOfSources sourcesIdentifiers { @@ -41,6 +42,7 @@ func GetTrustedSourceBehavior(ctx context.Context, c *api.Client, id string) (mo func ReadTrustedSourceBehaviorToResourceData(behavior models.TrustedSourceBehavior, d *schema.ResourceData) error { d.SetId(behavior.ID) d.Set("name", behavior.Name) + d.Set("visibility", behavior.Visibility) d.Set("min_num_of_sources", behavior.NumOfSources) sourcesIdentifiers := make([]string, len(behavior.SourcesIdentifiers)) diff --git a/internal/resources/trusted-sources/update.go b/internal/resources/trusted-sources/update.go index 8af9c53b..4af6b848 100644 --- a/internal/resources/trusted-sources/update.go +++ b/internal/resources/trusted-sources/update.go @@ -17,6 +17,10 @@ func UpdateTrustedSourceBehaviorInputFromResourceData(d *schema.ResourceData) (m res.Name = newName } + if _, newVisibility, hasChange := utils.MustGetChange[string](d, "visibility"); hasChange { + res.Visibility = newVisibility + } + if _, newMinNumberOfSources, hasChange := utils.MustGetChange[int](d, "min_num_of_sources"); hasChange { res.NumOfSources = newMinNumberOfSources } diff --git a/internal/resources/web-api-asset.go b/internal/resources/web-api-asset.go index 254d2a74..501ab50d 100644 --- a/internal/resources/web-api-asset.go +++ b/internal/resources/web-api-asset.go @@ -26,6 +26,7 @@ const ( xForwardedFor = "XForwardedFor" headerKey = "HeaderKey" cookie = "Cookie" + jwtKey = "JWTKey" // Allowed states suggestedState = "Suggested" @@ -37,9 +38,13 @@ func ResourceWebAPIAsset() *schema.Resource { validatePracticeModeFunc := validation.ToDiagFunc(validation.StringInSlice( []string{detectMode, preventMode, inactiveMode, accordingToPracticeMode, disabledMode, learnMode, activeMode}, false)) validateSourceIdentifierFunc := validation.ToDiagFunc(validation.StringInSlice( - []string{sourceIP, xForwardedFor, headerKey, cookie}, false)) + []string{sourceIP, xForwardedFor, headerKey, cookie, jwtKey}, false)) validateStateFunc := validation.ToDiagFunc(validation.StringInSlice( []string{suggestedState, activeState, headerKey, inactiveState}, false)) + mTLSTypeValidation := validation.ToDiagFunc(validation.StringInSlice( + []string{mTLSServer, mTLSClient}, false)) + mTLSFileTypeValidation := validation.ToDiagFunc(validation.StringInSlice( + []string{mTLSFileTypePEM, mTLSFileTypeCRT, mTLSFileTypeDER, mTLSFileTypeP12, mTLSFileTypePFX, mTLSFileTypeP7B, mTLSFileTypeP7C, mTLSFileTypeCER}, false)) return &schema.Resource{ Description: "Web API Asset", @@ -77,9 +82,9 @@ func ResourceWebAPIAsset() *schema.Resource { }, }, // top level behaviors - "trusted_sources": { + "behaviors": { Type: schema.TypeSet, - Description: "Trusted sources behavior used by the asset", + Description: "behaviors used by the asset", Optional: true, Elem: &schema.Schema{ Type: schema.TypeString, @@ -112,6 +117,27 @@ func ResourceWebAPIAsset() *schema.Resource { Type: schema.TypeString, }, }, + "tags": { + Type: schema.TypeSet, + Description: "The tags used by the asset", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, "practice": { Type: schema.TypeSet, Description: "The practices used by the asset", @@ -150,15 +176,6 @@ func ResourceWebAPIAsset() *schema.Resource { Type: schema.TypeString, }, }, - // practices.behaviors - "exceptions": { - Type: schema.TypeSet, - Description: "The exceptions used with the practice", - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeString, - }, - }, }, }, }, @@ -187,13 +204,13 @@ func ResourceWebAPIAsset() *schema.Resource { }, "source_identifier": { Type: schema.TypeSet, - Description: "Defines how the source identifier valuess of the asset are retrieved", + Description: "Defines how the source identifier values of the asset are retrieved", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "identifier": { Type: schema.TypeString, - Description: "The identifier of the source: SourceIP, XForwardedFor, HeaderKey or Cookie", + Description: "The identifier of the source: SourceIP, XForwardedFor, HeaderKey, Cookie or JWTKey", Optional: true, ValidateDiagFunc: validateSourceIdentifierFunc, }, @@ -262,6 +279,61 @@ func ResourceWebAPIAsset() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "is_shares_urls": { + Type: schema.TypeBool, + Computed: true, + }, + "mtls": { + Type: schema.TypeSet, + Description: "The MTLS settings", + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filename_id": { + Type: schema.TypeString, + Computed: true, + }, + "filename": { + Description: "The name of the certificate file", + Type: schema.TypeString, + Optional: true, + }, + "certificate_type": { + Description: "The type of the certificate file - .pem, .crt, .der, .p12, .pfx, .p7b, .p7c, .cer", + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: mTLSFileTypeValidation, + }, + "data_id": { + Type: schema.TypeString, + Computed: true, + }, + "data": { + Description: "The certificate data", + Type: schema.TypeString, + Sensitive: true, + Optional: true, + }, + "type": { + Description: "The type of the mTLS - server or client", + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: mTLSTypeValidation, + }, + "enable_id": { + Type: schema.TypeString, + Computed: true, + }, + "enable": { + Description: "Whether the mTLS is enabled", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, }, } } diff --git a/internal/resources/web-api-asset/create.go b/internal/resources/web-api-asset/create.go index f4e97af8..3b30adce 100644 --- a/internal/resources/web-api-asset/create.go +++ b/internal/resources/web-api-asset/create.go @@ -10,22 +10,43 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const ( + mtlsTypeClient = "client" + mtlsTypeServer = "server" + + mtlsClientEnable = "isUpstreamTrustedCAFile" + mtlsClientData = "upstreamTrustedCAFile" + mtlsClientFileName = "upstreamTrustedCAFileName" + + mtlsServerEnable = "isTrustedCAListFile" + mtlsServerData = "trustedCAListFile" + mtlsServerFileName = "trustedCAListFileName" +) + func CreateWebAPIAssetInputFromResourceData(d *schema.ResourceData) (models.CreateWebAPIAssetInput, error) { var res models.CreateWebAPIAssetInput res.Name = d.Get("name").(string) res.UpstreamURL = d.Get("upstream_url").(string) res.Profiles = utils.MustResourceDataCollectionToSlice[string](d, "profiles") - res.Behaviors = utils.MustResourceDataCollectionToSlice[string](d, "trusted_sources") + res.Behaviors = utils.MustResourceDataCollectionToSlice[string](d, "behaviors") res.URLs = utils.MustResourceDataCollectionToSlice[string](d, "urls") res.PracticeWrappers = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "practice"), mapToPracticeWrapperInput) res.ProxySettings = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "proxy_setting"), mapToProxySettingInput) res.SourceIdentifiers = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "source_identifier"), mapToSourceIdentifierInput) + res.Tags = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "tags"), mapToTagInput) + res.IsSharesURLs = d.Get("is_shares_urls").(bool) + res.State = d.Get("state").(string) + + var mtls models.MTLSSchemas + mtls = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "mtls"), mapToMTLSInput) + + res.ProxySettings = mapMTLSToProxySettingInputs(mtls, res.ProxySettings) return res, nil } -// NewWebAPIAsset sends a request to create the WebAPIAsset and retruns the newly created asset +// NewWebAPIAsset sends a request to create the WebAPIAsset and returns the newly created asset func NewWebAPIAsset(ctx context.Context, c *api.Client, input models.CreateWebAPIAssetInput) (models.WebAPIAsset, error) { vars := map[string]any{"assetInput": input} res, err := c.MakeGraphQLRequest(ctx, ` @@ -51,9 +72,6 @@ func NewWebAPIAsset(ctx context.Context, c *api.Client, input models.CreateWebAP triggers { id } - behaviors { - id - } } profiles { id @@ -62,6 +80,11 @@ func NewWebAPIAsset(ctx context.Context, c *api.Client, input models.CreateWebAP id name } + tags { + id + key + value + } sourceIdentifiers { id sourceIdentifier @@ -90,6 +113,7 @@ func NewWebAPIAsset(ctx context.Context, c *api.Client, input models.CreateWebAP mainAttributes intelligenceTags readOnly + isSharesURLs } } `, "newWebAPIAsset", vars) @@ -117,9 +141,9 @@ func mapToPracticeWrapperInput(practiceWrapperMap map[string]any) models.Practic if subPracticesModes, ok := practiceWrapperMap["sub_practices_modes"]; ok { subPracticesModesMap := subPracticesModes.(map[string]any) practiceWrapper.SubPracticeModes = make([]models.PracticeModeInput, 0, len(subPracticesModesMap)) - for subPratice, mode := range subPracticesModesMap { + for subPractice, mode := range subPracticesModesMap { practiceWrapper.SubPracticeModes = append(practiceWrapper.SubPracticeModes, - models.PracticeModeInput{Mode: mode.(string), SubPractice: subPratice}) + models.PracticeModeInput{Mode: mode.(string), SubPractice: subPractice}) } } @@ -127,10 +151,6 @@ func mapToPracticeWrapperInput(practiceWrapperMap map[string]any) models.Practic practiceWrapper.Triggers = utils.MustSchemaCollectionToSlice[string](triggersInterface) } - if behaviorsInterface, ok := practiceWrapperMap["exceptions"]; ok { - practiceWrapper.Behaviors = utils.MustSchemaCollectionToSlice[string](behaviorsInterface) - } - return practiceWrapper } @@ -158,3 +178,68 @@ func mapToSourceIdentifierInput(sourceIdentifierMap map[string]any) models.Sourc return ret } + +func mapToTagInput(tagsMap map[string]any) models.TagInput { + var ret models.TagInput + ret.Key, ret.Value = tagsMap["key"].(string), tagsMap["value"].(string) + if id, ok := tagsMap["id"]; ok { + ret.ID = id.(string) + } + return ret + +} + +func mapToMTLSInput(mTLSMap map[string]any) models.MTLSSchema { + mTLSFile, err := utils.UnmarshalAs[models.MTLSSchema](mTLSMap) + if err != nil { + fmt.Printf("Failed to convert input schema validation to MTLSSchema struct. Error: %+v", err) + return models.MTLSSchema{} + } + + mTLSFile = models.NewFileSchemaEncode(mTLSFile.Filename, mTLSFile.Data, mTLSFile.Type, mTLSFile.CertificateType, mTLSFile.Enable) + + if mTLSMap["filename_id"] != nil { + mTLSFile.FilenameID = mTLSMap["filename_id"].(string) + } + + if mTLSMap["data_id"] != nil { + mTLSFile.DataID = mTLSMap["data_id"].(string) + } + + if mTLSMap["enable_id"] != nil { + mTLSFile.EnableID = mTLSMap["enable_id"].(string) + } + + return mTLSFile +} + +func mapMTLSToProxySettingInputs(mTLS models.MTLSSchemas, proxySettings models.ProxySettingInputs) models.ProxySettingInputs { + for _, mTLSFile := range mTLS { + var proxySettingEnable, proxySettingData, proxySettingFileName models.ProxySettingInput + switch mTLSFile.Type { + case mtlsTypeClient: + proxySettingEnable.Key = mtlsClientEnable + proxySettingData.Key = mtlsClientData + proxySettingFileName.Key = mtlsClientFileName + case mtlsTypeServer: + proxySettingEnable.Key = mtlsServerEnable + proxySettingData.Key = mtlsServerData + proxySettingFileName.Key = mtlsServerFileName + default: + continue + } + + if mTLSFile.Enable { + proxySettingEnable.Value = "true" + } else { + proxySettingEnable.Value = "false" + } + + proxySettingData.Value = mTLSFile.Data + proxySettingFileName.Value = mTLSFile.Filename + + proxySettings = append(proxySettings, proxySettingEnable, proxySettingData, proxySettingFileName) + } + + return proxySettings +} diff --git a/internal/resources/web-api-asset/read.go b/internal/resources/web-api-asset/read.go index 49ea6b67..b8e5cf03 100644 --- a/internal/resources/web-api-asset/read.go +++ b/internal/resources/web-api-asset/read.go @@ -2,7 +2,9 @@ package webapiasset import ( "context" + "encoding/base64" "fmt" + "strings" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" models "github.com/CheckPointSW/terraform-provider-infinity-next/internal/models/web-api-asset" @@ -10,6 +12,18 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +func proxySettingKeyTomTLSType(proxySettingKey string) string { + if proxySettingKey == mtlsClientEnable || proxySettingKey == mtlsClientData || proxySettingKey == mtlsClientFileName { + return mtlsTypeClient + } + + if proxySettingKey == mtlsServerEnable || proxySettingKey == mtlsServerData || proxySettingKey == mtlsServerFileName { + return mtlsTypeServer + } + + return "" +} + func ReadWebAPIAssetToResourceData(asset models.WebAPIAsset, d *schema.ResourceData) error { d.SetId(asset.ID) d.Set("name", asset.Name) @@ -25,15 +39,103 @@ func ReadWebAPIAssetToResourceData(asset models.WebAPIAsset, d *schema.ResourceD d.Set("intelligence_tags", asset.IntelligenceTags) d.Set("read_only", asset.ReadOnly) d.Set("upstream_url", asset.UpstreamURL) - d.Set("trusted_sources", asset.Behaviors.ToSchema()) + d.Set("behaviors", asset.Behaviors.ToSchema()) d.Set("profiles", asset.Profiles.ToSchema()) + d.Set("is_shares_urls", asset.IsSharesURLs) + d.Set("state", asset.State) + + var proxySettingsSchemaMap []map[string]any + mTLSsSchemaMap := make(map[string]models.MTLSSchema) + var mTLSsMap []map[string]any + + for _, proxySetting := range asset.ProxySettings { + mTLSType := proxySettingKeyTomTLSType(proxySetting.Key) + if mTLSType != "" { + if _, ok := mTLSsSchemaMap[mTLSType]; !ok { + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{} + } - proxySettingsSchemaMap, err := utils.UnmarshalAs[[]map[string]any](asset.ProxySettings) - if err != nil { - return fmt.Errorf("failed to convert proxy settings to slice of maps. Error: %+v", err) + switch proxySetting.Key { + case mtlsClientEnable, mtlsServerEnable: + enable := false + if proxySetting.Value == "true" { + enable = true + } + + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: mTLSsSchemaMap[mTLSType].FilenameID, + Filename: mTLSsSchemaMap[mTLSType].Filename, + CertificateType: mTLSsSchemaMap[mTLSType].CertificateType, + DataID: mTLSsSchemaMap[mTLSType].DataID, + Data: mTLSsSchemaMap[mTLSType].Data, + Type: mTLSType, + EnableID: proxySetting.ID, + Enable: enable, + } + case mtlsClientData, mtlsServerData: + var decodedData string + var fileExtensionsByType string + // proxySetting.Value format is "data:;base64," + if strings.Contains(proxySetting.Value, "base64,") { + b64Data := strings.SplitN(proxySetting.Value, "base64,", 2)[1] + bDecodedData, err := base64.StdEncoding.DecodeString(b64Data) + if err != nil { + return fmt.Errorf("failed decoding base64 string %s: %w", b64Data, err) + } + + decodedData = string(bDecodedData) + + mimeType := strings.SplitN(proxySetting.Value, ":", 2)[1] + mimeType = strings.SplitN(mimeType, ";", 2)[0] + fileExtensionsByType = models.MimeTypeToFileExtension(mimeType) + } + + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: mTLSsSchemaMap[mTLSType].FilenameID, + Filename: mTLSsSchemaMap[mTLSType].Filename, + CertificateType: fileExtensionsByType, + DataID: proxySetting.ID, + Data: decodedData, + Type: mTLSType, + EnableID: mTLSsSchemaMap[mTLSType].EnableID, + Enable: mTLSsSchemaMap[mTLSType].Enable, + } + case mtlsClientFileName, mtlsServerFileName: + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: proxySetting.ID, + Filename: proxySetting.Value, + CertificateType: mTLSsSchemaMap[mTLSType].CertificateType, + DataID: mTLSsSchemaMap[mTLSType].DataID, + Data: mTLSsSchemaMap[mTLSType].Data, + Type: mTLSType, + EnableID: mTLSsSchemaMap[mTLSType].EnableID, + Enable: mTLSsSchemaMap[mTLSType].Enable, + } + + default: + continue + } + } else { + proxySettingSchemaMap, err := utils.UnmarshalAs[map[string]any](proxySetting) + if err != nil { + return fmt.Errorf("failed to convert proxy setting to map. Error: %+v", err) + } + + proxySettingsSchemaMap = append(proxySettingsSchemaMap, proxySettingSchemaMap) + } + } + + for _, mTLSscehma := range mTLSsSchemaMap { + mTLS, err := utils.UnmarshalAs[map[string]any](mTLSscehma) + if err != nil { + return fmt.Errorf("failed to convert mTLS to map. Error: %+v", err) + } + + mTLSsMap = append(mTLSsMap, mTLS) } d.Set("proxy_setting", proxySettingsSchemaMap) + d.Set("mtls", mTLSsMap) sourceIdentifiersSchema := asset.SourceIdentifiers.ToSchema() sourceIdentifiersSchemaMap, err := utils.UnmarshalAs[[]map[string]any](sourceIdentifiersSchema) @@ -55,6 +157,13 @@ func ReadWebAPIAssetToResourceData(asset models.WebAPIAsset, d *schema.ResourceD d.Set("practice", schemaPracticeWrappersMap) + tagsSchemaMap, err := utils.UnmarshalAs[[]map[string]any](asset.Tags) + if err != nil { + return fmt.Errorf("failed to convert tags to slice of maps. Error: %+v", err) + } + + d.Set("tags", tagsSchemaMap) + return nil } @@ -81,9 +190,6 @@ func GetWebAPIAsset(ctx context.Context, c *api.Client, id string) (models.WebAP triggers { id } - behaviors { - id - } } profiles { id @@ -92,6 +198,11 @@ func GetWebAPIAsset(ctx context.Context, c *api.Client, id string) (models.WebAP id name } + tags { + id + key + value + } sourceIdentifiers { id sourceIdentifier diff --git a/internal/resources/web-api-asset/update.go b/internal/resources/web-api-asset/update.go index f7f6f735..33373af6 100644 --- a/internal/resources/web-api-asset/update.go +++ b/internal/resources/web-api-asset/update.go @@ -51,7 +51,7 @@ func UpdateWebAPIAssetInputFromResourceData(d *schema.ResourceData) (models.Upda updateInput.AddProfiles, updateInput.RemoveProfiles = utils.SlicesDiff(oldProfilesString, newProfilesString) } - if oldBehaviorsStringList, newBehaviorsStringList, hasChange := utils.GetChangeWithParse(d, "trusted_sources", utils.MustSchemaCollectionToSlice[string]); hasChange { + if oldBehaviorsStringList, newBehaviorsStringList, hasChange := utils.GetChangeWithParse(d, "behaviors", utils.MustSchemaCollectionToSlice[string]); hasChange { updateInput.AddBehaviors, updateInput.RemoveBehaviors = utils.SlicesDiff(oldBehaviorsStringList, newBehaviorsStringList) } @@ -106,12 +106,84 @@ func UpdateWebAPIAssetInputFromResourceData(d *schema.ResourceData) (models.Upda newProxySettingsIndicators := newProxySettings.ToIndicatorsMap() for _, oldSetting := range oldProxySettings { + // if the key is a mTLS key - skip it + if proxySettingKeyTomTLSType(oldSetting.Key) != "" { + continue + } + if _, ok := newProxySettingsIndicators[oldSetting.Key]; !ok { updateInput.RemoveProxySetting = append(updateInput.RemoveProxySetting, oldSetting.ID) } } } + if oldMTLSs, newMTLSs, hasChange := utils.GetChangeWithParse(d, "mtls", parsemTLSs); hasChange { + oldMTLSsIndicators := oldMTLSs.ToIndicatorMap() + mTLSsToAdd := models.MTLSSchemas{} + for _, newMTLS := range newMTLSs { + oldMTLS, ok := oldMTLSsIndicators[newMTLS.Type] + if !ok { + mTLSsToAdd = append(mTLSsToAdd, newMTLS) + continue + } + if oldMTLS.Enable != newMTLS.Enable { + var enableToString string + if newMTLS.Enable { + enableToString = "true" + } else { + enableToString = "false" + } + + key := mtlsClientEnable + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerEnable + } + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.EnableID, + Key: key, + Value: enableToString, + }) + } + + if oldMTLS.Data != newMTLS.Data { + key := mtlsClientData + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerData + } + + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.DataID, + Key: key, + Value: newMTLS.Data, + }) + } + + if oldMTLS.Filename != newMTLS.Filename { + key := mtlsClientFileName + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerFileName + } + + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.FilenameID, + Key: key, + Value: newMTLS.Filename, + }) + } + } + + var proxySettingsToAdd models.ProxySettingInputs + if mTLSsToAdd != nil { + proxySettingsToAdd = mapMTLSToProxySettingInputs(mTLSsToAdd, models.ProxySettingInputs{}) + } + for _, proxySettingToAdd := range proxySettingsToAdd { + updateInput.AddProxySetting = append(updateInput.AddProxySetting, models.AddProxySetting{ + Key: proxySettingToAdd.Key, + Value: proxySettingToAdd.Value, + }) + } + } + if oldSourceIdentifiers, newSourceIdentifiers, hasChange := utils.GetChangeWithParse(d, "source_identifier", parseSchemaSourceIdentifiers); hasChange { oldSourceIdentifiersIndicatorMap := oldSourceIdentifiers.ToIndicatorsMap() for _, newSourceIdentifier := range newSourceIdentifiers { @@ -139,7 +211,7 @@ func UpdateWebAPIAssetInputFromResourceData(d *schema.ResourceData) (models.Upda SourceIdentifier: oldSourceIdentifier.SourceIdentifier, AddValues: valuesToAdd, RemoveValues: valuesIDsToRemove, - UpdateValues: []string{}, + UpdateValues: []models.UpdateSourceIdentifierValue{}, }) } @@ -149,38 +221,54 @@ func UpdateWebAPIAssetInputFromResourceData(d *schema.ResourceData) (models.Upda updateInput.RemoveSourceIdentifiers = append(updateInput.RemoveSourceIdentifiers, oldSourceIdentifier.ID) } } + + if oldTags, newTags, hasChange := utils.GetChangeWithParse(d, "tags", parseSchemaTags); hasChange { + tagsInputsToAdd, tagsInputsToRemove := utils.SlicesDiff(oldTags, newTags) + tagsInputsToAdd = utils.Filter(tagsInputsToAdd, validateTag) + tagsInputsToRemove = utils.Filter(tagsInputsToRemove, validateTag) + tagsToAdd := utils.Map(tagsInputsToAdd, utils.MustUnmarshalAs[models.AddTag, models.TagInput]) + tagsToRemove := utils.Map(tagsInputsToRemove, func(tag models.TagInput) string { return tag.ID }) + updateInput.AddTags = tagsToAdd + updateInput.RemoveTags = tagsToRemove + } } return updateInput, nil } // parseSchemaSourceIdentifiers converts the source identifiers (type schema.TypeSet) to a slice of map[string]any -// and than converts the it to a slice of modles.SourceIdentifierInput +// and then converts it to a slice of models.SourceIdentifierInput func parseSchemaSourceIdentifiers(sourceIdentifiersFromResourceData any) models.SourceIdentifiersInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](sourceIdentifiersFromResourceData), mapToSourceIdentifierInput) } // parseSchemaPracticeWrappers converts the practice wrappers (type schema.TypeSet) to a slice of map[string]any -// and than converts the it to a slice of modles.PracticeWrapperInput +// and then converts it to a slice of models.PracticeWrapperInput func parseSchemaPracticeWrappers(practiceWrappersFromResourceData any) models.PracticeWrappersInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](practiceWrappersFromResourceData), mapToPracticeWrapperInput) } // parseSchemaProxySettings converts the proxy settings (type schema.TypeSet) to a slice of map[string]any -// and than converts the it to a slice of modles.PracticeWrapperInput +// and then converts it to a slice of models.PracticeWrapperInput func parseSchemaProxySettings(proxySettingsInterfaceFromResourceData any) models.ProxySettingInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](proxySettingsInterfaceFromResourceData), mapToProxySettingInput) } +// parseSchemaTags converts the tags (type schema.TypeSet) to a slice of map[string]any +// and then converts it to a slice of models.TagInput +func parseSchemaTags(tagsFromResourceData any) models.TagsInputs { + return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](tagsFromResourceData), mapToTagInput) +} + // validatePracticeWrapperInput validates that there is no empty modes in the input (because this fails the update api call) // this function is used during update of a practice since the getChange func of the terraform helper package // sometimes returns an extra empty practice -func validatePracticeWrapperInput(pracitce models.PracticeWrapperInput) bool { - if pracitce.PracticeID == "" || pracitce.MainMode == "" { +func validatePracticeWrapperInput(practice models.PracticeWrapperInput) bool { + if practice.PracticeID == "" || practice.MainMode == "" { return false } - for _, mode := range pracitce.SubPracticeModes { + for _, mode := range practice.SubPracticeModes { if mode.Mode == "" { return false } @@ -188,3 +276,11 @@ func validatePracticeWrapperInput(pracitce models.PracticeWrapperInput) bool { return true } + +func validateTag(tag models.TagInput) bool { + return tag.Key != "" && tag.Value != "" +} + +func parsemTLSs(mTLSsFromResourceData any) models.MTLSSchemas { + return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](mTLSsFromResourceData), mapToMTLSInput) +} diff --git a/internal/resources/web-api-practice.go b/internal/resources/web-api-practice.go index ddff3a88..e1463d2d 100644 --- a/internal/resources/web-api-practice.go +++ b/internal/resources/web-api-practice.go @@ -2,7 +2,6 @@ package resources import ( "context" - "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" webapipractice "github.com/CheckPointSW/terraform-provider-infinity-next/internal/resources/web-api-practice" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/utils" @@ -11,7 +10,32 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +const ( + severityLevelHigh = "High" + severityLevelMedium = "Medium" + + performanceImpactVeryLow = "VeryLow" + performanceImpactLowOrLower = "LowOrLower" + performanceImpactMediumOrLower = "MediumOrLower" + performanceImpactHighOrLower = "HighOrLower" + + visibilityShared = "Shared" + visibilityLocal = "Local" +) + func ResourceWebAPIPractice() *schema.Resource { + validationSeverityLevel := validation.ToDiagFunc( + validation.StringInSlice([]string{severityLevelLowOrAbove, severityLevelMediumOrAbove, severityLevelHighOrAbove, severityLevelCritical}, false)) + validationFileSecurityMode := validation.ToDiagFunc( + validation.StringInSlice([]string{fileSecurityModeDetect, fileSecurityModePrevent, fileSecurityModeInactive, fileSecurityModeAccordingToPractice}, false)) + validationFileSizeUnits := validation.ToDiagFunc( + validation.StringInSlice([]string{fileSizeUnitsBytes, fileSizeUnitsKB, fileSizeUnitsMB, fileSizeUnitsGB}, false)) + validationVisibility := validation.ToDiagFunc( + validation.StringInSlice([]string{visibilityShared, visibilityLocal}, false)) + validationPerformanceImpact := validation.ToDiagFunc( + validation.StringInSlice([]string{performanceImpactVeryLow, performanceImpactLowOrLower, performanceImpactMediumOrLower, performanceImpactHighOrLower}, false)) + validationMinimumSeverity := validation.ToDiagFunc( + validation.StringInSlice([]string{severityLevelCritical, severityLevelHigh, severityLevelMedium}, false)) return &schema.Resource{ Description: "Practice for securing a web API", @@ -33,6 +57,13 @@ func ResourceWebAPIPractice() *schema.Resource { Description: "The name of the resource, also acts as its unique ID", Required: true, }, + "visibility": { + Type: schema.TypeString, + Description: "The visibility of the resource, Shared or Local", + Default: "Shared", + Optional: true, + ValidateDiagFunc: validationVisibility, + }, "practice_type": { Type: schema.TypeString, Computed: true, @@ -59,17 +90,17 @@ func ResourceWebAPIPractice() *schema.Resource { }, "performance_impact": { Type: schema.TypeString, - Description: "The performance impact: LowOrLower, MediumOrLower or HighOrLower", + Description: "The performance impact: VeryLow, LowOrLower, MediumOrLower or HighOrLower", Default: "MediumOrLower", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"LowOrLower", "MediumOrLower", "HighOrLower"}, false)), + ValidateDiagFunc: validationPerformanceImpact, }, "severity_level": { Type: schema.TypeString, Description: "The severity level: LowOrAbove, MediumOrAbove, HighOrAbove or Critical", Default: "MediumOrAbove", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"}, false)), + ValidateDiagFunc: validationSeverityLevel, }, "protections_from_year": { Type: schema.TypeString, @@ -79,24 +110,24 @@ func ResourceWebAPIPractice() *schema.Resource { }, "high_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", - Default: "Prevent", + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, "medium_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", - Default: "Prevent", + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, "low_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", + Description: "Detect, Prevent, Inactive or AccordingToPractice", Default: "Detect", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, }, }, @@ -117,7 +148,7 @@ func ResourceWebAPIPractice() *schema.Resource { Description: "Medium, High or Critical", Default: "High", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Critical", "High", "Medium"}, false)), + ValidateDiagFunc: validationMinimumSeverity, }, "advanced_setting": { Type: schema.TypeSet, @@ -172,7 +203,7 @@ func ResourceWebAPIPractice() *schema.Resource { Type: schema.TypeString, Computed: true, }, - "filename": { + "name": { Type: schema.TypeString, Required: true, }, @@ -181,6 +212,125 @@ func ResourceWebAPIPractice() *schema.Resource { Sensitive: true, Required: true, }, + "size": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + }, + "is_file_exist": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + }, + }, + }, + }, + "file_security": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "severity_level": { + Type: schema.TypeString, + Description: "LowOrAbove, MediumOrAbove, HighOrAbove or Critical", + Default: "MediumOrAbove", + Optional: true, + ValidateDiagFunc: validationSeverityLevel, + }, + "high_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "medium_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "low_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "Detect", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_file_size_limit": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "file_size_limit": { + Type: schema.TypeInt, + Default: 10, + Optional: true, + }, + "file_size_limit_unit": { + Type: schema.TypeString, + Description: "Bytes, KB, MB or GB", + Default: "MB", + Optional: true, + ValidateDiagFunc: validationFileSizeUnits, + }, + "files_without_name": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "required_archive_extraction": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + "archive_file_size_limit": { + Type: schema.TypeInt, + Default: 10, + Optional: true, + }, + "archive_file_size_limit_unit": { + Type: schema.TypeString, + Description: "Bytes, KB, MB or GB", + Default: "MB", + Optional: true, + ValidateDiagFunc: validationFileSizeUnits, + }, + "allow_archive_within_archive": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_an_unopened_archive": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_file_type": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + "required_threat_emulation": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, }, }, }, diff --git a/internal/resources/web-api-practice/create.go b/internal/resources/web-api-practice/create.go index 4c2827f5..db081bf9 100644 --- a/internal/resources/web-api-practice/create.go +++ b/internal/resources/web-api-practice/create.go @@ -14,7 +14,7 @@ func CreateWebAPIPracticeInputFromResourceData(d *schema.ResourceData) (models.C var res models.CreateWebAPIPracticeInput res.Name = d.Get("name").(string) - res.Visibility = "Shared" + res.Visibility = d.Get("visibility").(string) ipsSlice := utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "ips"), mapToIPSInput) if len(ipsSlice) > 0 { res.IPS = ipsSlice[0] @@ -25,11 +25,16 @@ func CreateWebAPIPracticeInputFromResourceData(d *schema.ResourceData) (models.C res.APIAttacks = apiAttacksSlice[0] } - schemaValidationSlice := utils.Map(utils.MustResourceDataCollectionToSlice[any](d, "schema_validation"), createSchemaValidationInput) + schemaValidationSlice := utils.Map(utils.MustResourceDataCollectionToSlice[any](d, "schema_validation"), mapToSchemaValidationInput) if len(schemaValidationSlice) > 0 { res.SchemaValidation = schemaValidationSlice[0] } + fileSecuritySlice := utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "file_security"), mapToFileSecurityInput) + if len(fileSecuritySlice) > 0 { + res.FileSecurity = fileSecuritySlice[0] + } + return res, nil } @@ -41,6 +46,7 @@ func NewWebAPIPractice(ctx context.Context, c *api.Client, input models.CreateWe newWebAPIPractice(ownerId: $ownerId, subPracticeModes: $subPracticeModes, mainMode: $mainMode, practiceInput: $practiceInput) { id name + visibility practiceType category default @@ -70,8 +76,28 @@ func NewWebAPIPractice(ctx context.Context, c *api.Client, input models.CreateWe OasSchema { data name + size + isFileExist } } + FileSecurity { + id + severityLevel + highConfidence + mediumConfidence + lowConfidence + allowFileSizeLimit + fileSizeLimit + fileSizeLimitUnit + filesWithoutName + requiredArchiveExtraction + archiveFileSizeLimit + archiveFileSizeLimitUnit + allowArchiveWithinArchive + allowAnUnopenedArchive + allowFileType + requiredThreatEmulation + } } } `, "newWebAPIPractice", vars) @@ -125,8 +151,8 @@ func mapToAPIAttacksInput(apiAttacksMap map[string]any) models.APIAttacksInput { return res } -func createSchemaValidationInput(schemaValidtionFromResourceData any) models.SchemaValidationInput { - schemaValidation, err := utils.UnmarshalAs[models.FileSchema](schemaValidtionFromResourceData) +func mapToSchemaValidationInput(schemaValidationFromResourceData any) models.SchemaValidationInput { + schemaValidation, err := utils.UnmarshalAs[models.FileSchema](schemaValidationFromResourceData) if err != nil { fmt.Printf("Failed to convert input schema validation to FileSchema struct. Error: %+v", err) return models.SchemaValidationInput{} @@ -137,3 +163,23 @@ func createSchemaValidationInput(schemaValidtionFromResourceData any) models.Sch OASSchema: schemaValidation.Data, } } + +func mapToFileSecurityInput(fileSecurityMap map[string]any) models.WebAPIFileSecurityInput { + return models.WebAPIFileSecurityInput{ + SeverityLevel: fileSecurityMap["severity_level"].(string), + HighConfidence: fileSecurityMap["high_confidence"].(string), + MediumConfidence: fileSecurityMap["medium_confidence"].(string), + LowConfidence: fileSecurityMap["low_confidence"].(string), + AllowFileSizeLimit: fileSecurityMap["allow_file_size_limit"].(string), + FileSizeLimit: fileSecurityMap["file_size_limit"].(int), + FileSizeLimitUnit: fileSecurityMap["file_size_limit_unit"].(string), + FilesWithoutName: fileSecurityMap["files_without_name"].(string), + RequiredArchiveExtraction: fileSecurityMap["required_archive_extraction"].(bool), + ArchiveFileSizeLimit: fileSecurityMap["archive_file_size_limit"].(int), + ArchiveFileSizeLimitUnit: fileSecurityMap["archive_file_size_limit_unit"].(string), + AllowArchiveWithinArchive: fileSecurityMap["allow_archive_within_archive"].(string), + AllowAnUnopenedArchive: fileSecurityMap["allow_an_unopened_archive"].(string), + AllowFileType: fileSecurityMap["allow_file_type"].(bool), + RequiredThreatEmulation: fileSecurityMap["required_threat_emulation"].(bool), + } +} diff --git a/internal/resources/web-api-practice/read.go b/internal/resources/web-api-practice/read.go index c0ab1126..46b74537 100644 --- a/internal/resources/web-api-practice/read.go +++ b/internal/resources/web-api-practice/read.go @@ -18,6 +18,7 @@ func ReadWebAPIPracticeToResourceData(practice models.WebAPIPractice, d *schema. d.Set("practice_type", practice.PracticeType) d.Set("category", practice.Category) d.Set("default", practice.Default) + d.Set("visibility", practice.Visibility) ipsSchema := models.SchemaIPS{ ID: practice.IPS.ID, @@ -81,15 +82,43 @@ func ReadWebAPIPracticeToResourceData(practice models.WebAPIPractice, d *schema. ID: practice.SchemaValidation.ID, Filename: practice.SchemaValidation.OASSchema.Name, Data: decodedData, + Size: practice.SchemaValidation.OASSchema.Size, + //IsFileExist: practice.SchemaValidation.OASSchema.IsFileExist, } schemaValidationMap, err := utils.UnmarshalAs[map[string]any](schemaValidation) if err != nil { - return fmt.Errorf("failed to convert FileSchema struct to map. Error: %w", err) + return fmt.Errorf("failed to convert SchemaValidation struct to map. Error: %w", err) } d.Set("schema_validation", []map[string]any{schemaValidationMap}) + fileSecurity := models.WebApplicationFileSecuritySchema{ + ID: practice.FileSecurity.ID, + SeverityLevel: practice.FileSecurity.SeverityLevel, + HighConfidence: practice.FileSecurity.HighConfidence, + MediumConfidence: practice.FileSecurity.MediumConfidence, + LowConfidence: practice.FileSecurity.LowConfidence, + AllowFileSizeLimit: practice.FileSecurity.AllowFileSizeLimit, + FileSizeLimit: practice.FileSecurity.FileSizeLimit, + FileSizeLimitUnit: practice.FileSecurity.FileSizeLimitUnit, + FilesWithoutName: practice.FileSecurity.FilesWithoutName, + RequiredArchiveExtraction: practice.FileSecurity.RequiredArchiveExtraction, + ArchiveFileSizeLimit: practice.FileSecurity.ArchiveFileSizeLimit, + ArchiveFileSizeLimitUnit: practice.FileSecurity.ArchiveFileSizeLimitUnit, + AllowArchiveWithinArchive: practice.FileSecurity.AllowArchiveWithinArchive, + AllowAnUnopenedArchive: practice.FileSecurity.AllowAnUnopenedArchive, + AllowFileType: practice.FileSecurity.AllowFileType, + RequiredThreatEmulation: practice.FileSecurity.RequiredThreatEmulation, + } + + fileSecurityMap, err := utils.UnmarshalAs[map[string]any](fileSecurity) + if err != nil { + return fmt.Errorf("failed to convert FileSecurity struct to map. Error: %w", err) + } + + d.Set("file_security", []map[string]any{fileSecurityMap}) + return nil } @@ -99,6 +128,7 @@ func GetWebAPIPractice(ctx context.Context, c *api.Client, id string) (models.We getWebAPIPractice(id: "`+id+`") { id name + visibility practiceType category default @@ -128,8 +158,28 @@ func GetWebAPIPractice(ctx context.Context, c *api.Client, id string) (models.We OasSchema { data name + size + isFileExist } } + FileSecurity { + id + severityLevel + highConfidence + mediumConfidence + lowConfidence + allowFileSizeLimit + fileSizeLimit + fileSizeLimitUnit + filesWithoutName + requiredArchiveExtraction + archiveFileSizeLimit + archiveFileSizeLimitUnit + allowArchiveWithinArchive + allowAnUnopenedArchive + allowFileType + requiredThreatEmulation + } } } `, "getWebAPIPractice") diff --git a/internal/resources/web-api-practice/update.go b/internal/resources/web-api-practice/update.go index bf84b966..c9a6a94a 100644 --- a/internal/resources/web-api-practice/update.go +++ b/internal/resources/web-api-practice/update.go @@ -17,6 +17,10 @@ func UpdateWebAPIPracticeInputFromResourceData(d *schema.ResourceData) (models.U updateInput.Name = newName } + if _, newVisibility, hasChange := utils.MustGetChange[string](d, "visibility"); hasChange { + updateInput.Visibility = newVisibility + } + if oldIPSSlice, newIPSSlice, hasChange := utils.GetChangeWithParse(d, "ips", parseSchemaIPS); hasChange && len(newIPSSlice) > 0 { if len(oldIPSSlice) > 0 { newIPSSlice[0].ID = oldIPSSlice[0].ID @@ -41,6 +45,14 @@ func UpdateWebAPIPracticeInputFromResourceData(d *schema.ResourceData) (models.U updateInput.SchemaValidation = newSchemaValidation[0] } + if oldFileSecuritySlice, newFileSecuritySlice, hasChange := utils.GetChangeWithParse(d, "file_security", parseSchemaFileSecurity); hasChange && len(newFileSecuritySlice) > 0 { + if len(oldFileSecuritySlice) > 0 { + newFileSecuritySlice[0].ID = oldFileSecuritySlice[0].ID + } + + updateInput.FileSecurity = newFileSecuritySlice[0] + } + return updateInput, nil } @@ -77,6 +89,11 @@ func parseSchemaAPIAttacks(schemaAPIAttacks any) []models.UpdateAPIAttacksInput } func parseSchemaValidation(validation any) []models.UpdateSchemaValidationInput { - input := utils.Map(utils.MustSchemaCollectionToSlice[any](validation), createSchemaValidationInput) + input := utils.Map(utils.MustSchemaCollectionToSlice[any](validation), mapToSchemaValidationInput) return utils.Map(input, utils.MustUnmarshalAs[models.UpdateSchemaValidationInput, models.SchemaValidationInput]) } + +func parseSchemaFileSecurity(schemaFileSecurity any) []models.UpdateWebApplicationFileSecurityInput { + input := utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](schemaFileSecurity), mapToFileSecurityInput) + return utils.Map(input, utils.MustUnmarshalAs[models.UpdateWebApplicationFileSecurityInput, models.WebAPIFileSecurityInput]) +} diff --git a/internal/resources/web-app-asset.go b/internal/resources/web-app-asset.go index d44dc0dd..c966df90 100644 --- a/internal/resources/web-app-asset.go +++ b/internal/resources/web-app-asset.go @@ -2,6 +2,7 @@ package resources import ( "context" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" webappasset "github.com/CheckPointSW/terraform-provider-infinity-next/internal/resources/web-app-asset" @@ -10,7 +11,27 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const ( + mTLSServer = "server" + mTLSClient = "client" + + mTLSFileTypePEM = ".pem" + mTLSFileTypeCRT = ".crt" + mTLSFileTypeDER = ".der" + mTLSFileTypeP12 = ".p12" + mTLSFileTypePFX = ".pfx" + mTLSFileTypeP7B = ".p7b" + mTLSFileTypeP7C = ".p7c" + mTLSFileTypeCER = ".cer" +) + func ResourceWebAppAsset() *schema.Resource { + validateStateFunc := validation.ToDiagFunc(validation.StringInSlice( + []string{suggestedState, activeState, headerKey, inactiveState}, false)) + mTLSTypeValidation := validation.ToDiagFunc(validation.StringInSlice( + []string{mTLSServer, mTLSClient}, false)) + mTLSFileTypeValidation := validation.ToDiagFunc(validation.StringInSlice( + []string{mTLSFileTypePEM, mTLSFileTypeCRT, mTLSFileTypeDER, mTLSFileTypeP12, mTLSFileTypePFX, mTLSFileTypeP7B, mTLSFileTypeP7C, mTLSFileTypeCER}, false)) return &schema.Resource{ Description: "Web Application Asset", @@ -55,6 +76,11 @@ func ResourceWebAppAsset() *schema.Resource { Type: schema.TypeString, }, }, + "state": { + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: validateStateFunc, + }, "upstream_url": { Type: schema.TypeString, Description: "The URL of the application's backend server to which the reverse proxy redirects " + @@ -77,6 +103,27 @@ func ResourceWebAppAsset() *schema.Resource { Type: schema.TypeString, }, }, + "tags": { + Type: schema.TypeSet, + Description: "The tags used by the asset", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + }, + "value": { + Type: schema.TypeString, + Required: true, + }, + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, "practice": { Type: schema.TypeSet, Description: "The practices used by the asset", @@ -148,13 +195,13 @@ func ResourceWebAppAsset() *schema.Resource { }, "source_identifier": { Type: schema.TypeSet, - Description: "Defines how the source identifier valuess of the asset are retrieved", + Description: "Defines how the source identifier values of the asset are retrieved", Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "identifier": { Type: schema.TypeString, - Description: "The identifier of the source: SourceIP, XForwardedFor, HeaderKey or Cookie", + Description: "The identifier of the source: SourceIP, XForwardedFor, HeaderKey Cookie or JWTKey", Optional: true, }, "id": { @@ -222,6 +269,61 @@ func ResourceWebAppAsset() *schema.Resource { Type: schema.TypeBool, Computed: true, }, + "is_shares_urls": { + Type: schema.TypeBool, + Computed: true, + }, + "mtls": { + Type: schema.TypeSet, + Description: "The mutual TLS settings", + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "filename_id": { + Type: schema.TypeString, + Computed: true, + }, + "filename": { + Description: "The name of the certificate file", + Type: schema.TypeString, + Optional: true, + }, + "certificate_type": { + Description: "The type of the certificate file - .pem, .crt, .der, .p12, .pfx, .p7b, .p7c, .cer", + Type: schema.TypeString, + Optional: true, + ValidateDiagFunc: mTLSFileTypeValidation, + }, + "data_id": { + Type: schema.TypeString, + Computed: true, + }, + "data": { + Description: "The certificate data", + Type: schema.TypeString, + Sensitive: true, + Optional: true, + }, + "type": { + Description: "The type of the mTLS - server or client", + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: mTLSTypeValidation, + }, + "enable_id": { + Type: schema.TypeString, + Computed: true, + }, + "enable": { + Description: "Whether the mTLS is enabled", + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + }, + }, + }, }, } } diff --git a/internal/resources/web-app-asset/create.go b/internal/resources/web-app-asset/create.go index 1b767eae..c4207887 100644 --- a/internal/resources/web-app-asset/create.go +++ b/internal/resources/web-app-asset/create.go @@ -10,6 +10,19 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +const ( + mtlsTypeClient = "client" + mtlsTypeServer = "server" + + mtlsClientEnable = "isUpstreamTrustedCAFile" + mtlsClientData = "upstreamTrustedCAFile" + mtlsClientFileName = "upstreamTrustedCAFileName" + + mtlsServerEnable = "isTrustedCAListFile" + mtlsServerData = "trustedCAListFile" + mtlsServerFileName = "trustedCAListFileName" +) + func CreateWebApplicationAssetInputFromResourceData(d *schema.ResourceData) (models.CreateWebApplicationAssetInput, error) { var res models.CreateWebApplicationAssetInput @@ -21,6 +34,13 @@ func CreateWebApplicationAssetInputFromResourceData(d *schema.ResourceData) (mod res.PracticeWrappers = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "practice"), mapToPracticeWrapperInput) res.ProxySettings = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "proxy_setting"), mapToProxySettingInput) res.SourceIdentifiers = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "source_identifier"), mapToSourceIdentifierInput) + res.Tags = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "tags"), mapToTagsInputs) + res.IsSharesURLs = d.Get("is_shares_urls").(bool) + + var mtls models.MTLSSchemas + mtls = utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "mtls"), mapToMTLSInput) + + res.ProxySettings = mapMTLSToProxySettingInputs(mtls, res.ProxySettings) return res, nil } @@ -54,6 +74,11 @@ func NewWebApplicationAsset(ctx context.Context, c *api.Client, input models.Cre profiles { id } + tags { + id + key + value + } behaviors { id } @@ -85,6 +110,7 @@ func NewWebApplicationAsset(ctx context.Context, c *api.Client, input models.Cre mainAttributes intelligenceTags readOnly + isSharesURLs } } `, "newWebApplicationAsset", vars) @@ -111,15 +137,15 @@ func mapToPracticeWrapperInput(practiceWrapperMap map[string]any) models.Practic practicesModesMap := make(map[string]string) if subPracticesModes, ok := practiceWrapperMap["sub_practices_modes"]; ok { - for subPratice, mode := range subPracticesModes.(map[string]any) { - practicesModesMap[subPratice] = mode.(string) + for subPractice, mode := range subPracticesModes.(map[string]any) { + practicesModesMap[subPractice] = mode.(string) } } practiceWrapper.SubPracticeModes = make([]models.PracticeModeInput, 0, len(practicesModesMap)) - for subPratice, mode := range practicesModesMap { + for subPractice, mode := range practicesModesMap { practiceWrapper.SubPracticeModes = append(practiceWrapper.SubPracticeModes, - models.PracticeModeInput{Mode: mode, SubPractice: subPratice}) + models.PracticeModeInput{Mode: mode, SubPractice: subPractice}) } if triggersInterface, ok := practiceWrapperMap["triggers"]; ok { @@ -157,3 +183,70 @@ func mapToSourceIdentifierInput(sourceIdentifierMap map[string]any) models.Sourc return ret } + +func mapToTagsInputs(tagsMap map[string]any) models.TagInput { + var ret models.TagInput + ret.Key, ret.Value = tagsMap["key"].(string), tagsMap["value"].(string) + + if id, ok := tagsMap["id"]; ok { + ret.ID = id.(string) + } + + return ret + +} + +func mapToMTLSInput(mTLSMap map[string]any) models.MTLSSchema { + mTLSFile, err := utils.UnmarshalAs[models.MTLSSchema](mTLSMap) + if err != nil { + fmt.Printf("Failed to convert input schema validation to MTLSSchema struct. Error: %+v", err) + return models.MTLSSchema{} + } + + mTLSFile = models.NewFileSchemaEncode(mTLSFile.Filename, mTLSFile.Data, mTLSFile.Type, mTLSFile.CertificateType, mTLSFile.Enable) + + if mTLSMap["filename_id"] != nil { + mTLSFile.FilenameID = mTLSMap["filename_id"].(string) + } + + if mTLSMap["data_id"] != nil { + mTLSFile.DataID = mTLSMap["data_id"].(string) + } + + if mTLSMap["enable_id"] != nil { + mTLSFile.EnableID = mTLSMap["enable_id"].(string) + } + + return mTLSFile +} + +func mapMTLSToProxySettingInputs(mTLS models.MTLSSchemas, proxySettings models.ProxySettingInputs) models.ProxySettingInputs { + for _, mTLSFile := range mTLS { + var proxySettingEnable, proxySettingData, proxySettingFileName models.ProxySettingInput + switch mTLSFile.Type { + case mtlsTypeClient: + proxySettingEnable.Key = mtlsClientEnable + proxySettingData.Key = mtlsClientData + proxySettingFileName.Key = mtlsClientFileName + case mtlsTypeServer: + proxySettingEnable.Key = mtlsServerEnable + proxySettingData.Key = mtlsServerData + proxySettingFileName.Key = mtlsServerFileName + default: + continue + } + + if mTLSFile.Enable { + proxySettingEnable.Value = "true" + } else { + proxySettingEnable.Value = "false" + } + + proxySettingData.Value = mTLSFile.Data + proxySettingFileName.Value = mTLSFile.Filename + + proxySettings = append(proxySettings, proxySettingEnable, proxySettingData, proxySettingFileName) + } + + return proxySettings +} diff --git a/internal/resources/web-app-asset/read.go b/internal/resources/web-app-asset/read.go index 466e9964..ae9c8153 100644 --- a/internal/resources/web-app-asset/read.go +++ b/internal/resources/web-app-asset/read.go @@ -2,7 +2,10 @@ package webappasset import ( "context" + "encoding/base64" "fmt" + webAPIAssetModels "github.com/CheckPointSW/terraform-provider-infinity-next/internal/models/web-api-asset" + "strings" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" models "github.com/CheckPointSW/terraform-provider-infinity-next/internal/models/web-app-asset" @@ -10,6 +13,16 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) +func proxySettingKeyTomTLSType(proxySettingKey string) string { + if proxySettingKey == mtlsClientEnable || proxySettingKey == mtlsClientData || proxySettingKey == mtlsClientFileName { + return mtlsTypeClient + } + if proxySettingKey == mtlsServerEnable || proxySettingKey == mtlsServerData || proxySettingKey == mtlsServerFileName { + return mtlsTypeServer + } + return "" +} + func ReadWebApplicationAssetToResourceData(asset models.WebApplicationAsset, d *schema.ResourceData) error { d.SetId(asset.ID) d.Set("name", asset.Name) @@ -27,13 +40,99 @@ func ReadWebApplicationAssetToResourceData(asset models.WebApplicationAsset, d * d.Set("upstream_url", asset.UpstreamURL) d.Set("behaviors", asset.Behaviors.ToSchema()) d.Set("profiles", asset.Profiles.ToSchema()) + d.Set("is_shares_urls", asset.IsSharesURLs) - proxySettingsSchemaMap, err := utils.UnmarshalAs[[]map[string]any](asset.ProxySettings) - if err != nil { - return fmt.Errorf("failed to convert proxy settings to slice of maps. Error: %+v", err) + var proxySettingsSchemaMap []map[string]any + mTLSsSchemaMap := make(map[string]models.MTLSSchema) + var mTLSsMap []map[string]any + + for _, proxySetting := range asset.ProxySettings { + mTLSType := proxySettingKeyTomTLSType(proxySetting.Key) + if mTLSType != "" { + if _, ok := mTLSsSchemaMap[mTLSType]; !ok { + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{} + } + + switch proxySetting.Key { + case mtlsClientEnable, mtlsServerEnable: + enable := false + if proxySetting.Value == "true" { + enable = true + } + + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: mTLSsSchemaMap[mTLSType].FilenameID, + Filename: mTLSsSchemaMap[mTLSType].Filename, + CertificateType: mTLSsSchemaMap[mTLSType].CertificateType, + DataID: mTLSsSchemaMap[mTLSType].DataID, + Data: mTLSsSchemaMap[mTLSType].Data, + Type: mTLSType, + EnableID: proxySetting.ID, + Enable: enable, + } + case mtlsClientData, mtlsServerData: + var decodedData string + var fileExtensionsByType string + // proxySetting.Value format is "data:;base64," + if strings.Contains(proxySetting.Value, "base64,") { + b64Data := strings.SplitN(proxySetting.Value, "base64,", 2)[1] + bDecodedData, err := base64.StdEncoding.DecodeString(b64Data) + if err != nil { + return fmt.Errorf("failed decoding base64 string %s: %w", b64Data, err) + } + + decodedData = string(bDecodedData) + + mimeType := strings.SplitN(proxySetting.Value, ":", 2)[1] + mimeType = strings.SplitN(mimeType, ";", 2)[0] + fileExtensionsByType = webAPIAssetModels.MimeTypeToFileExtension(mimeType) + } + + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: mTLSsSchemaMap[mTLSType].FilenameID, + Filename: mTLSsSchemaMap[mTLSType].Filename, + CertificateType: fileExtensionsByType, + DataID: proxySetting.ID, + Data: decodedData, + Type: mTLSType, + EnableID: mTLSsSchemaMap[mTLSType].EnableID, + Enable: mTLSsSchemaMap[mTLSType].Enable, + } + case mtlsClientFileName, mtlsServerFileName: + mTLSsSchemaMap[mTLSType] = models.MTLSSchema{ + FilenameID: proxySetting.ID, + Filename: proxySetting.Value, + CertificateType: mTLSsSchemaMap[mTLSType].CertificateType, + DataID: mTLSsSchemaMap[mTLSType].DataID, + Data: mTLSsSchemaMap[mTLSType].Data, + Type: mTLSType, + EnableID: mTLSsSchemaMap[mTLSType].EnableID, + Enable: mTLSsSchemaMap[mTLSType].Enable, + } + default: + continue + } + } else { + proxySettingSchemaMap, err := utils.UnmarshalAs[map[string]any](proxySetting) + if err != nil { + return fmt.Errorf("failed to convert proxy setting to map. Error: %+v", err) + } + + proxySettingsSchemaMap = append(proxySettingsSchemaMap, proxySettingSchemaMap) + } + } + + for _, mTLSscehma := range mTLSsSchemaMap { + mTLS, err := utils.UnmarshalAs[map[string]any](mTLSscehma) + if err != nil { + return fmt.Errorf("failed to convert mTLS to map. Error: %+v", err) + } + + mTLSsMap = append(mTLSsMap, mTLS) } d.Set("proxy_setting", proxySettingsSchemaMap) + d.Set("mtls", mTLSsMap) sourceIdentifiersSchema := asset.SourceIdentifiers.ToSchema() sourceIdentifiersSchemaMap, err := utils.UnmarshalAs[[]map[string]any](sourceIdentifiersSchema) @@ -55,6 +154,13 @@ func ReadWebApplicationAssetToResourceData(asset models.WebApplicationAsset, d * d.Set("practice", schemaPracticeWrappersMap) + tagsSchemaMap, err := utils.UnmarshalAs[[]map[string]any](asset.Tags) + if err != nil { + return fmt.Errorf("failed to convert tags to slice of maps. Error: %+v", err) + } + + d.Set("tags", tagsSchemaMap) + return nil } @@ -88,6 +194,11 @@ func GetWebApplicationAsset(ctx context.Context, c *api.Client, id string) (mode behaviors { id } + tags { + id + key + value + } sourceIdentifiers { id sourceIdentifier @@ -116,6 +227,7 @@ func GetWebApplicationAsset(ctx context.Context, c *api.Client, id string) (mode mainAttributes intelligenceTags readOnly + isSharesURLs } } `, "getWebApplicationAsset") diff --git a/internal/resources/web-app-asset/update.go b/internal/resources/web-app-asset/update.go index 696f3aaf..86837cf6 100644 --- a/internal/resources/web-app-asset/update.go +++ b/internal/resources/web-app-asset/update.go @@ -85,12 +85,84 @@ func UpdateWebApplicationAssetInputFromResourceData(d *schema.ResourceData, asse newProxySettingsIndicators := newProxySettings.ToIndicatorsMap() for _, oldSetting := range oldProxySettings { + // if the key is mTLS type - skip it + if proxySettingKeyTomTLSType(oldSetting.Key) != "" { + continue + } + if _, ok := newProxySettingsIndicators[oldSetting.Key]; !ok { updateInput.RemoveProxySetting = append(updateInput.RemoveProxySetting, oldSetting.ID) } } } + if oldMTLSs, newMTLSs, hasChange := utils.GetChangeWithParse(d, "mtls", parsemTLSs); hasChange { + oldMTLSsIndicators := oldMTLSs.ToIndicatorMap() + mTLSsToAdd := models.MTLSSchemas{} + for _, newMTLS := range newMTLSs { + oldMTLS, ok := oldMTLSsIndicators[newMTLS.Type] + if !ok { + mTLSsToAdd = append(mTLSsToAdd, newMTLS) + continue + } + if oldMTLS.Enable != newMTLS.Enable { + var enableToString string + if newMTLS.Enable { + enableToString = "true" + } else { + enableToString = "false" + } + + key := mtlsClientEnable + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerEnable + } + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.EnableID, + Key: key, + Value: enableToString, + }) + } + + if oldMTLS.Data != newMTLS.Data { + key := mtlsClientData + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerData + } + + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.DataID, + Key: key, + Value: newMTLS.Data, + }) + } + + if oldMTLS.Filename != newMTLS.Filename { + key := mtlsClientFileName + if oldMTLS.Type == mtlsTypeServer { + key = mtlsServerFileName + } + + updateInput.UpdateProxySetting = append(updateInput.UpdateProxySetting, models.UpdateProxySetting{ + ID: oldMTLS.FilenameID, + Key: key, + Value: newMTLS.Filename, + }) + } + } + + var proxySettingsToAdd models.ProxySettingInputs + if mTLSsToAdd != nil { + proxySettingsToAdd = mapMTLSToProxySettingInputs(mTLSsToAdd, models.ProxySettingInputs{}) + } + for _, proxySettingToAdd := range proxySettingsToAdd { + updateInput.AddProxySetting = append(updateInput.AddProxySetting, models.AddProxySetting{ + Key: proxySettingToAdd.Key, + Value: proxySettingToAdd.Value, + }) + } + } + if oldSourceIdentifiers, newSourceIdentifiers, hasChange := utils.GetChangeWithParse(d, "source_identifier", parseSchemaSourceIdentifiers); hasChange { oldSourceIdentifiersIndicatorMap := oldSourceIdentifiers.ToIndicatorsMap() for _, newSourceIdentifier := range newSourceIdentifiers { @@ -118,7 +190,7 @@ func UpdateWebApplicationAssetInputFromResourceData(d *schema.ResourceData, asse SourceIdentifier: oldSourceIdentifier.SourceIdentifier, AddValues: valuesToAdd, RemoveValues: valuesIDsToRemove, - UpdateValues: []string{}, + UpdateValues: []models.UpdateSourceIdentifierValue{}, }) } @@ -130,6 +202,38 @@ func UpdateWebApplicationAssetInputFromResourceData(d *schema.ResourceData, asse } } + if oldTags, newTags, hasChange := utils.GetChangeWithParse(d, "tags", parseSchemaTags); hasChange { + oldTagsIndicatorMap := oldTags.ToIndicatorsMap() + for _, newTag := range newTags { + oldTag, ok := oldTagsIndicatorMap[newTag.Key] + // if tag does not exist - add it + if !ok { + updateInput.AddTags = append(updateInput.AddTags, models.AddTag{ + Key: newTag.Key, + Value: newTag.Value, + }) + + continue + } + + // tag exist - check if it needs to be updated + if oldTag.Value != newTag.Value { + updateInput.RemoveTags = append(updateInput.RemoveTags, oldTag.ID) + updateInput.AddTags = append(updateInput.AddTags, models.AddTag{ + Key: newTag.Key, + Value: newTag.Value, + }) + } + } + + newTagsIndicatorMap := newTags.ToIndicatorsMap() + for _, oldTag := range oldTags { + if _, ok := newTagsIndicatorMap[oldTag.Key]; !ok { + updateInput.RemoveTags = append(updateInput.RemoveTags, oldTag.ID) + } + } + } + return updateInput, nil } @@ -155,19 +259,19 @@ func UpdateWebApplicationAsset(ctx context.Context, c *api.Client, id any, input } // parseSchemaSourceIdentifiers converts the source identifiers (type schema.TypeSet) to a slice of map[string]any -// and then converts the it to a slice of modles.SourceIdentifierInput +// and then converts it to a slice of models.SourceIdentifierInput func parseSchemaSourceIdentifiers(sourceIdentifiersFromResourceData any) models.SourceIdentifiersInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](sourceIdentifiersFromResourceData), mapToSourceIdentifierInput) } // parseSchemaPracticeWrappers converts the practice wrappers (type schema.TypeSet) to a slice of map[string]any -// and then converts the it to a slice of modles.PracticeWrapperInput +// and then converts it to a slice of models.PracticeWrapperInput func parseSchemaPracticeWrappers(practiceWrappersFromResourceData any) []models.PracticeWrapperInput { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](practiceWrappersFromResourceData), mapToPracticeWrapperInput) } // parseSchemaProxySettings converts the proxy settings (type schema.TypeSet) to a slice of map[string]any -// and then converts the it to a slice of modles.PracticeWrapperInput +// and then converts it to a slice of models.PracticeWrapperInput func parseSchemaProxySettings(proxySettingsInterfaceFromResourceData any) models.ProxySettingInputs { return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](proxySettingsInterfaceFromResourceData), mapToProxySettingInput) } @@ -175,12 +279,12 @@ func parseSchemaProxySettings(proxySettingsInterfaceFromResourceData any) models // validatePracticeWrapperInput validates that there is no empty modes in the input (because this falis the update api call) // this function is used during update of a practice since the getChange func of the terraform helper package // sometimes returns an extra empty practice -func validatePracticeWrapperInput(pracitce models.PracticeWrapperInput) bool { - if pracitce.PracticeID == "" || pracitce.MainMode == "" { +func validatePracticeWrapperInput(practice models.PracticeWrapperInput) bool { + if practice.PracticeID == "" || practice.MainMode == "" { return false } - for _, mode := range pracitce.SubPracticeModes { + for _, mode := range practice.SubPracticeModes { if mode.Mode == "" { return false } @@ -188,3 +292,11 @@ func validatePracticeWrapperInput(pracitce models.PracticeWrapperInput) bool { return true } + +func parseSchemaTags(tagsFromResourceData any) models.TagsInputs { + return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](tagsFromResourceData), mapToTagsInputs) +} + +func parsemTLSs(mTLSsFromResourceData any) models.MTLSSchemas { + return utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](mTLSsFromResourceData), mapToMTLSInput) +} diff --git a/internal/resources/web-app-practice.go b/internal/resources/web-app-practice.go index 9c2b29e4..4f2fb153 100644 --- a/internal/resources/web-app-practice.go +++ b/internal/resources/web-app-practice.go @@ -2,7 +2,6 @@ package resources import ( "context" - "github.com/CheckPointSW/terraform-provider-infinity-next/internal/api" webapppractice "github.com/CheckPointSW/terraform-provider-infinity-next/internal/resources/web-app-practice" "github.com/CheckPointSW/terraform-provider-infinity-next/internal/utils" @@ -11,7 +10,43 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +const ( + severityLevelLowOrAbove = "LowOrAbove" + severityLevelMediumOrAbove = "MediumOrAbove" + severityLevelHighOrAbove = "HighOrAbove" + severityLevelCritical = "Critical" + + fileSecurityModeDetect = "Detect" + fileSecurityModePrevent = "Prevent" + fileSecurityModeInactive = "Inactive" + fileSecurityModeAccordingToPractice = "AccordingToPractice" + + fileSizeUnitsBytes = "Bytes" + fileSizeUnitsKB = "KB" + fileSizeUnitsMB = "MB" + fileSizeUnitsGB = "GB" + + waapModeDisabled = "Disabled" + waapModeLearn = "Learn" + waapModePrevent = "Prevent" + waapModePractice = "AccordingToPractice" +) + func ResourceWebAppPractice() *schema.Resource { + validationSeverityLevel := validation.ToDiagFunc( + validation.StringInSlice([]string{severityLevelLowOrAbove, severityLevelMediumOrAbove, severityLevelHighOrAbove, severityLevelCritical}, false)) + validationFileSecurityMode := validation.ToDiagFunc( + validation.StringInSlice([]string{fileSecurityModeDetect, fileSecurityModePrevent, fileSecurityModeInactive, fileSecurityModeAccordingToPractice}, false)) + validationFileSizeUnits := validation.ToDiagFunc( + validation.StringInSlice([]string{fileSizeUnitsBytes, fileSizeUnitsKB, fileSizeUnitsMB, fileSizeUnitsGB}, false)) + validationVisibility := validation.ToDiagFunc( + validation.StringInSlice([]string{visibilityShared, visibilityLocal}, false)) + validationPerformanceImpact := validation.ToDiagFunc( + validation.StringInSlice([]string{performanceImpactVeryLow, performanceImpactLowOrLower, performanceImpactMediumOrLower, performanceImpactHighOrLower}, false)) + validationMinimumSeverity := validation.ToDiagFunc( + validation.StringInSlice([]string{severityLevelCritical, severityLevelHigh, severityLevelMedium}, false)) + validationWAAPMode := validation.ToDiagFunc( + validation.StringInSlice([]string{waapModeDisabled, waapModeLearn, waapModePrevent, waapModePractice}, false)) return &schema.Resource{ Description: "Web Application Practice", @@ -33,6 +68,13 @@ func ResourceWebAppPractice() *schema.Resource { Description: "The name of the resource, also acts as its unique ID", Required: true, }, + "visibility": { + Type: schema.TypeString, + Description: "The visibility of the resource, Shared or Local", + Default: "Shared", + Optional: true, + ValidateDiagFunc: validationVisibility, + }, "practice_type": { Type: schema.TypeString, Computed: true, @@ -60,17 +102,17 @@ func ResourceWebAppPractice() *schema.Resource { }, "performance_impact": { Type: schema.TypeString, - Description: "The performance impact: LowOrLower, MediumOrLower or HighOrLower", + Description: "The performance impact: VeryLow, LowOrLower, MediumOrLower or HighOrLower", Default: "MediumOrLower", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"LowOrLower", "MediumOrLower", "HighOrLower"}, false)), + ValidateDiagFunc: validationPerformanceImpact, }, "severity_level": { Type: schema.TypeString, Description: "The severity level: LowOrAbove, MediumOrAbove, HighOrAbove or Critical", Default: "MediumOrAbove", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"LowOrAbove", "MediumOrAbove", "HighOrAbove", "Critical"}, false)), + ValidateDiagFunc: validationSeverityLevel, }, "protections_from_year": { Type: schema.TypeString, @@ -80,57 +122,25 @@ func ResourceWebAppPractice() *schema.Resource { }, "high_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", - Default: "Prevent", + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, "medium_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", - Default: "Prevent", + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, "low_confidence": { Type: schema.TypeString, - Description: "Detect, Prevent or Inactive", + Description: "Detect, Prevent, Inactive or AccordingToPractice", Default: "Detect", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Detect", "Prevent", "Inactive"}, false)), + ValidateDiagFunc: validationFileSecurityMode, }, - // "advanced_policy": { - // Type: schema.TypeSet, - // Optional: true, - // MaxItems: 1, - // Elem: &schema.Resource{ - // Schema: map[string]*schema.Schema{ - // "id": { - // Type: schema.TypeString, - // Computed: true, - // }, - // "filename": { - // Type: schema.TypeString, - // Required: true, - // }, - // "data": { - // Type: schema.TypeString, - // Sensitive: true, - // Required: true, - // }, - // "size": { - // Type: schema.TypeInt, - // Optional: true, - // Computed: true, - // }, - // "override_setting": { - // Type: schema.TypeBool, - // Default: false, - // Optional: true, - // }, - // }, - // }, - // }, }, }, }, @@ -150,7 +160,7 @@ func ResourceWebAppPractice() *schema.Resource { Description: "Medium, High or Critical", Default: "High", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Critical", "High", "Medium"}, false)), + ValidateDiagFunc: validationMinimumSeverity, }, "advanced_setting": { Type: schema.TypeSet, @@ -168,21 +178,21 @@ func ResourceWebAppPractice() *schema.Resource { Description: "Prevent, AccordingToPractice, Disabled or Learn", Default: "Disabled", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Disabled", "Learn", "Prevent", "AccordingToPractice"}, false)), + ValidateDiagFunc: validationWAAPMode, }, "open_redirect": { Type: schema.TypeString, Description: "Prevent, AccordingToPractice, Disabled or Learn", Default: "Disabled", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Disabled", "Learn", "Prevent", "AccordingToPractice"}, false)), + ValidateDiagFunc: validationWAAPMode, }, "error_disclosure": { Type: schema.TypeString, Description: "Prevent, AccordingToPractice, Disabled or Learn", Default: "Disabled", Optional: true, - ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice([]string{"Disabled", "Learn", "Prevent", "AccordingToPractice"}, false)), + ValidateDiagFunc: validationWAAPMode, }, "body_size": { Type: schema.TypeInt, @@ -260,6 +270,115 @@ func ResourceWebAppPractice() *schema.Resource { }, }, }, + "file_security": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "severity_level": { + Type: schema.TypeString, + Description: "LowOrAbove, MediumOrAbove, HighOrAbove or Critical", + Default: "MediumOrAbove", + Optional: true, + ValidateDiagFunc: validationSeverityLevel, + }, + "high_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "medium_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "low_confidence": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "Detect", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_file_size_limit": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "file_size_limit": { + Type: schema.TypeInt, + Default: 10, + Optional: true, + }, + "file_size_limit_unit": { + Type: schema.TypeString, + Description: "Bytes, KB, MB or GB", + Default: "MB", + Optional: true, + ValidateDiagFunc: validationFileSizeUnits, + }, + "files_without_name": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "required_archive_extraction": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + "archive_file_size_limit": { + Type: schema.TypeInt, + Default: 10, + Optional: true, + }, + "archive_file_size_limit_unit": { + Type: schema.TypeString, + Description: "Bytes, KB, MB or GB", + Default: "MB", + Optional: true, + ValidateDiagFunc: validationFileSizeUnits, + }, + "allow_archive_within_archive": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_an_unopened_archive": { + Type: schema.TypeString, + Description: "Detect, Prevent, Inactive or AccordingToPractice", + Default: "AccordingToPractice", + Optional: true, + ValidateDiagFunc: validationFileSecurityMode, + }, + "allow_file_type": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + "required_threat_emulation": { + Type: schema.TypeBool, + Default: false, + Optional: true, + }, + }, + }, + }, }, } } diff --git a/internal/resources/web-app-practice/create.go b/internal/resources/web-app-practice/create.go index 0007f892..b8de523e 100644 --- a/internal/resources/web-app-practice/create.go +++ b/internal/resources/web-app-practice/create.go @@ -10,8 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func mapToIPSInput(ipsMap map[string]any) models.WebApplicationPractcieIPSInput { - return models.WebApplicationPractcieIPSInput{ +func mapToIPSInput(ipsMap map[string]any) models.WebApplicationPracticeIPSInput { + return models.WebApplicationPracticeIPSInput{ PerformanceImpact: ipsMap["performance_impact"].(string), SeverityLevel: ipsMap["severity_level"].(string), ProtectionsFromYear: "Y" + ipsMap["protections_from_year"].(string), @@ -58,11 +58,31 @@ func mapToWebBotInput(webBotMap map[string]any) models.WebApplicationPracticeWeb return webBotInput } +func mapToFileSecurityInput(fileSecurityMap map[string]any) models.FileSecurityInput { + return models.FileSecurityInput{ + SeverityLevel: fileSecurityMap["severity_level"].(string), + HighConfidence: fileSecurityMap["high_confidence"].(string), + MediumConfidence: fileSecurityMap["medium_confidence"].(string), + LowConfidence: fileSecurityMap["low_confidence"].(string), + AllowFileSizeLimit: fileSecurityMap["allow_file_size_limit"].(string), + FileSizeLimit: fileSecurityMap["file_size_limit"].(int), + FileSizeLimitUnit: fileSecurityMap["file_size_limit_unit"].(string), + FilesWithoutName: fileSecurityMap["files_without_name"].(string), + RequiredArchiveExtraction: fileSecurityMap["required_archive_extraction"].(bool), + ArchiveFileSizeLimit: fileSecurityMap["archive_file_size_limit"].(int), + ArchiveFileSizeLimitUnit: fileSecurityMap["archive_file_size_limit_unit"].(string), + AllowArchiveWithinArchive: fileSecurityMap["allow_archive_within_archive"].(string), + AllowAnUnopenedArchive: fileSecurityMap["allow_an_unopened_archive"].(string), + AllowFileType: fileSecurityMap["allow_file_type"].(bool), + RequiredThreatEmulation: fileSecurityMap["required_threat_emulation"].(bool), + } +} + func CreateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) (models.CreateWebApplicationPracticeInput, error) { var res models.CreateWebApplicationPracticeInput res.Name = d.Get("name").(string) - res.Visibility = "Shared" + res.Visibility = d.Get("visibility").(string) ipsSlice := utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "ips"), mapToIPSInput) if len(ipsSlice) > 0 { res.IPS = ipsSlice[0] @@ -78,6 +98,11 @@ func CreateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( res.WebBot = webBotSlice[0] } + fileSecuritySlice := utils.Map(utils.MustResourceDataCollectionToSlice[map[string]any](d, "file_security"), mapToFileSecurityInput) + if len(fileSecuritySlice) > 0 { + res.FileSecurity = fileSecuritySlice[0] + } + return res, nil } @@ -89,6 +114,7 @@ func NewWebApplicationPractice(ctx context.Context, c *api.Client, input models. newWebApplicationPractice(ownerId: $ownerId, subPracticeModes: $subPracticeModes, mainMode: $mainMode, practiceInput: $practiceInput) { id name + visibility practiceType category default @@ -127,6 +153,24 @@ func NewWebApplicationPractice(ctx context.Context, c *api.Client, input models. URI } } + FileSecurity { + id + severityLevel + highConfidence + mediumConfidence + lowConfidence + allowFileSizeLimit + fileSizeLimit + fileSizeLimitUnit + filesWithoutName + requiredArchiveExtraction + archiveFileSizeLimit + archiveFileSizeLimitUnit + allowArchiveWithinArchive + allowAnUnopenedArchive + allowFileType + requiredThreatEmulation + } } } `, "newWebApplicationPractice", vars) diff --git a/internal/resources/web-app-practice/read.go b/internal/resources/web-app-practice/read.go index 8df32117..60b40f2b 100644 --- a/internal/resources/web-app-practice/read.go +++ b/internal/resources/web-app-practice/read.go @@ -17,6 +17,7 @@ func ReadWebApplicationPracticeToResourceData(practice models.WebApplicationPrac d.Set("practice_type", practice.PracticeType) d.Set("category", practice.Category) d.Set("default", practice.Default) + d.Set("visibility", practice.Visibility) ipsSchema := models.WebApplicationPracticeIPSSchema{ ID: practice.IPS.ID, @@ -98,6 +99,32 @@ func ReadWebApplicationPracticeToResourceData(practice models.WebApplicationPrac d.Set("web_bot", []map[string]any{webBotMap}) + fileSecurity := models.FileSecuritySchema{ + ID: practice.FileSecurity.ID, + SeverityLevel: practice.FileSecurity.SeverityLevel, + HighConfidence: practice.FileSecurity.HighConfidence, + MediumConfidence: practice.FileSecurity.MediumConfidence, + LowConfidence: practice.FileSecurity.LowConfidence, + AllowFileSizeLimit: practice.FileSecurity.AllowFileSizeLimit, + FileSizeLimit: practice.FileSecurity.FileSizeLimit, + FileSizeLimitUnit: practice.FileSecurity.FileSizeLimitUnit, + FilesWithoutName: practice.FileSecurity.FilesWithoutName, + RequiredArchiveExtraction: practice.FileSecurity.RequiredArchiveExtraction, + ArchiveFileSizeLimit: practice.FileSecurity.ArchiveFileSizeLimit, + ArchiveFileSizeLimitUnit: practice.FileSecurity.ArchiveFileSizeLimitUnit, + AllowArchiveWithinArchive: practice.FileSecurity.AllowArchiveWithinArchive, + AllowAnUnopenedArchive: practice.FileSecurity.AllowAnUnopenedArchive, + AllowFileType: practice.FileSecurity.AllowFileType, + RequiredThreatEmulation: practice.FileSecurity.RequiredThreatEmulation, + } + + fileSecurityMap, err := utils.UnmarshalAs[map[string]any](fileSecurity) + if err != nil { + return fmt.Errorf("failed to convert FileSecurity struct to map. Error: %w", err) + } + + d.Set("file_security", []map[string]any{fileSecurityMap}) + return nil } @@ -107,6 +134,7 @@ func GetWebApplicationPractice(ctx context.Context, c *api.Client, id string) (m getWebApplicationPractice(id: "`+id+`") { id name + visibility practiceType category default @@ -145,6 +173,24 @@ func GetWebApplicationPractice(ctx context.Context, c *api.Client, id string) (m URI } } + FileSecurity { + id + severityLevel + highConfidence + mediumConfidence + lowConfidence + allowFileSizeLimit + fileSizeLimit + fileSizeLimitUnit + filesWithoutName + requiredArchiveExtraction + archiveFileSizeLimit + archiveFileSizeLimitUnit + allowArchiveWithinArchive + allowAnUnopenedArchive + allowFileType + requiredThreatEmulation + } } } `, "getWebApplicationPractice") diff --git a/internal/resources/web-app-practice/update.go b/internal/resources/web-app-practice/update.go index f8c1c76a..3b9d7664 100644 --- a/internal/resources/web-app-practice/update.go +++ b/internal/resources/web-app-practice/update.go @@ -17,6 +17,10 @@ func UpdateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( updateInput.Name = newName } + if _, newVisibility, hasChange := utils.MustGetChange[string](d, "visibility"); hasChange { + updateInput.Visibility = newVisibility + } + if oldIPSSlice, newIPSSlice, hasChange := utils.GetChangeWithParse(d, "ips", parseSchemaIPS); hasChange && len(newIPSSlice) > 0 { if len(oldIPSSlice) > 0 { newIPSSlice[0].ID = oldIPSSlice[0].ID @@ -41,8 +45,8 @@ func UpdateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( oldInjectURIsToIDsMap := oldSchemaWebBot.InjectURIsIDs.ToIndicatorsMap() var removedInjectURIsIDs []string for _, removedInjectURI := range removedInjectURIs { - if removdID, ok := oldInjectURIsToIDsMap[removedInjectURI]; ok { - removedInjectURIsIDs = append(removedInjectURIsIDs, removdID) + if removedID, ok := oldInjectURIsToIDsMap[removedInjectURI]; ok { + removedInjectURIsIDs = append(removedInjectURIsIDs, removedID) } } @@ -50,8 +54,8 @@ func UpdateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( oldValidURIsToIDsMap := oldSchemaWebBot.ValidURIsIDs.ToIndicatorsMap() var removedValidURIsIDs []string for _, removedValidURI := range removedValidURIs { - if removdID, ok := oldValidURIsToIDsMap[removedValidURI]; ok { - removedValidURIsIDs = append(removedValidURIsIDs, removdID) + if removedID, ok := oldValidURIsToIDsMap[removedValidURI]; ok { + removedValidURIsIDs = append(removedValidURIsIDs, removedID) } } @@ -59,8 +63,10 @@ func UpdateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( ID: oldSchemaWebBot.ID, AddInjectURIs: addedInjectURIs, RemoveInjectURIsIDs: removedInjectURIsIDs, + UpdateInjectURIs: models.UpdateURIsInputs{}, AddValidURIs: addedValidURIs, RemoveValidURIsIDs: removedValidURIsIDs, + UpdateValidURIs: models.UpdateURIsInputs{}, } } else { @@ -71,12 +77,20 @@ func UpdateWebApplicationPracticeInputFromResourceData(d *schema.ResourceData) ( } } + if oldFileSecurity, newFileSecurity, hasChange := utils.GetChangeWithParse(d, "file_security", parseSchemaFileSecurity); hasChange && len(newFileSecurity) > 0 { + if len(oldFileSecurity) > 0 { + newFileSecurity[0].ID = oldFileSecurity[0].ID + } + + updateInput.FileSecurity = newFileSecurity[0] + } + return updateInput, nil } func parseSchemaIPS(schemaIPS any) []models.UpdateWebApplicationPracticeIPSInput { input := utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](schemaIPS), mapToIPSInput) - return utils.Map(input, utils.MustUnmarshalAs[models.UpdateWebApplicationPracticeIPSInput, models.WebApplicationPractcieIPSInput]) + return utils.Map(input, utils.MustUnmarshalAs[models.UpdateWebApplicationPracticeIPSInput, models.WebApplicationPracticeIPSInput]) } func parseSchemaWebAttacks(schemaWebAttacks any) []models.UpdateWebApplicationPracticeWebAttacksInput { @@ -119,3 +133,8 @@ func UpdateWebApplicationPractice(ctx context.Context, c *api.Client, id string, return value, err } + +func parseSchemaFileSecurity(schemaFileSecurity any) []models.UpdateFileSecurity { + input := utils.Map(utils.MustSchemaCollectionToSlice[map[string]any](schemaFileSecurity), mapToFileSecurityInput) + return utils.Map(input, utils.MustUnmarshalAs[models.UpdateFileSecurity, models.FileSecurityInput]) +} diff --git a/internal/resources/web-user-response.go b/internal/resources/web-user-response.go index 343fc892..8683de23 100644 --- a/internal/resources/web-user-response.go +++ b/internal/resources/web-user-response.go @@ -12,6 +12,7 @@ import ( ) func ResourceWebUserResponse() *schema.Resource { + validateVisibility := validation.ToDiagFunc(validation.StringInSlice([]string{visibilityShared, visibilityLocal}, false)) return &schema.Resource{ Description: "Determine the response returned to the client who initiated a blocked traffic." + "The response can be a simple HTTP error code, an HTTP redirect message, or a Block page that a user can view in their browser.", @@ -40,6 +41,13 @@ func ResourceWebUserResponse() *schema.Resource { Description: "The name of the resource, also acts as its unique ID", Required: true, }, + "visibility": { + Type: schema.TypeString, + Description: "The visibility of the web user response object", + Optional: true, + Default: "Shared", + ValidateDiagFunc: validateVisibility, + }, "mode": { Type: schema.TypeString, Description: "The type of the web user response object", diff --git a/internal/resources/web-user-response/create.go b/internal/resources/web-user-response/create.go index 24013b83..08dff7a3 100644 --- a/internal/resources/web-user-response/create.go +++ b/internal/resources/web-user-response/create.go @@ -14,7 +14,7 @@ func CreateWebUserResponseBehaviorInputFromResourceData(d *schema.ResourceData) var input models.CreateWebUserResponseBehaviorInput input.Name = d.Get("name").(string) - input.Visibility = "Shared" + input.Visibility = d.Get("visibility").(string) input.Mode = d.Get("mode").(string) input.MessageTitle = d.Get("message_title").(string) input.MessageBody = d.Get("message_body").(string) @@ -36,6 +36,7 @@ func NewWebUserResponseBehavior(ctx context.Context, c *api.Client, input models mode messageTitle messageBody + visibility httpResponseCode redirectURL xEventId diff --git a/internal/resources/web-user-response/read.go b/internal/resources/web-user-response/read.go index 72f07e11..f72b007f 100644 --- a/internal/resources/web-user-response/read.go +++ b/internal/resources/web-user-response/read.go @@ -16,6 +16,7 @@ func GetWebUserResponseBehavior(ctx context.Context, c *api.Client, id string) ( getWebUserResponseBehavior(id: "`+id+`") { id name + visibility mode messageTitle messageBody @@ -41,6 +42,7 @@ func GetWebUserResponseBehavior(ctx context.Context, c *api.Client, id string) ( func ReadWebUserResponseBehaviorToResourceData(behavior models.WebUserResponseBehavior, d *schema.ResourceData) error { d.SetId(behavior.ID) d.Set("name", behavior.Name) + d.Set("visibility", behavior.Visibility) d.Set("mode", behavior.Mode) d.Set("message_title", behavior.MessageTitle) d.Set("message_body", behavior.MessageBody) diff --git a/internal/resources/web-user-response/update.go b/internal/resources/web-user-response/update.go index 6e29edef..859623b8 100644 --- a/internal/resources/web-user-response/update.go +++ b/internal/resources/web-user-response/update.go @@ -12,6 +12,7 @@ import ( func UpdateWebUserResponseBehaviorInputFromResourceData(d *schema.ResourceData) (models.UpdateWebUserResponseBehaviorInput, error) { var res models.UpdateWebUserResponseBehaviorInput res.Name = d.Get("name").(string) + res.Visibility = d.Get("visibility").(string) res.Mode = d.Get("mode").(string) res.MessageTitle = d.Get("message_title").(string) res.MessageBody = d.Get("message_body").(string)