Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vulnerability scanning config in Artifact Registry #20726

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/12535.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
artifactregistry: added `vulnerability_scanning_config` field to `google_artifact_registry_repository` resource
```
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,33 @@ Repository. Upstream policies cannot be set on a standard repository.`,
},
ConflictsWith: []string{"remote_repository_config"},
},
"vulnerability_scanning_config": {
Type: schema.TypeList,
Computed: true,
Optional: true,
Description: `Configuration for vulnerability scanning of artifacts stored in this repository.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enablement_config": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"INHERITED", "DISABLED", ""}),
Description: `This configures whether vulnerability scanning is automatically performed for artifacts pushed to this repository. Possible values: ["INHERITED", "DISABLED"]`,
},
"enablement_state": {
Type: schema.TypeString,
Computed: true,
Description: `This field returns whether scanning is active for this repository.`,
},
"enablement_state_reason": {
Type: schema.TypeString,
Computed: true,
Description: `This provides an explanation for the state of scanning on this repository.`,
},
},
},
},
"create_time": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -757,6 +784,12 @@ func resourceArtifactRegistryRepositoryCreate(d *schema.ResourceData, meta inter
} else if v, ok := d.GetOkExists("cleanup_policy_dry_run"); !tpgresource.IsEmptyValue(reflect.ValueOf(cleanupPolicyDryRunProp)) && (ok || !reflect.DeepEqual(v, cleanupPolicyDryRunProp)) {
obj["cleanupPolicyDryRun"] = cleanupPolicyDryRunProp
}
vulnerabilityScanningConfigProp, err := expandArtifactRegistryRepositoryVulnerabilityScanningConfig(d.Get("vulnerability_scanning_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("vulnerability_scanning_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(vulnerabilityScanningConfigProp)) && (ok || !reflect.DeepEqual(v, vulnerabilityScanningConfigProp)) {
obj["vulnerabilityScanningConfig"] = vulnerabilityScanningConfigProp
}
labelsProp, err := expandArtifactRegistryRepositoryEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -941,6 +974,9 @@ func resourceArtifactRegistryRepositoryRead(d *schema.ResourceData, meta interfa
if err := d.Set("cleanup_policy_dry_run", flattenArtifactRegistryRepositoryCleanupPolicyDryRun(res["cleanupPolicyDryRun"], d, config)); err != nil {
return fmt.Errorf("Error reading Repository: %s", err)
}
if err := d.Set("vulnerability_scanning_config", flattenArtifactRegistryRepositoryVulnerabilityScanningConfig(res["vulnerabilityScanningConfig"], d, config)); err != nil {
return fmt.Errorf("Error reading Repository: %s", err)
}
if err := d.Set("terraform_labels", flattenArtifactRegistryRepositoryTerraformLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Repository: %s", err)
}
Expand Down Expand Up @@ -1003,6 +1039,12 @@ func resourceArtifactRegistryRepositoryUpdate(d *schema.ResourceData, meta inter
} else if v, ok := d.GetOkExists("cleanup_policy_dry_run"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, cleanupPolicyDryRunProp)) {
obj["cleanupPolicyDryRun"] = cleanupPolicyDryRunProp
}
vulnerabilityScanningConfigProp, err := expandArtifactRegistryRepositoryVulnerabilityScanningConfig(d.Get("vulnerability_scanning_config"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("vulnerability_scanning_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, vulnerabilityScanningConfigProp)) {
obj["vulnerabilityScanningConfig"] = vulnerabilityScanningConfigProp
}
labelsProp, err := expandArtifactRegistryRepositoryEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -1048,6 +1090,10 @@ func resourceArtifactRegistryRepositoryUpdate(d *schema.ResourceData, meta inter
updateMask = append(updateMask, "cleanupPolicyDryRun")
}

if d.HasChange("vulnerability_scanning_config") {
updateMask = append(updateMask, "vulnerabilityScanningConfig")
}

if d.HasChange("effective_labels") {
updateMask = append(updateMask, "labels")
}
Expand Down Expand Up @@ -1737,6 +1783,35 @@ func flattenArtifactRegistryRepositoryCleanupPolicyDryRun(v interface{}, d *sche
return v
}

func flattenArtifactRegistryRepositoryVulnerabilityScanningConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["enablement_config"] =
flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementConfig(original["enablementConfig"], d, config)
transformed["enablement_state"] =
flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementState(original["enablementState"], d, config)
transformed["enablement_state_reason"] =
flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementStateReason(original["enablementStateReason"], d, config)
return []interface{}{transformed}
}
func flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementStateReason(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenArtifactRegistryRepositoryTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -2549,6 +2624,51 @@ func expandArtifactRegistryRepositoryCleanupPolicyDryRun(v interface{}, d tpgres
return v, nil
}

func expandArtifactRegistryRepositoryVulnerabilityScanningConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedEnablementConfig, err := expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementConfig(original["enablement_config"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnablementConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enablementConfig"] = transformedEnablementConfig
}

transformedEnablementState, err := expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementState(original["enablement_state"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnablementState); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enablementState"] = transformedEnablementState
}

transformedEnablementStateReason, err := expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementStateReason(original["enablement_state_reason"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnablementStateReason); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["enablementStateReason"] = transformedEnablementStateReason
}

return transformed, nil
}

func expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandArtifactRegistryRepositoryVulnerabilityScanningConfigEnablementStateReason(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandArtifactRegistryRepositoryEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,45 @@ resource "google_artifact_registry_repository" "my-repo" {
`, context)
}

func TestAccArtifactRegistryRepository_artifactRegistryRepositoryVulnerabilityScanningExample(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckArtifactRegistryRepositoryDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccArtifactRegistryRepository_artifactRegistryRepositoryVulnerabilityScanningExample(context),
},
{
ResourceName: "google_artifact_registry_repository.my-repo",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"labels", "location", "repository_id", "terraform_labels"},
},
},
})
}

func testAccArtifactRegistryRepository_artifactRegistryRepositoryVulnerabilityScanningExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_artifact_registry_repository" "my-repo" {
location = "us-central1"
repository_id = "tf-test-my-repository%{random_suffix}"
description = "example docker repository with vulnerability scanning %{random_suffix}"
format = "DOCKER"
vulnerability_scanning_config {
enablement_config = "INHERITED"
}
}
`, context)
}

func testAccCheckArtifactRegistryRepositoryDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
for name, rs := range s.RootModule().Resources {
Expand Down
39 changes: 39 additions & 0 deletions website/docs/r/artifact_registry_repository.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,25 @@ resource "google_artifact_registry_repository" "my-repo" {
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_image=gcr.io%2Fcloudshell-images%2Fcloudshell%3Alatest&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md&cloudshell_working_dir=artifact_registry_repository_vulnerability_scanning&open_in_editor=main.tf" target="_blank">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
</a>
</div>
## Example Usage - Artifact Registry Repository Vulnerability Scanning


```hcl
resource "google_artifact_registry_repository" "my-repo" {
location = "us-central1"
repository_id = "my-repository"
description = "example docker repository with vulnerability scanning config"
format = "DOCKER"
vulnerability_scanning_config {
enablement_config = "INHERITED"
}
}
```

## Argument Reference

Expand Down Expand Up @@ -725,6 +744,11 @@ The following arguments are supported:
If true, the cleanup pipeline is prevented from deleting versions in this
repository.

* `vulnerability_scanning_config` -
(Optional)
Configuration for vulnerability scanning of artifacts stored in this repository.
Structure is [documented below](#nested_vulnerability_scanning_config).

* `location` -
(Optional)
The name of the repository's location. In addition to specific regions,
Expand Down Expand Up @@ -1039,6 +1063,21 @@ The following arguments are supported:
remote repository. Must be in the format of
`projects/{project}/secrets/{secret}/versions/{version}`.

<a name="nested_vulnerability_scanning_config"></a>The `vulnerability_scanning_config` block supports:

* `enablement_config` -
(Optional)
This configures whether vulnerability scanning is automatically performed for artifacts pushed to this repository.
Possible values are: `INHERITED`, `DISABLED`.

* `enablement_state` -
(Output)
This field returns whether scanning is active for this repository.

* `enablement_state_reason` -
(Output)
This provides an explanation for the state of scanning on this repository.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are exported:
Expand Down
Loading