From d076600efeeebb9f6a97a25f94a94be44bc1aad8 Mon Sep 17 00:00:00 2001 From: Jay Sanghani <104069497+JayS-crest@users.noreply.github.com> Date: Sat, 22 Apr 2023 02:14:49 +0530 Subject: [PATCH] inspectConfig added to jobTrigger (#7677) * inspectConfig added to jobTrigger * Test Precheck Updated * fields added to test * removed deprecated attributes contentOptions and detectionRules * customInfoTypes tests added covering all attributes * tabs removed from erb file and double space added * removed required from mentioned attributes * minor changes * Additional test for Exclusion Rule added * removing required from hotwordRegex and pattern * Spacing changed * immutable removed from customInfoType attributes * required removed from proximity * required removed from proximity and likelihoodAdjustment in rules * Tests modified and new cases added * added remaining 4 attr to test config * minor changes --- mmv1/products/dlp/JobTrigger.yaml | 421 ++++++ .../examples/dlp_job_trigger_inspect.tf.erb | 88 ++ ...e_data_loss_prevention_job_trigger_test.go | 1269 +++++++++++++++++ 3 files changed, 1778 insertions(+) create mode 100644 mmv1/templates/terraform/examples/dlp_job_trigger_inspect.tf.erb diff --git a/mmv1/products/dlp/JobTrigger.yaml b/mmv1/products/dlp/JobTrigger.yaml index fa90f9c51cea..febaa36e5599 100644 --- a/mmv1/products/dlp/JobTrigger.yaml +++ b/mmv1/products/dlp/JobTrigger.yaml @@ -77,10 +77,18 @@ examples: project: :PROJECT_NAME test_vars_overrides: name: '"tf_test_" + RandString(t, 10)' + - !ruby/object:Provider::Terraform::Examples name: "dlp_job_trigger_hybrid" primary_resource_id: "hybrid_trigger" test_env_vars: project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: "dlp_job_trigger_inspect" + primary_resource_id: "inspect" + vars: + trigger: "trigger" + test_env_vars: + project: :PROJECT_NAME custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/wrap_object.go.erb custom_import: templates/terraform/custom_import/dlp_import.go.erb @@ -100,6 +108,16 @@ properties: The resource name of the job trigger. Set by the server. output: true custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::String + name: 'createTime' + description: | + The creation timestamp of an inspectTemplate. Set by the server. + output: true + - !ruby/object:Api::Type::String + name: 'updateTime' + description: | + The last update timestamp of an inspectTemplate. Set by the server. + output: true - !ruby/object:Api::Type::String name: 'description' description: | @@ -158,6 +176,409 @@ properties: name: 'inspectTemplateName' description: The name of the template to run when this job is triggered. required: true + - !ruby/object:Api::Type::NestedObject + name: 'inspectConfig' + description: The core content of the template. + properties: + - !ruby/object:Api::Type::Boolean + name: 'excludeInfoTypes' + description: When true, excludes type information of the findings. + - !ruby/object:Api::Type::Boolean + name: 'includeQuote' + description: When true, a contextual quote from the data that triggered a + finding is included in the response. + - !ruby/object:Api::Type::Enum + name: 'minLikelihood' + description: | + Only returns findings equal or above this threshold. See https://cloud.google.com/dlp/docs/likelihood for more info + values: + - :VERY_UNLIKELY + - :UNLIKELY + - :POSSIBLE + - :LIKELY + - :VERY_LIKELY + default_value: :POSSIBLE + - !ruby/object:Api::Type::NestedObject + name: 'limits' + description: Configuration to control the number of findings returned. + properties: + - !ruby/object:Api::Type::Integer + name: 'maxFindingsPerItem' + description: Max number of findings that will be returned for each item + scanned. The maximum returned is 2000. + at_least_one_of: + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_item + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_request + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_info_type + - !ruby/object:Api::Type::Integer + name: 'maxFindingsPerRequest' + description: Max number of findings that will be returned per request/job. + The maximum returned is 2000. + at_least_one_of: + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_item + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_request + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_info_type + - !ruby/object:Api::Type::Array + name: 'maxFindingsPerInfoType' + description: | + Configuration of findings limit given for specified infoTypes. + at_least_one_of: + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_item + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_request + - inspect_job.0.inspect_config.0.limits.0.max_findings_per_info_type + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'infoType' + description: | + Type of information the findings limit applies to. Only one limit per infoType should be provided. If InfoTypeLimit does + not have an infoType, the DLP API applies the limit against all infoTypes that are found but not + specified in another InfoTypeLimit. + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Name of the information type. Either a name of your choosing when creating a CustomInfoType, or one of the names listed + at https://cloud.google.com/dlp/docs/infotypes-reference when specifying a built-in type. + - !ruby/object:Api::Type::String + name: 'version' + description: | + Version of the information type to use. By default, the version is set to stable + - !ruby/object:Api::Type::Integer + name: 'maxFindings' + description: Max findings limit for the given infoType. + - !ruby/object:Api::Type::Array + name: 'infoTypes' + description: | + Restricts what infoTypes to look for. The values must correspond to InfoType values returned by infoTypes.list + or listed at https://cloud.google.com/dlp/docs/infotypes-reference. + + When no InfoTypes or CustomInfoTypes are specified in a request, the system may automatically choose what detectors to run. + By default this may be all types, but may change over time as detectors are updated. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Name of the information type. Either a name of your choosing when creating a CustomInfoType, or one of the names listed + at https://cloud.google.com/dlp/docs/infotypes-reference when specifying a built-in type. + - !ruby/object:Api::Type::String + name: 'version' + description: | + Version of the information type to use. By default, the version is set to stable + - !ruby/object:Api::Type::Array + name: 'ruleSet' + description: | + Set of rules to apply to the findings for this InspectConfig. Exclusion rules, contained in the set are executed in the end, + other rules are executed in the order they are specified for each info type. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Array + name: 'infoTypes' + description: | + List of infoTypes this rule set is applied to. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Name of the information type. Either a name of your choosing when creating a CustomInfoType, or one of the names listed + at https://cloud.google.com/dlp/docs/infotypes-reference when specifying a built-in type. + - !ruby/object:Api::Type::String + name: 'version' + description: | + Version of the information type to use. By default, the version is set to stable. + - !ruby/object:Api::Type::Array + name: 'rules' + required: true + description: | + Set of rules to be applied to infoTypes. The rules are applied in order. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'hotwordRule' + description: Hotword-based detection rule. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'hotwordRegex' + description: Regular expression pattern defining what qualifies + as a hotword. + properties: + - !ruby/object:Api::Type::String + name: 'pattern' + description: | + Pattern defining the regular expression. Its syntax + (https://github.com/google/re2/wiki/Syntax) can be found under the google/re2 repository on GitHub. + - !ruby/object:Api::Type::Array + name: 'groupIndexes' + description: | + The index of the submatch to extract as findings. When not specified, + the entire match is returned. No more than 3 may be included. + item_type: Api::Type::Integer + - !ruby/object:Api::Type::NestedObject + name: 'proximity' + description: | + Proximity of the finding within which the entire hotword must reside. The total length of the window cannot + exceed 1000 characters. Note that the finding itself will be included in the window, so that hotwords may be + used to match substrings of the finding itself. For example, the certainty of a phone number regex + `(\d{3}) \d{3}-\d{4}` could be adjusted upwards if the area code is known to be the local area code of a company + office using the hotword regex `(xxx)`, where `xxx` is the area code in question. + properties: + - !ruby/object:Api::Type::Integer + name: 'windowBefore' + description: | + Number of characters before the finding to consider. Either this or window_after must be specified + - !ruby/object:Api::Type::Integer + name: 'windowAfter' + description: | + Number of characters after the finding to consider. Either this or window_before must be specified + - !ruby/object:Api::Type::NestedObject + name: 'likelihoodAdjustment' + description: | + Likelihood adjustment to apply to all matching findings. + properties: + - !ruby/object:Api::Type::Enum + name: 'fixedLikelihood' + description: | + Set the likelihood of a finding to a fixed value. Either this or relative_likelihood can be set. + values: + - :VERY_UNLIKELY + - :UNLIKELY + - :POSSIBLE + - :LIKELY + - :VERY_LIKELY + - !ruby/object:Api::Type::Integer + name: 'relativeLikelihood' + description: | + Increase or decrease the likelihood by the specified number of levels. For example, + if a finding would be POSSIBLE without the detection rule and relativeLikelihood is 1, + then it is upgraded to LIKELY, while a value of -1 would downgrade it to UNLIKELY. + Likelihood may never drop below VERY_UNLIKELY or exceed VERY_LIKELY, so applying an + adjustment of 1 followed by an adjustment of -1 when base likelihood is VERY_LIKELY + will result in a final likelihood of LIKELY. Either this or fixed_likelihood can be set. + - !ruby/object:Api::Type::NestedObject + name: 'exclusionRule' + description: The rule that specifies conditions when findings + of infoTypes specified in InspectionRuleSet are removed from + results. + properties: + - !ruby/object:Api::Type::Enum + name: 'matchingType' + required: true + description: | + How the rule is applied. See the documentation for more information: https://cloud.google.com/dlp/docs/reference/rest/v2/InspectConfig#MatchingType + values: + - :MATCHING_TYPE_FULL_MATCH + - :MATCHING_TYPE_PARTIAL_MATCH + - :MATCHING_TYPE_INVERSE_MATCH + - !ruby/object:Api::Type::NestedObject + name: 'dictionary' + description: Dictionary which defines the rule. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'wordList' + description: List of words or phrases to search for. + properties: + - !ruby/object:Api::Type::Array + name: 'words' + required: true + description: | + Words or phrases defining the dictionary. The dictionary must contain at least one + phrase and every phrase must contain at least 2 characters that are letters or digits. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'cloudStoragePath' + description: Newline-delimited file of words in Cloud + Storage. Only a single file is accepted. + properties: + - !ruby/object:Api::Type::String + name: 'path' + required: true + description: | + A url representing a file or path (no wildcards) in Cloud Storage. Example: `gs://[BUCKET_NAME]/dictionary.txt` + - !ruby/object:Api::Type::NestedObject + name: 'regex' + description: Regular expression which defines the rule. + properties: + - !ruby/object:Api::Type::String + name: 'pattern' + required: true + description: | + Pattern defining the regular expression. + Its syntax (https://github.com/google/re2/wiki/Syntax) can be found under the google/re2 repository on GitHub. + - !ruby/object:Api::Type::Array + name: 'groupIndexes' + description: | + The index of the submatch to extract as findings. When not specified, the entire match is returned. No more than 3 may be included. + item_type: Api::Type::Integer + - !ruby/object:Api::Type::NestedObject + name: 'excludeInfoTypes' + description: Set of infoTypes for which findings would affect + this rule. + properties: + - !ruby/object:Api::Type::Array + name: 'infoTypes' + required: true + description: | + If a finding is matched by any of the infoType detectors listed here, the finding will be excluded from the scan results. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Name of the information type. Either a name of your choosing when creating a CustomInfoType, or one of the names listed + at https://cloud.google.com/dlp/docs/infotypes-reference when specifying a built-in type. + - !ruby/object:Api::Type::String + name: 'version' + description: | + Version of the information type to use. By default, the version is set to stable. + - !ruby/object:Api::Type::NestedObject + name: 'excludeByHotword' + description: Drop if the hotword rule is contained in the proximate context. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'hotwordRegex' + description: Regular expression pattern defining what qualifies + as a hotword. + properties: + - !ruby/object:Api::Type::String + name: 'pattern' + description: | + Pattern defining the regular expression. Its syntax + (https://github.com/google/re2/wiki/Syntax) can be found under the google/re2 repository on GitHub. + - !ruby/object:Api::Type::Array + name: 'groupIndexes' + description: | + The index of the submatch to extract as findings. When not specified, + the entire match is returned. No more than 3 may be included. + item_type: Api::Type::Integer + - !ruby/object:Api::Type::NestedObject + name: 'proximity' + description: | + Proximity of the finding within which the entire hotword must reside. The total length of the window cannot + exceed 1000 characters. Note that the finding itself will be included in the window, so that hotwords may be + used to match substrings of the finding itself. For example, the certainty of a phone number regex + `(\d{3}) \d{3}-\d{4}` could be adjusted upwards if the area code is known to be the local area code of a company + office using the hotword regex `(xxx)`, where `xxx` is the area code in question. + properties: + - !ruby/object:Api::Type::Integer + name: 'windowBefore' + description: | + Number of characters before the finding to consider. Either this or window_after must be specified + - !ruby/object:Api::Type::Integer + name: 'windowAfter' + description: | + Number of characters after the finding to consider. Either this or window_before must be specified + - !ruby/object:Api::Type::Array + name: 'customInfoTypes' + description: | + Custom info types to be used. See https://cloud.google.com/dlp/docs/creating-custom-infotypes to learn more. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'infoType' + required: true + description: | + CustomInfoType can either be a new infoType, or an extension of built-in infoType, when the name matches one of existing + infoTypes and that infoType is specified in `info_types` field. Specifying the latter adds findings to the + one detected by the system. If built-in info type is not specified in `info_types` list then the name is + treated as a custom info type. + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Name of the information type. Either a name of your choosing when creating a CustomInfoType, or one of the names + listed at https://cloud.google.com/dlp/docs/infotypes-reference when specifying a built-in type. + - !ruby/object:Api::Type::String + name: 'version' + description: | + Version of the information type to use. By default, the version is set to stable. + - !ruby/object:Api::Type::Enum + name: 'likelihood' + description: | + Likelihood to return for this CustomInfoType. This base value can be altered by a detection rule if the finding meets the criteria + specified by the rule. + values: + - :VERY_UNLIKELY + - :UNLIKELY + - :POSSIBLE + - :LIKELY + - :VERY_LIKELY + default_value: :VERY_LIKELY + - !ruby/object:Api::Type::Enum + name: 'exclusionType' + description: | + If set to EXCLUSION_TYPE_EXCLUDE this infoType will not cause a finding to be returned. It still can be used for rules matching. + values: + - :EXCLUSION_TYPE_EXCLUDE + - !ruby/object:Api::Type::NestedObject + name: 'regex' + description: Regular expression which defines the rule. + properties: + - !ruby/object:Api::Type::String + name: 'pattern' + required: true + description: | + Pattern defining the regular expression. + Its syntax (https://github.com/google/re2/wiki/Syntax) can be found under the google/re2 repository on GitHub. + - !ruby/object:Api::Type::Array + name: 'groupIndexes' + description: | + The index of the submatch to extract as findings. When not specified, the entire match is returned. No more than 3 may be included. + item_type: Api::Type::Integer + - !ruby/object:Api::Type::NestedObject + name: 'dictionary' + description: Dictionary which defines the rule. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'wordList' + description: List of words or phrases to search for. + properties: + - !ruby/object:Api::Type::Array + name: 'words' + required: true + description: | + Words or phrases defining the dictionary. The dictionary must contain at least one + phrase and every phrase must contain at least 2 characters that are letters or digits. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'cloudStoragePath' + description: Newline-delimited file of words in Cloud Storage. Only + a single file is accepted. + properties: + - !ruby/object:Api::Type::String + name: 'path' + required: true + description: | + A url representing a file or path (no wildcards) in Cloud Storage. Example: `gs://[BUCKET_NAME]/dictionary.txt` + - !ruby/object:Api::Type::NestedObject + name: 'storedType' + description: A reference to a StoredInfoType to use with scanning. + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + Resource name of the requested StoredInfoType, for example `organizations/433245324/storedInfoTypes/432452342` + or `projects/project-id/storedInfoTypes/432452342`. + - !ruby/object:Api::Type::String + name: 'createTime' + description: | + The creation timestamp of an inspectTemplate. Set by the server. + output: true + - !ruby/object:Api::Type::NestedObject + name: 'surrogateType' + description: | + Message for detecting output from deidentification transformations that support reversing. + properties: [] # Meant to be an empty object with no properties - see here : https://cloud.google.com/dlp/docs/reference/rest/v2/InspectConfig#SurrogateType + # The fields below are necessary to include the "surrogateType" in the payload + send_empty_value: true + allow_empty_object: true - !ruby/object:Api::Type::NestedObject name: 'storageConfig' description: Information on where to inspect diff --git a/mmv1/templates/terraform/examples/dlp_job_trigger_inspect.tf.erb b/mmv1/templates/terraform/examples/dlp_job_trigger_inspect.tf.erb new file mode 100644 index 000000000000..2fb6637ed260 --- /dev/null +++ b/mmv1/templates/terraform/examples/dlp_job_trigger_inspect.tf.erb @@ -0,0 +1,88 @@ +resource "google_data_loss_prevention_job_trigger" "<%= ctx[:primary_resource_id] %>" { + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + description = "Description" + display_name = "Displayname" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + } + + likelihood = "UNLIKELY" + + regex { + pattern = "test*" + } + } + + info_types { + name = "EMAIL_ADDRESS" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + + rule_set { + info_types { + name = "MY_CUSTOM_TYPE" + } + rules { + hotword_rule { + hotword_regex { + pattern = "example*" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + } + } + } +} diff --git a/mmv1/third_party/terraform/tests/resource_data_loss_prevention_job_trigger_test.go b/mmv1/third_party/terraform/tests/resource_data_loss_prevention_job_trigger_test.go index 877372fa138c..d3e35536697f 100644 --- a/mmv1/third_party/terraform/tests/resource_data_loss_prevention_job_trigger_test.go +++ b/mmv1/third_party/terraform/tests/resource_data_loss_prevention_job_trigger_test.go @@ -214,6 +214,110 @@ func TestAccDataLossPreventionJobTrigger_dlpJobTriggerHybridUpdate(t *testing.T) }) } +func TestAccDataLossPreventionJobTrigger_dlpJobTriggerInspect(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": GetTestProjectFromEnv(), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataLossPreventionJobTriggerDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionJobTrigger_inspectBasic(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectUpdate(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectExclusionRule(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + }, + }) +} + +func TestAccDataLossPreventionJobTrigger_dlpJobTriggerInspectCustomInfoTypes(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project": GetTestProjectFromEnv(), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataLossPreventionJobTriggerDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesRegex(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesDictionaryWordList(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesDictionaryCloudStoragePath(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesStoredType(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesSurrogateType(context), + }, + { + ResourceName: "google_data_loss_prevention_job_trigger.inspect", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + }, + }) +} + func testAccDataLossPreventionJobTrigger_dlpJobTriggerBasic(context map[string]interface{}) string { return Nprintf(` resource "google_data_loss_prevention_job_trigger" "basic" { @@ -684,3 +788,1168 @@ resource "google_data_loss_prevention_job_trigger" "hybrid" { } `, context) } + +func testAccDataLossPreventionJobTrigger_inspectBasic(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + include_quote = false + exclude_info_types = false + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectUpdate(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + info_types { + name = "PERSON_NAME" + version = "stable" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "not-a-patient" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "UNLIKELY" + } + } + } + } + + limits { + max_findings_per_item = 1 + max_findings_per_request = 5 + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "20" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesRegex(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + version = "0.4" + } + + exclusion_type = "EXCLUSION_TYPE_EXCLUDE" + likelihood = "UNLIKELY" + + regex { + pattern = "test*" + group_indexes = [1] + } + } + + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + version = "latest" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesDictionaryWordList(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + } + + likelihood = "UNLIKELY" + + dictionary { + word_list { + words = ["TEST"] + } + } + } + + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + version = "latest" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesDictionaryCloudStoragePath(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + } + + likelihood = "UNLIKELY" + + dictionary { + cloud_storage_path { + path = "gs://mybucket/directory.txt" + } + } + } + + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + version = "latest" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + } + proximity { + window_before = 25 + window_after = 25 + } + likelihood_adjustment { + relative_likelihood = 1 + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesStoredType(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + } + + likelihood = "UNLIKELY" + + stored_type { + name = google_data_loss_prevention_stored_info_type.basic.id + } + } + + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + version = "latest" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + group_indexes = [1] + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + group_indexes = [1] + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} + +resource "google_data_loss_prevention_stored_info_type" "basic" { + parent = "projects/%{project}" + description = "Description" + display_name = "Displayname" + + regex { + pattern = "patient" + group_indexes = [2] + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectCustomInfoTypesSurrogateType(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + custom_info_types { + info_type { + name = "MY_CUSTOM_TYPE" + } + + likelihood = "UNLIKELY" + + surrogate_type {} + } + + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + version = "latest" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "FIRST_NAME" + } + rules { + exclusion_rule { + dictionary { + word_list { + words = ["TEST"] + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + hotword_rule { + hotword_regex { + pattern = "patient" + } + proximity { + window_before = 50 + } + likelihood_adjustment { + fixed_likelihood = "VERY_LIKELY" + } + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + } + } + } + } + } +} +`, context) +} + +func testAccDataLossPreventionJobTrigger_inspectExclusionRule(context map[string]interface{}) string { + return Nprintf(` +resource "google_data_loss_prevention_job_trigger" "inspect" { + parent = "projects/%{project}" + description = "Starting description" + display_name = "display" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset123" + } + } + } + } + storage_config { + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + inspect_config { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "PERSON_NAME" + } + info_types { + name = "LAST_NAME" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + info_types { + name = "FIRST_NAME" + } + + min_likelihood = "UNLIKELY" + include_quote = false + exclude_info_types = false + rule_set { + info_types { + name = "EMAIL_ADDRESS" + version = "0.1" + } + rules { + exclusion_rule { + regex { + pattern = ".+@example.com" + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "EMAIL_ADDRESS" + } + info_types { + name = "DOMAIN_NAME" + } + info_types { + name = "PHONE_NUMBER" + } + rules { + exclusion_rule { + dictionary { + cloud_storage_path { + path = "gs://mybucket/directory.txt" + } + } + matching_type = "MATCHING_TYPE_FULL_MATCH" + } + } + } + rule_set { + info_types { + name = "PERSON_NAME" + } + rules { + exclusion_rule { + exclude_by_hotword { + hotword_regex { + pattern = "patient" + group_indexes = [1] + } + proximity { + window_before = 25 + window_after = 25 + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + rule_set { + info_types { + name = "PERSON_NAME" + version = "0.1" + } + rules { + exclusion_rule { + exclude_info_types { + info_types { + name = "FIRST_NAME" + version = "0.1" + } + } + matching_type = "MATCHING_TYPE_PARTIAL_MATCH" + } + } + } + + limits { + max_findings_per_item = 10 + max_findings_per_request = 50 + max_findings_per_info_type { + max_findings = "75" + info_type { + name = "PERSON_NAME" + version = "0.1" + } + } + max_findings_per_info_type { + max_findings = "80" + info_type { + name = "LAST_NAME" + version = "0.1" + } + } + } + } + } +} +`, context) +}