Skip to content

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi could you please include your json doc as well.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Google Cloud Security Scanner Scan Config Policy Documentation

## Resource

Terraform resource: `google_security_scanner_scan_config`

This resource defines a Google Cloud Security Scanner scan configuration. It controls scan entry points, scan rate, authentication settings, excluded URL patterns, target platform, and export of scan findings.

The resource is implemented using the `google-beta` provider because the Terraform provider documentation marks `google_security_scanner_scan_config` as a beta resource.

## Implemented Policies

| Policy | Terraform argument | Included / Excluded | Justification |
|---|---|---|---|
| `starting_urls` | `starting_urls` | Included | This argument defines the URLs where the scanner begins scanning. A policy was added to require HTTPS URLs so that scanner entry points use encrypted transport instead of insecure HTTP. |
| `max_qps` | `max_qps` | Included | This argument controls the maximum scan requests per second. A policy was added to prevent overly aggressive scanning that may affect application availability. Terraform allows values from 5 to 20, but the policy applies a safer project limit. |
| `export_to_security_command_center` | `export_to_security_command_center` | Included | This argument controls whether scan configuration and scan results are exported to Security Command Center. A policy was added to require `ENABLED` so findings remain visible for central security monitoring. |
| `custom_account_login_url` | `authentication.custom_account.login_url` | Included | This argument is required when custom account authentication is used. A policy was added to require HTTPS for the login URL so authentication traffic is not sent to an insecure HTTP endpoint. |
| `blacklist_patterns` | `blacklist_patterns` | Included | This argument defines URL patterns excluded from scanning. A policy was added to require exclusions for sensitive or risky paths such as admin, logout, delete, account, or payment pages. |

## Excluded Arguments

| Terraform argument | Included / Excluded | Reason for exclusion |
|---|---|---|
| `display_name` | Excluded | This is a required display or identifier field. It does not directly create a security risk suitable for this policy set. |
| `project` | Excluded | This is environment-specific. Enforcing a fixed project value would make the policy less reusable across projects. |
| `target_platforms` | Excluded | Valid values are environment-dependent, such as `APP_ENGINE` or `COMPUTE`. There was no clear security requirement to restrict one platform over another. |
| `user_agent` | Excluded | The provider already restricts this to predefined allowed values. It is mainly scan-behaviour configuration rather than a strong security control. |
| `schedule` | Excluded | This controls operational scan timing. No security requirement was provided to enforce a specific schedule or frequency. |
| `authentication.google_account.username` | Excluded | Username format alone is not a strong security control, and authentication method choice depends on the target application. |
| `authentication.google_account.password` | Excluded | Password values are sensitive and should not be validated directly in policy output. |
| `authentication.custom_account.username` | Excluded | Username value is application-specific and does not provide a general reusable security rule. |
| `authentication.custom_account.password` | Excluded | Password values are sensitive and should not be validated directly in policy output. |
| `timeouts` | Excluded | Timeout settings are operational Terraform behaviour and do not directly affect the security posture of the scanner configuration. |
| `id` / `name` | Excluded | These are computed attributes generated by Google Cloud after resource creation, so they are not suitable for input policy validation. |

## Testing Evidence

Each policy was tested using:

1. A compliant Terraform example: `compliant_<policy_name>.tf`
2. A non-compliant Terraform example: `non_compliant_<policy_name>.tf`
3. Terraform plan output converted to JSON using `terraform show -json`
4. OPA evaluation against the generated `plan.json`

## Terraform Plan JSON

Each policy input folder includes a generated `plan.json` file. This file is created from the Terraform plan and is used by the OPA policy to evaluate compliant and non-compliant `google_security_scanner_scan_config` resources.

The `plan.json` file can be generated using:

```bash
terraform plan -out=tfplan
terraform show -json tfplan > plan.json
```

Example path:

```text
inputs/gcp/cloud_security_scanner/google_security_scanner_scan_config/blacklist_patterns/plan.json
```

The `plan.json` file contains the planned Terraform resource values that are checked by the policy rules. It helps confirm that both compliant and non-compliant Terraform resources are present in the input data used for OPA testing.

## Expected Result

- The compliant Terraform file should pass the policy.
- The non-compliant Terraform file should produce a policy violation message.
- OPA output should show the violation only for the non-compliant resource.
- The generated `plan.json` should include both compliant and non-compliant resources for the tested policy.

## Summary

The selected policies focus on arguments that directly affect security posture, scan safety, encrypted communication, centralised finding visibility, and protection of sensitive application paths. Arguments that are operational, environment-specific, sensitive, or already provider-controlled were excluded to avoid unnecessary or unreliable policy checks.
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
"starting_urls": {
"description": "The starting URLs from which the scanner finds site pages.",
"required": true,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Using insecure HTTP starting URLs can expose scan traffic to interception or manipulation.",
"rationale": "Scanner entry points should use HTTPS so the scanner communicates with encrypted endpoints.",
"compliant": "https://example.com",
"non-compliant": "http://example.com",
"parent": null
},
"max_qps": {
"description": "The maximum QPS during scanning. A valid value ranges from 5 to 20 inclusively. Defaults to 15.",
"required": false,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "A high scan request rate can affect application availability or performance.",
"rationale": "The policy limits scan rate to an approved safer value to reduce operational impact.",
"compliant": 10,
"non-compliant": 20,
"parent": null
},
"authentication": {
Expand Down Expand Up @@ -70,10 +70,16 @@
"blacklist_patterns": {
"description": "The blacklist URL patterns as described in https://cloud.google.com/security-scanner/docs/excluded-urls",
"required": false,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "If sensitive paths are not excluded, scans may interact with risky areas such as admin, logout, delete, payment, or account pages.",
"rationale": "Sensitive URL patterns should be excluded to reduce the risk of unsafe scanner behaviour.",
"compliant": [
".*admin.*",
".*logout.*",
".*delete.*",
".*payment.*",
".*account.*"
],
"non-compliant": [],
"parent": null
},
"schedule": {
Expand Down Expand Up @@ -117,19 +123,19 @@
"export_to_security_command_center": {
"description": "Controls export of scan configurations and results to Cloud Security Command Center. Default value is `ENABLED`. Possible values are: `ENABLED`, `DISABLED`.",
"required": false,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Disabling export can reduce central visibility of scanner findings.",
"rationale": "Security scanner findings should be exported to Security Command Center for centralised monitoring and response.",
"compliant": "ENABLED",
"non-compliant": "DISABLED",
"parent": null
},
"project": {
"description": "If it is not provided, the provider project is used.",
"required": null,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Using the wrong project can cause scan configurations and findings to be created in an unintended Google Cloud project, reducing visibility and control.",
"rationale": "The project should be explicitly reviewed or correctly inherited from the provider to ensure scans run against the intended environment.",
"compliant": "approved-gcp-project",
"non-compliant": "unapproved-gcp-project",
"parent": null
},
"google_account": {
Expand All @@ -153,10 +159,10 @@
"password": {
"description": "The password of the Google account. The credential is stored encrypted in GCP. **Note**: This property is sensitive and will not be displayed in the plan.",
"required": true,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Weak or exposed Google account passwords can allow unauthorised access to authenticated scan targets.",
"rationale": "Google account credentials used for scanning should be protected and managed securely to reduce the risk of credential misuse.",
"compliant": "strong-secure-password",
"non-compliant": "password123",
"parent": "google_account"
}
}
Expand All @@ -182,19 +188,19 @@
"password": {
"description": "The password of the custom account. The credential is stored encrypted in GCP. **Note**: This property is sensitive and will not be displayed in the plan.",
"required": true,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Weak or exposed custom account passwords can allow unauthorised access to the scanned application.",
"rationale": "Custom account credentials used by the scanner should be strong and securely managed to protect authenticated areas of the application.",
"compliant": "strong-secure-password",
"non-compliant": "password123",
"parent": "custom_account"
},
"login_url": {
"description": "The login form URL of the website.",
"required": true,
"security_impact": null,
"rationale": null,
"compliant": null,
"non-compliant": null,
"security_impact": "Using an HTTP login URL may expose authentication traffic and credentials.",
"rationale": "Custom account login URLs should use HTTPS to protect login data.",
"compliant": "https://example.com/login",
"non-compliant": "http://example.com/login",
"parent": "custom_account"
}
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi please give this file a relatable policy name.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
resource "google_security_scanner_scan_config" "c" {
provider = google-beta
display_name = "compliant-security-scanner"

starting_urls = ["https://example.com"]

blacklist_patterns = [
"https://example.com/admin/*",
"https://example.com/logout",
"https://example.com/delete/*"
]
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Did you generate your plan.json?

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
terraform {
required_providers {
google-beta = {
source = "hashicorp/google-beta"
}
}
}

provider "google-beta" {
project = "dummy-project"
region = "us-central1"

credentials = <<EOT
{
"type": "service_account",
"project_id": "dummy-project",
"private_key_id": "dummy",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC\n-----END PRIVATE KEY-----\n",
"client_email": "dummy@dummy-project.iam.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/dummy"
}
EOT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "google_security_scanner_scan_config" "nc" {
provider = google-beta
display_name = "nc"

starting_urls = ["https://example.com"]
blacklist_patterns = []
}
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "google_security_scanner_scan_config" "c" {
provider = google-beta
display_name = "compliant-security-scanner"

starting_urls = ["https://example.com"]

authentication {
custom_account {
username = "scanner-user"
password = "scanner-password"
login_url = "https://example.com/login"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
terraform {
required_providers {
google-beta = {
source = "hashicorp/google-beta"
}
}
}

provider "google-beta" {
project = "dummy-project"
region = "us-central1"

credentials = <<EOT
{
"type": "service_account",
"project_id": "dummy-project",
"private_key_id": "dummy",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC\n-----END PRIVATE KEY-----\n",
"client_email": "dummy@dummy-project.iam.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/dummy"
}
EOT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
resource "google_security_scanner_scan_config" "nc" {
provider = google-beta
display_name = "nc"

starting_urls = ["https://example.com"]

authentication {
custom_account {
username = "scanner-user"
password = "scanner-password"
login_url = "http://example.com/login"
}
}
}
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "google_security_scanner_scan_config" "c" {
provider = google-beta
display_name = "c"
starting_urls = ["https://example.com"]
target_platforms = ["COMPUTE"]

export_to_security_command_center = "ENABLED"
}
Loading
Loading