hashicorp / terraform-provider-googleworkspace

Terraform Provider for Google Workspace
https://registry.terraform.io/providers/hashicorp/googleworkspace
Mozilla Public License 2.0
130 stars 58 forks source link

If a policy schema has two or more fields of differing types, googleworkspace_chrome_policy validation may erroneously fail. #471

Open w0de opened 10 months ago

w0de commented 10 months ago

Terraform Version

✗ terraform -v
Terraform v1.6.4
on darwin_arm64
+ provider registry.terraform.io/hashicorp/googleworkspace v0.7.0

Affected Resource(s)

Terraform Configuration Files

provider "googleworkspace" {
  credentials             = var.credentials_path
  customer_id             = var.customer_id
  impersonated_user_email = var.subject_email
  oauth_scopes = [
    "https://www.googleapis.com/auth/gmail.settings.basic",
    "https://www.googleapis.com/auth/gmail.settings.sharing",
    "https://www.googleapis.com/auth/chrome.management.policy",
    "https://www.googleapis.com/auth/cloud-platform",
    "https://www.googleapis.com/auth/admin.directory.customer",
    "https://www.googleapis.com/auth/admin.directory.domain",
    "https://www.googleapis.com/auth/admin.directory.group",
    "https://www.googleapis.com/auth/admin.directory.orgunit",
    "https://www.googleapis.com/auth/admin.directory.rolemanagement",
    "https://www.googleapis.com/auth/admin.directory.userschema",
    "https://www.googleapis.com/auth/admin.directory.user",
    "https://www.googleapis.com/auth/apps.groups.settings",
  ]
}

resource "googleworkspace_org_unit" "base_ou" {
  name                 = "Terraform Dev Base OU"
  description          = "Hello, world"
}

resource "googleworkspace_chrome_policy" "cleanup" {
  org_unit_id = resource.googleworkspace_org_unit.base_ou.org_unit_id
  policies {
    schema_name = "chrome.users.ChromeCleanupEnabled"
    schema_values = {
      chromeCleanupEnabled          = jsonencode(true) # TYPE_BOOL
      chromeCleanupReportingEnabled = jsonencode("FALSE") # TYPE_ENUM (nullable bool)
    }
  }
}

Debug Output

https://gist.github.com/w0de/32f5f90f4440d221b1a7453fffa079f2

Panic Output

n/a

Expected Behavior

A chrome.users.DomainReliabilityAllowed policy is created with the two specified values.

Actual Behavior

No policy is created. The schema_values fail validation:

googleworkspace_chrome_policy.cleanup: Creating...
╷
│ Error: value provided for chromeCleanupEnabled is of incorrect type (expected type: TYPE_BOOL)
│
│   with googleworkspace_chrome_policy.cleanup,
│   on main.tf line 54, in resource "googleworkspace_chrome_policy" "cleanup":
│   54: resource "googleworkspace_chrome_policy" "cleanup" {
│
╵

Here's the schema:

chrome.users.ChromeCleanupEnabled ```json { "categoryTitle": "Security", "definition": { "enumType": [ { "name": "NullableBoolean", "value": [ { "name": "UNSET", "number": 1 }, { "name": "FALSE", "number": 2 }, { "name": "TRUE", "number": 3 } ] } ], "messageType": [ { "field": [ { "label": "LABEL_OPTIONAL", "name": "chromeCleanupEnabled", "number": 1, "type": "TYPE_BOOL" }, { "label": "LABEL_OPTIONAL", "name": "chromeCleanupReportingEnabled", "number": 2, "type": "TYPE_ENUM", "typeName": "NullableBoolean" } ], "name": "ChromeCleanupEnabled" } ] }, "fieldDescriptions": [ { "defaultValue": true, "description": "Enables Chrome Cleanup on Windows, which periodically scans the system for unwanted software.", "field": "chromeCleanupEnabled", "fieldDescription": "Enables Chrome Cleanup on Windows, which periodically scans the system for unwanted software.", "knownValueDescriptions": [ { "description": "Allow Chrome Cleanup to periodically scan the system and allow manual scans.", "value": "true" }, { "description": "Prevent Chrome Cleanup from periodical scans and disallow manual scans.", "value": "false" } ] }, { "defaultValue": "UNSET", "description": "Chrome Cleanup data reporting. Controls how Chrome Cleanup reports data to Google.", "field": "chromeCleanupReportingEnabled", "fieldDependencies": [ { "sourceField": "chromeCleanupEnabled", "sourceFieldValue": "true" } ], "fieldDescription": "Controls how Chrome Cleanup reports data to Google.", "knownValueDescriptions": [ { "description": "Users may choose to share results from a Chrome Cleanup cleanup run with Google.", "value": "UNSET" }, { "description": "Results from a Chrome Cleanup cleanup are always shared with Google.", "value": "TRUE" }, { "description": "Results from a Chrome Cleanup cleanup are never shared with Google.", "value": "FALSE" } ], "name": "Chrome Cleanup data reporting." } ], "name": "customers/redacted/policySchemas/chrome.users.ChromeCleanupEnabled", "policyApiLifecycle": { "policyApiLifecycleStage": "API_CURRENT" }, "policyDescription": "Chrome Cleanup.", "schemaName": "chrome.users.ChromeCleanupEnabled", "supportUri": "https://support.google.com/chrome/a/answer/2657289?hl=en#chrome_cleanup_enabled", "validTargetResources": [ "ORG_UNIT" ] } ```

Appears that validation function is indeed incorrectly validating all values against all fields: https://github.com/hashicorp/terraform-provider-googleworkspace/blob/main/internal/provider/resource_chrome_policy.go#L331-L354

Steps to Reproduce

  1. Define a policy for any schema which supports two or more schema_values of differing types (except if the types are only TYPE_ENUM and TYPE_STRING). Include one or more apparently valid schema_value(s).
  2. Attempt to create the policy with terraform apply.

Important Factoids

Also occurs if only one value is provided (absent value(s) fail). It does not occur if the types are TYPE_ENUM and TYPE_STRING only (validation logic identical?).

My dev workspace's policy schema defines 117 policies with >=2 fields of differing type (list).

References

n/a

toddthiel commented 2 months ago

The same issue exists on other policy items, in case someone wanted to see this wasn't an isolated issue. The below fails as well.

resource "googleworkspace_chrome_policy" "SafeBrowsingProtectionLevel" {
  org_unit_id = googleworkspace_org_unit.stage.id
  policies {
    schema_name = "chrome.users.SafeBrowsingProtectionLevel"
    schema_values = {
      "safeBrowsingProtectionLevel"              = jsonencode("SAFE_BROWSING_PROTECTION_LEVEL_ENUM_ENHANCED_PROTECTION")
      "safeBrowsingProxiedRealTimeChecksAllowed" = true
    }
  }
}

However, if they're the same type, it goes through just fine.

resource "googleworkspace_chrome_policy" "PrivacySandboxPromptEnabled" {
  org_unit_id = googleworkspace_org_unit.stage.id
  policies {
    schema_name = "chrome.users.PrivacySandboxPromptEnabled"
    schema_values = {
      "privacySandboxPromptEnabled"         = false
      "privacySandboxAdTopicsEnabled"       = false
      "privacySandboxSiteEnabledAdsEnabled" = false
      "privacySandboxAdMeasurementEnabled"  = false
    }
  }
}