Skip to content

Commit

Permalink
Merge pull request hashicorp#34049 from DanielRieske/f/add-image-scan…
Browse files Browse the repository at this point in the history
…ning-configuration-image-builder

Add image scanning configuration to `image_builder_image` resource
  • Loading branch information
ewbankkit authored Oct 23, 2023
2 parents 20b530b + 5a76c4f commit d01d855
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 54 deletions.
7 changes: 7 additions & 0 deletions .changelog/34049.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_imagebuilder_image: Add `image_scanning_configuration` configuration block
```

```release-note:enhancement
data-source/aws_imagebuilder_image: Add `image_scanning_configuration` attribute
```
17 changes: 17 additions & 0 deletions internal/acctest/acctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (

"github.com/YakDriver/regexache"
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
"github.com/aws/aws-sdk-go-v2/service/inspector2"
inspector2types "github.com/aws/aws-sdk-go-v2/service/inspector2/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/aws/endpoints"
Expand All @@ -41,6 +43,7 @@ import (
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/envvar"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/provider"
tfacmpca "github.com/hashicorp/terraform-provider-aws/internal/service/acmpca"
Expand Down Expand Up @@ -919,6 +922,20 @@ func PreCheckPartitionNot(t *testing.T, partitions ...string) {
}
}

func PreCheckInspector2(ctx context.Context, t *testing.T) {
conn := Provider.Meta().(*conns.AWSClient).Inspector2Client(ctx)

_, err := conn.ListDelegatedAdminAccounts(ctx, &inspector2.ListDelegatedAdminAccountsInput{})

if errs.IsA[*inspector2types.AccessDeniedException](err) {
t.Skipf("Amazon Inspector not available: %s", err)
}

if err != nil {
t.Fatalf("listing Inspector2 delegated administrators: %s", err)
}
}

func PreCheckOrganizationsAccount(ctx context.Context, t *testing.T) {
_, err := tforganizations.FindOrganization(ctx, Provider.Meta().(*conns.AWSClient).OrganizationsConn(ctx))

Expand Down
56 changes: 52 additions & 4 deletions internal/service/imagebuilder/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ func ResourceImage() *schema.Resource {
ReadWithoutTimeout: resourceImageRead,
UpdateWithoutTimeout: resourceImageUpdate,
DeleteWithoutTimeout: resourceImageDelete,

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(60 * time.Minute),
},
Expand All @@ -43,17 +45,17 @@ func ResourceImage() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"date_created": {
Type: schema.TypeString,
Computed: true,
},
"container_recipe_arn": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringMatch(regexache.MustCompile(`^arn:aws[^:]*:imagebuilder:[^:]+:(?:\d{12}|aws):container-recipe/[0-9a-z_-]+/\d+\.\d+\.\d+$`), "valid container recipe ARN must be provided"),
ExactlyOneOf: []string{"container_recipe_arn", "image_recipe_arn"},
},
"date_created": {
Type: schema.TypeString,
Computed: true,
},
"distribution_configuration_arn": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -73,6 +75,42 @@ func ResourceImage() *schema.Resource {
ValidateFunc: validation.StringMatch(regexache.MustCompile(`^arn:aws[^:]*:imagebuilder:[^:]+:(?:\d{12}|aws):image-recipe/[0-9a-z_-]+/\d+\.\d+\.\d+$`), "valid image recipe ARN must be provided"),
ExactlyOneOf: []string{"container_recipe_arn", "image_recipe_arn"},
},
"image_scanning_configuration": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ecr_configuration": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"container_tags": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"repository_name": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"image_scanning_enabled": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
},
},
"image_tests_configuration": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -202,6 +240,10 @@ func resourceImageCreate(ctx context.Context, d *schema.ResourceData, meta inter
input.ImageRecipeArn = aws.String(v.(string))
}

if v, ok := d.GetOk("image_scanning_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.ImageScanningConfiguration = expandImageScanningConfiguration(v.([]interface{})[0].(map[string]interface{}))
}

if v, ok := d.GetOk("image_tests_configuration"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
input.ImageTestsConfiguration = expandImageTestConfiguration(v.([]interface{})[0].(map[string]interface{}))
}
Expand Down Expand Up @@ -272,6 +314,12 @@ func resourceImageRead(ctx context.Context, d *schema.ResourceData, meta interfa
d.Set("image_recipe_arn", image.ImageRecipe.Arn)
}

if image.ImageScanningConfiguration != nil {
d.Set("image_scanning_configuration", []interface{}{flattenImageScanningConfiguration(image.ImageScanningConfiguration)})
} else {
d.Set("image_scanning_configuration", nil)
}

if image.ImageTestsConfiguration != nil {
d.Set("image_tests_configuration", []interface{}{flattenImageTestsConfiguration(image.ImageTestsConfiguration)})
} else {
Expand Down
37 changes: 37 additions & 0 deletions internal/service/imagebuilder/image_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,37 @@ func DataSourceImage() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"image_scanning_configuration": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ecr_configuration": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"container_tags": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"repository_name": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"image_scanning_enabled": {
Type: schema.TypeBool,
Computed: true,
},
},
},
},
"image_tests_configuration": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -193,6 +224,12 @@ func dataSourceImageRead(ctx context.Context, d *schema.ResourceData, meta inter
d.Set("image_recipe_arn", image.ImageRecipe.Arn)
}

if image.ImageScanningConfiguration != nil {
d.Set("image_scanning_configuration", []interface{}{flattenImageScanningConfiguration(image.ImageScanningConfiguration)})
} else {
d.Set("image_scanning_configuration", nil)
}

if image.ImageTestsConfiguration != nil {
d.Set("image_tests_configuration", []interface{}{flattenImageTestsConfiguration(image.ImageTestsConfiguration)})
} else {
Expand Down
12 changes: 12 additions & 0 deletions internal/service/imagebuilder/image_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func TestAccImageBuilderImageDataSource_ARN_aws(t *testing.T) { // nosemgrep:ci.
resource.TestCheckNoResourceAttr(dataSourceName, "distribution_configuration_arn"),
resource.TestCheckResourceAttr(dataSourceName, "enhanced_image_metadata_enabled", "false"),
resource.TestCheckNoResourceAttr(dataSourceName, "image_recipe_arn"),
resource.TestCheckResourceAttr(dataSourceName, "image_scanning_configuration.#", "0"),
resource.TestCheckResourceAttr(dataSourceName, "image_tests_configuration.#", "0"),
resource.TestCheckNoResourceAttr(dataSourceName, "infrastructure_configuration_arn"),
resource.TestCheckResourceAttr(dataSourceName, "name", "Amazon Linux 2 x86"),
Expand Down Expand Up @@ -69,6 +70,7 @@ func TestAccImageBuilderImageDataSource_ARN_self(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "distribution_configuration_arn", resourceName, "distribution_configuration_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "enhanced_image_metadata_enabled", resourceName, "enhanced_image_metadata_enabled"),
resource.TestCheckResourceAttrPair(dataSourceName, "image_recipe_arn", resourceName, "image_recipe_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "image_scanning_configuration.#", resourceName, "image_scanning_configuration.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "image_tests_configuration.#", resourceName, "image_tests_configuration.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "infrastructure_configuration_arn", resourceName, "infrastructure_configuration_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
Expand Down Expand Up @@ -100,6 +102,7 @@ func TestAccImageBuilderImageDataSource_ARN_containerRecipe(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "container_recipe_arn", resourceName, "container_recipe_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "image_scanning_configuration.#", resourceName, "image_scanning_configuration.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "output_resources.#", resourceName, "output_resources.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "output_resources.0.containers.#", resourceName, "output_resources.0.containers.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "output_resources.0.containers.0.image_uris.#", resourceName, "output_resources.0.containers.0.image_uris.#"),
Expand Down Expand Up @@ -362,6 +365,15 @@ resource "aws_imagebuilder_infrastructure_configuration" "test" {
resource "aws_imagebuilder_image" "test" {
container_recipe_arn = aws_imagebuilder_container_recipe.test.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
image_scanning_configuration {
image_scanning_enabled = true
ecr_configuration {
repository_name = aws_ecr_repository.test.name
container_tags = ["foo", "bar"]
}
}
}
data "aws_imagebuilder_image" "test" {
Expand Down
79 changes: 77 additions & 2 deletions internal/service/imagebuilder/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/hashicorp/terraform-provider-aws/internal/acctest"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
tfimagebuilder "github.com/hashicorp/terraform-provider-aws/internal/service/imagebuilder"
"github.com/hashicorp/terraform-provider-aws/names"
)

func TestAccImageBuilderImage_basic(t *testing.T) {
Expand Down Expand Up @@ -266,6 +267,33 @@ func TestAccImageBuilderImage_containerRecipeARN(t *testing.T) {
})
}

func TestAccImageBuilderImage_imageScanningConfiguration(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_imagebuilder_image.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
acctest.PreCheckPartitionHasService(t, names.Inspector2EndpointID)
acctest.PreCheckInspector2(ctx, t)
acctest.PreCheckOrganizationManagementAccount(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, imagebuilder.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckImageDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccImageConfig_imageScanningConfigurationEnabled(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckImageExists(ctx, resourceName),
resource.TestCheckResourceAttr(resourceName, "image_scanning_configuration.#", "1"),
),
},
},
})
}

func TestAccImageBuilderImage_outputResources_containers(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -562,14 +590,18 @@ resource "aws_imagebuilder_image" "test" {
`, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccImageConfig_containerRecipe(rName string) string {
func testAccImageConfig_containerRecipeBase(rName string) string {
return fmt.Sprintf(`
data "aws_region" "current" {}
data "aws_partition" "current" {}
resource "aws_vpc" "test" {
cidr_block = "10.0.0.0/16"
tags = {
Name = %[1]q
}
}
resource "aws_default_route_table" "test" {
Expand Down Expand Up @@ -601,12 +633,20 @@ resource "aws_default_security_group" "test" {
resource "aws_internet_gateway" "test" {
vpc_id = aws_vpc.test.id
tags = {
Name = %[1]q
}
}
resource "aws_subnet" "test" {
cidr_block = cidrsubnet(aws_vpc.test.cidr_block, 8, 0)
map_public_ip_on_launch = true
vpc_id = aws_vpc.test.id
tags = {
Name = %[1]q
}
}
resource "aws_iam_role" "test" {
Expand Down Expand Up @@ -682,10 +722,45 @@ resource "aws_imagebuilder_infrastructure_configuration" "test" {
depends_on = [aws_default_route_table.test]
}
`, rName)
}

func testAccImageConfig_containerRecipe(rName string) string {
return acctest.ConfigCompose(
testAccImageConfig_containerRecipeBase(rName),
`
resource "aws_imagebuilder_image" "test" {
container_recipe_arn = aws_imagebuilder_container_recipe.test.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
}
`, rName)
`)
}

func testAccImageConfig_imageScanningConfigurationEnabled(rName string) string {
return acctest.ConfigCompose(
testAccImageConfig_containerRecipeBase(rName),
`
data "aws_caller_identity" "current" {}
resource "aws_inspector2_enabler" "test" {
account_ids = [data.aws_caller_identity.current.account_id]
resource_types = ["ECR"]
}
resource "aws_imagebuilder_image" "test" {
container_recipe_arn = aws_imagebuilder_container_recipe.test.arn
infrastructure_configuration_arn = aws_imagebuilder_infrastructure_configuration.test.arn
image_scanning_configuration {
image_scanning_enabled = true
ecr_configuration {
repository_name = aws_ecr_repository.test.name
container_tags = ["foo", "bar"]
}
}
depends_on = [aws_inspector2_enabler.test]
}
`)
}
29 changes: 0 additions & 29 deletions internal/service/inspector2/acc_test.go

This file was deleted.

Loading

0 comments on commit d01d855

Please sign in to comment.