Skip to content

Commit

Permalink
Merge pull request #25721 from hashicorp/f-ssm-insecure-parameter-value
Browse files Browse the repository at this point in the history
ssm/parameter: Add insecure_value argument
  • Loading branch information
YakDriver authored Jul 7, 2022
2 parents 87b2ab2 + 4274889 commit 5c7a69d
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 75 deletions.
3 changes: 3 additions & 0 deletions .changelog/25721.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_ssm_parameter: Add `insecure_value` argument to enable dynamic use of SSM parameter values
```
111 changes: 73 additions & 38 deletions internal/service/ssm/parameter.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,53 @@ func ResourceParameter() *schema.Resource {
},

Schema: map[string]*schema.Schema{
"name": {
"allowed_pattern": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 2048),
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 1024),
},
"arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"data_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{
"aws:ec2:image",
"text",
}, false),
},
"description": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 1024),
},
"insecure_value": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"insecure_value", "value"},
},
"key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringLenBetween(1, 2048),
},
"overwrite": {
Type: schema.TypeBool,
Optional: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
"tier": {
Type: schema.TypeString,
Optional: true,
Expand All @@ -64,44 +100,16 @@ func ResourceParameter() *schema.Resource {
ValidateFunc: validation.StringInSlice(ssm.ParameterType_Values(), false),
},
"value": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
"arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"data_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{
"aws:ec2:image",
"text",
}, false),
},
"overwrite": {
Type: schema.TypeBool,
Optional: true,
},
"allowed_pattern": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringLenBetween(0, 1024),
Sensitive: true,
Computed: true,
ExactlyOneOf: []string{"insecure_value", "value"},
},
"version": {
Type: schema.TypeInt,
Computed: true,
},
"tags": tftags.TagsSchema(),
"tags_all": tftags.TagsSchemaComputed(),
},

CustomizeDiff: customdiff.Sequence(
Expand All @@ -113,6 +121,13 @@ func ResourceParameter() *schema.Resource {
customdiff.ComputedIf("version", func(_ context.Context, diff *schema.ResourceDiff, meta interface{}) bool {
return diff.HasChange("value")
}),
customdiff.ComputedIf("value", func(_ context.Context, diff *schema.ResourceDiff, meta interface{}) bool {
return diff.HasChange("insecure_value")
}),
customdiff.ComputedIf("insecure_value", func(_ context.Context, diff *schema.ResourceDiff, meta interface{}) bool {
return diff.HasChange("value")
}),

verify.SetTagsDiff,
),
}
Expand All @@ -125,10 +140,16 @@ func resourceParameterCreate(d *schema.ResourceData, meta interface{}) error {

name := d.Get("name").(string)

value := d.Get("value").(string)

if v, ok := d.Get("insecure_value").(string); ok && v != "" {
value = v
}

paramInput := &ssm.PutParameterInput{
Name: aws.String(name),
Type: aws.String(d.Get("type").(string)),
Value: aws.String(d.Get("value").(string)),
Value: aws.String(value),
AllowedPattern: aws.String(d.Get("allowed_pattern").(string)),
}

Expand Down Expand Up @@ -213,9 +234,18 @@ func resourceParameterRead(d *schema.ResourceData, meta interface{}) error {
name := aws.StringValue(param.Name)
d.Set("name", name)
d.Set("type", param.Type)
d.Set("value", param.Value)
d.Set("version", param.Version)

if _, ok := d.GetOk("insecure_value"); ok && aws.StringValue(param.Type) != ssm.ParameterTypeSecureString {
d.Set("insecure_value", param.Value)
} else {
d.Set("value", param.Value)
}

if aws.StringValue(param.Type) == ssm.ParameterTypeSecureString && d.Get("insecure_value").(string) != "" {
return fmt.Errorf("invalid configuration, cannot set type = %s and insecure_value", aws.StringValue(param.Type))
}

describeParamsInput := &ssm.DescribeParametersInput{
ParameterFilters: []*ssm.ParameterStringFilter{
{
Expand Down Expand Up @@ -269,11 +299,16 @@ func resourceParameterUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*conns.AWSClient).SSMConn

if d.HasChangesExcept("tags", "tags_all") {
value := d.Get("value").(string)

if v, ok := d.Get("insecure_value").(string); ok && v != "" {
value = v
}
paramInput := &ssm.PutParameterInput{
Name: aws.String(d.Get("name").(string)),
Type: aws.String(d.Get("type").(string)),
Tier: aws.String(d.Get("tier").(string)),
Value: aws.String(d.Get("value").(string)),
Value: aws.String(value),
Overwrite: aws.Bool(ShouldUpdateParameter(d)),
AllowedPattern: aws.String(d.Get("allowed_pattern").(string)),
}
Expand Down
114 changes: 102 additions & 12 deletions internal/service/ssm/parameter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ssm_test

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/aws"
Expand Down Expand Up @@ -273,7 +274,7 @@ func TestAccSSMParameter_disappears(t *testing.T) {
})
}

func TestAccSSMParameter_overwrite(t *testing.T) {
func TestAccSSMParameter_Overwrite_basic(t *testing.T) {
var param ssm.Parameter
name := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -310,7 +311,7 @@ func TestAccSSMParameter_overwrite(t *testing.T) {
}

// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/12213
func TestAccSSMParameter_overwriteCascade(t *testing.T) {
func TestAccSSMParameter_Overwrite_cascade(t *testing.T) {
name := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))

resource.ParallelTest(t, resource.TestCase{
Expand All @@ -335,7 +336,7 @@ func TestAccSSMParameter_overwriteCascade(t *testing.T) {
}

// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/18550
func TestAccSSMParameter_overwriteWithTags(t *testing.T) {
func TestAccSSMParameter_Overwrite_tags(t *testing.T) {
var param ssm.Parameter
rName := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -365,7 +366,7 @@ func TestAccSSMParameter_overwriteWithTags(t *testing.T) {
}

// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/18550
func TestAccSSMParameter_noOverwriteWithTags(t *testing.T) {
func TestAccSSMParameter_Overwrite_noOverwriteTags(t *testing.T) {
var param ssm.Parameter
rName := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -395,7 +396,7 @@ func TestAccSSMParameter_noOverwriteWithTags(t *testing.T) {
}

// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/18550
func TestAccSSMParameter_updateToOverwriteWithTags(t *testing.T) {
func TestAccSSMParameter_Overwrite_updateToTags(t *testing.T) {
var param ssm.Parameter
rName := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -508,7 +509,7 @@ func TestAccSSMParameter_updateType(t *testing.T) {
})
}

func TestAccSSMParameter_updateDescription(t *testing.T) {
func TestAccSSMParameter_Overwrite_updateDescription(t *testing.T) {
var param ssm.Parameter
name := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -604,7 +605,7 @@ func TestAccSSMParameter_fullPath(t *testing.T) {
})
}

func TestAccSSMParameter_secure(t *testing.T) {
func TestAccSSMParameter_Secure_basic(t *testing.T) {
var param ssm.Parameter
name := fmt.Sprintf("%s_%s", t.Name(), sdkacctest.RandString(10))
resourceName := "aws_ssm_parameter.test"
Expand Down Expand Up @@ -634,6 +635,85 @@ func TestAccSSMParameter_secure(t *testing.T) {
})
}

func TestAccSSMParameter_Secure_insecure(t *testing.T) {
var param ssm.Parameter
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_ssm_parameter.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ssm.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckParameterDestroy,
Steps: []resource.TestStep{
{
Config: testAccParameterConfig_insecure(rName, "String", "notsecret"),
Check: resource.ComposeTestCheckFunc(
testAccCheckParameterExists(resourceName, &param),
resource.TestCheckResourceAttr(resourceName, "insecure_value", "notsecret"),
resource.TestCheckResourceAttr(resourceName, "type", "String"),
),
},
{
Config: testAccParameterConfig_insecure(rName, "String", "newvalue"),
Check: resource.ComposeTestCheckFunc(
testAccCheckParameterExists(resourceName, &param),
resource.TestCheckResourceAttr(resourceName, "insecure_value", "newvalue"),
resource.TestCheckResourceAttr(resourceName, "type", "String"),
),
},
{
Config: testAccParameterConfig_insecure(rName, "String", "diff"),
PlanOnly: true,
ExpectNonEmptyPlan: true,
},
{
Config: testAccParameterConfig_insecure(rName, "SecureString", "notsecret"),
ExpectError: regexp.MustCompile("invalid configuration"),
},
},
})
}

func TestAccSSMParameter_Secure_insecureChangeSecure(t *testing.T) {
var param ssm.Parameter
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_ssm_parameter.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ssm.EndpointsID),
ProviderFactories: acctest.ProviderFactories,
CheckDestroy: testAccCheckParameterDestroy,
Steps: []resource.TestStep{
{
Config: testAccParameterConfig_insecure(rName, "String", "notsecret"),
Check: resource.ComposeTestCheckFunc(
testAccCheckParameterExists(resourceName, &param),
resource.TestCheckResourceAttr(resourceName, "insecure_value", "notsecret"),
resource.TestCheckResourceAttr(resourceName, "type", "String"),
),
},
{
Config: testAccParameterConfig_secure(rName, "newvalue"),
Check: resource.ComposeTestCheckFunc(
testAccCheckParameterExists(resourceName, &param),
resource.TestCheckResourceAttr(resourceName, "value", "newvalue"),
resource.TestCheckResourceAttr(resourceName, "type", "SecureString"),
),
},
{
Config: testAccParameterConfig_insecure(rName, "String", "atlantis"),
Check: resource.ComposeTestCheckFunc(
testAccCheckParameterExists(resourceName, &param),
resource.TestCheckResourceAttr(resourceName, "insecure_value", "atlantis"),
resource.TestCheckResourceAttr(resourceName, "type", "String"),
),
},
},
})
}

func TestAccSSMParameter_DataType_ec2Image(t *testing.T) {
var param ssm.Parameter
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
Expand Down Expand Up @@ -662,11 +742,11 @@ func TestAccSSMParameter_DataType_ec2Image(t *testing.T) {
})
}

func TestAccSSMParameter_secureWithKey(t *testing.T) {
func TestAccSSMParameter_Secure_key(t *testing.T) {
var param ssm.Parameter
randString := sdkacctest.RandString(10)
name := fmt.Sprintf("%s_%s", t.Name(), randString)
resourceName := "aws_ssm_parameter.secret_test"
resourceName := "aws_ssm_parameter.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand Down Expand Up @@ -697,7 +777,7 @@ func TestAccSSMParameter_Secure_keyUpdate(t *testing.T) {
var param ssm.Parameter
randString := sdkacctest.RandString(10)
name := fmt.Sprintf("%s_%s", t.Name(), randString)
resourceName := "aws_ssm_parameter.secret_test"
resourceName := "aws_ssm_parameter.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Expand Down Expand Up @@ -822,6 +902,16 @@ resource "aws_ssm_parameter" "test" {
`, rName, pType, value)
}

func testAccParameterConfig_insecure(rName, pType, value string) string {
return fmt.Sprintf(`
resource "aws_ssm_parameter" "test" {
name = %[1]q
type = %[2]q
insecure_value = %[3]q
}
`, rName, pType, value)
}

func testAccParameterConfig_tier(rName, tier string) string {
return fmt.Sprintf(`
resource "aws_ssm_parameter" "test" {
Expand Down Expand Up @@ -943,7 +1033,7 @@ resource "aws_ssm_parameter" "test_downstream" {

func testAccParameterConfig_secure(rName string, value string) string {
return fmt.Sprintf(`
resource "aws_ssm_parameter" "secret_test" {
resource "aws_ssm_parameter" "test" {
name = "test_secure_parameter-%[1]s"
description = "description for parameter %[1]s"
type = "SecureString"
Expand All @@ -954,7 +1044,7 @@ resource "aws_ssm_parameter" "secret_test" {

func testAccParameterConfig_secureKey(rName string, value string, keyAlias string) string {
return fmt.Sprintf(`
resource "aws_ssm_parameter" "secret_test" {
resource "aws_ssm_parameter" "test" {
name = "test_secure_parameter-%[1]s"
description = "description for parameter %[1]s"
type = "SecureString"
Expand Down
Loading

0 comments on commit 5c7a69d

Please sign in to comment.