Skip to content

Commit

Permalink
Add Fallback parameters matching Vault PR (#2375)
Browse files Browse the repository at this point in the history
  • Loading branch information
kpcraig authored Dec 11, 2024
1 parent 4b62925 commit cac5adf
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 2 deletions.
3 changes: 3 additions & 0 deletions internal/consts/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ const (
FieldSecretNameTemplate = "secret_name_template"
FieldIAMEndpoint = "iam_endpoint"
FieldSTSEndpoint = "sts_endpoint"
FieldSTSFallbackEndpoints = "sts_fallback_endpoints"
FieldIdentityTokenAudience = "identity_token_audience"
FieldIdentityTokenTTL = "identity_token_ttl"
FieldRoleArn = "role_arn"
Expand Down Expand Up @@ -417,6 +418,7 @@ const (
FieldGranularityLevel = "granularity_level"
FieldEC2Endpoint = "ec2_endpoint"
FieldSTSRegion = "sts_region"
FieldSTSFallbackRegions = "sts_fallback_regions"
FieldIAMServerIDHeaderValue = "iam_server_id_header_value"
FieldListingVisibility = "listing_visibility"
FieldPassthroughRequestHeaders = "passthrough_request_headers"
Expand Down Expand Up @@ -528,6 +530,7 @@ const (
VaultVersion116 = "1.16.0"
VaultVersion117 = "1.17.0"
VaultVersion118 = "1.18.0"
VaultVersion119 = "1.19.0"

/*
Vault auth methods
Expand Down
1 change: 1 addition & 0 deletions internal/provider/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var (
VaultVersion116 = version.Must(version.NewSemver(consts.VaultVersion116))
VaultVersion117 = version.Must(version.NewSemver(consts.VaultVersion117))
VaultVersion118 = version.Must(version.NewSemver(consts.VaultVersion118))
VaultVersion119 = version.Must(version.NewSemver(consts.VaultVersion119))

TokenTTLMinRecommended = time.Minute * 15
)
Expand Down
79 changes: 77 additions & 2 deletions vault/resource_aws_secret_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ func awsSecretBackendResource() *schema.Resource {
Optional: true,
Description: "Specifies a custom HTTP STS endpoint to use.",
},
consts.FieldSTSRegion: {
Type: schema.TypeString,
Optional: true,
Description: "Specifies a custom STS region to use.",
},
consts.FieldSTSFallbackEndpoints: {
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Description: "Specifies a list of custom STS fallback endpoints to use (in order).",
},
consts.FieldSTSFallbackRegions: {
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Description: "Specifies a list of custom STS fallback regions to use (in order).",
},
consts.FieldUsernameTemplate: {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -163,6 +180,9 @@ func getMountCustomizeDiffFunc(field string) schema.CustomizeDiffFunc {
}

func awsSecretBackendCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
useAPIVer119 := provider.IsAPISupported(meta, provider.VaultVersion119)
useAPIVer116 := provider.IsAPISupported(meta, provider.VaultVersion116) && provider.IsEnterpriseSupported(meta)

client, e := provider.GetClient(d, meta)
if e != nil {
return diag.FromErr(e)
Expand All @@ -183,7 +203,7 @@ func awsSecretBackendCreate(ctx context.Context, d *schema.ResourceData, meta in
DefaultLeaseTTL: fmt.Sprintf("%ds", defaultTTL),
MaxLeaseTTL: fmt.Sprintf("%ds", maxTTL),
}
useAPIVer116 := provider.IsAPISupported(meta, provider.VaultVersion116) && provider.IsEnterpriseSupported(meta)

if useAPIVer116 {
identityTokenKey := d.Get(consts.FieldIdentityTokenKey).(string)
if identityTokenKey != "" {
Expand All @@ -207,12 +227,27 @@ func awsSecretBackendCreate(ctx context.Context, d *schema.ResourceData, meta in
consts.FieldAccessKey: accessKey,
consts.FieldSecretKey: secretKey,
}

for _, k := range awsSecretFields {
if v, ok := d.GetOk(k); ok {
data[k] = v.(string)
}
}

if useAPIVer119 {
if v, ok := d.GetOk(consts.FieldSTSFallbackEndpoints); ok {
data[consts.FieldSTSFallbackEndpoints] = util.ToStringArray(v.([]interface{}))
}

if v, ok := d.GetOk(consts.FieldSTSFallbackRegions); ok {
data[consts.FieldSTSFallbackRegions] = util.ToStringArray(v.([]interface{}))
}

if v, ok := d.GetOk(consts.FieldSTSRegion); ok {
data[consts.FieldSTSRegion] = v.(string)
}
}

if useAPIVer116 {
if v, ok := d.GetOk(consts.FieldIdentityTokenAudience); ok && v != "" {
data[consts.FieldIdentityTokenAudience] = v.(string)
Expand Down Expand Up @@ -244,6 +279,7 @@ func awsSecretBackendCreate(ctx context.Context, d *schema.ResourceData, meta in

func awsSecretBackendRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
useAPIVer116 := provider.IsAPISupported(meta, provider.VaultVersion116) && provider.IsEnterpriseSupported(meta)
useAPIVer119 := provider.IsAPISupported(meta, provider.VaultVersion119)

client, e := provider.GetClient(d, meta)
if e != nil {
Expand Down Expand Up @@ -304,6 +340,26 @@ func awsSecretBackendRead(ctx context.Context, d *schema.ResourceData, meta inte
}
}

if useAPIVer119 {
if v, ok := resp.Data[consts.FieldSTSFallbackEndpoints]; ok {
if err := d.Set(consts.FieldSTSFallbackEndpoints, v); err != nil {
return diag.Errorf("error reading %s for AWS Secret Backend %q: %q", consts.FieldSTSFallbackEndpoints, path, err)
}
}

if v, ok := resp.Data[consts.FieldSTSFallbackRegions]; ok {
if err := d.Set(consts.FieldSTSFallbackRegions, v); err != nil {
return diag.Errorf("error reading %s for AWS Secret Backend %q: %q", consts.FieldSTSFallbackRegions, path, err)
}
}

if v, ok := resp.Data[consts.FieldSTSRegion]; ok {
if err := d.Set(consts.FieldSTSRegion, v); err != nil {
return diag.Errorf("error reading %s for AWS Secret Backend %q: %q", consts.FieldSTSRegion, path, err)
}
}
}

if useAPIVer116 {
if err := d.Set(consts.FieldIdentityTokenAudience, resp.Data[consts.FieldIdentityTokenAudience]); err != nil {
return diag.Errorf("error reading %s for AWS Secret Backend %q: %q", consts.FieldIdentityTokenAudience, path, err)
Expand Down Expand Up @@ -343,6 +399,7 @@ func awsSecretBackendRead(ctx context.Context, d *schema.ResourceData, meta inte

func awsSecretBackendUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
useAPIVer116 := provider.IsAPISupported(meta, provider.VaultVersion116) && provider.IsEnterpriseSupported(meta)
useAPIVer119 := provider.IsAPISupported(meta, provider.VaultVersion119)

client, e := provider.GetClient(d, meta)
if e != nil {
Expand Down Expand Up @@ -377,7 +434,11 @@ func awsSecretBackendUpdate(ctx context.Context, d *schema.ResourceData, meta in
}
log.Printf("[DEBUG] Updated mount config input for %q", path)
}
if d.HasChanges(consts.FieldAccessKey, consts.FieldSecretKey, consts.FieldRegion, consts.FieldIAMEndpoint, consts.FieldSTSEndpoint, consts.FieldIdentityTokenTTL, consts.FieldIdentityTokenAudience, consts.FieldRoleArn) {
if d.HasChanges(consts.FieldAccessKey,
consts.FieldSecretKey, consts.FieldRegion, consts.FieldIAMEndpoint,
consts.FieldSTSEndpoint, consts.FieldSTSFallbackEndpoints, consts.FieldSTSRegion, consts.FieldSTSFallbackRegions,
consts.FieldIdentityTokenTTL, consts.FieldIdentityTokenAudience, consts.FieldRoleArn,
) {
log.Printf("[DEBUG] Updating root credentials at %q", path+"/config/root")
data := map[string]interface{}{
consts.FieldAccessKey: d.Get(consts.FieldAccessKey).(string),
Expand All @@ -390,6 +451,20 @@ func awsSecretBackendUpdate(ctx context.Context, d *schema.ResourceData, meta in
}
}

if useAPIVer119 {
if v, ok := d.GetOk(consts.FieldSTSFallbackEndpoints); ok {
data[consts.FieldSTSFallbackEndpoints] = util.ToStringArray(v.([]interface{}))
}

if v, ok := d.GetOk(consts.FieldSTSFallbackRegions); ok {
data[consts.FieldSTSFallbackRegions] = util.ToStringArray(v.([]interface{}))
}

if v, ok := d.GetOk(consts.FieldSTSRegion); ok {
data[consts.FieldSTSRegion] = v.(string)
}
}

if useAPIVer116 {
identityTokenAudience := d.Get(consts.FieldIdentityTokenAudience).(string)
if identityTokenAudience != "" {
Expand Down
84 changes: 84 additions & 0 deletions vault/resource_aws_secret_backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,51 @@ func TestAccAWSSecretBackend_basic(t *testing.T) {
})
}

func TestAccAWSSecretBackend_fallback(t *testing.T) {
path := acctest.RandomWithPrefix("tf-test-aws")
resourceType := "vault_aws_secret_backend"
resourceName := resourceType + ".test"
accessKey, secretKey := testutil.GetTestAWSCreds(t)
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories,
PreCheck: func() { testutil.TestAccPreCheck(t) },
CheckDestroy: testCheckMountDestroyed(resourceType, consts.MountTypeAWS, consts.FieldPath),
Steps: []resource.TestStep{
{
Config: testAccAWSSecretBackendConfig_fallback(path, accessKey, secretKey),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, consts.FieldPath, path),
resource.TestCheckResourceAttr(resourceName, consts.FieldDescription, "test description"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSEndpoint, "https://sts.us-west-1.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSRegion, "us-west-1"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".0", "us-east-2"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".1", "us-east-1"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".#", "2"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".0", "https://sts.us-east-2.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".1", "https://sts.us-east-1.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".#", "2"),
),
},
testutil.GetImportTestStep(resourceName, false, nil, consts.FieldSecretKey, consts.FieldDisableRemount),
{
Config: testAccAWSSecretBackendConfig_fallbackUpdated(path, accessKey, secretKey),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, consts.FieldPath, path),
resource.TestCheckResourceAttr(resourceName, consts.FieldDescription, "updated description"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSEndpoint, "https://sts.us-central-2.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSRegion, "us-central-2"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".0", "us-east-2"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".1", "eu-central-1"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackRegions+".#", "2"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".0", "https://sts.us-east-2.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".1", "https://sts.eu-central-1.amazonaws.com"),
resource.TestCheckResourceAttr(resourceName, consts.FieldSTSFallbackEndpoints+".#", "2"),
),
},
},
})
}

func TestAccAWSSecretBackend_wif(t *testing.T) {
path := acctest.RandomWithPrefix("tf-test-aws")
resourceType := "vault_aws_secret_backend"
Expand Down Expand Up @@ -194,6 +239,45 @@ resource "vault_aws_secret_backend" "test" {
}`, path, accessKey, secretKey)
}

func testAccAWSSecretBackendConfig_fallback(path, accessKey, secretKey string) string {
return fmt.Sprintf(`
resource "vault_aws_secret_backend" "test" {
path = "%s"
description = "test description"
default_lease_ttl_seconds = 1800
max_lease_ttl_seconds = 43200
access_key = "%s"
secret_key = "%s"
region = "us-west-1"
iam_endpoint = "https://iam.amazonaws.com"
sts_endpoint = "https://sts.us-west-1.amazonaws.com"
sts_region = "us-west-1"
sts_fallback_regions = ["us-east-2", "us-east-1"]
sts_fallback_endpoints = ["https://sts.us-east-2.amazonaws.com","https://sts.us-east-1.amazonaws.com"]
}`, path, accessKey, secretKey)
}

func testAccAWSSecretBackendConfig_fallbackUpdated(path, accessKey, secretKey string) string {
return fmt.Sprintf(`
resource "vault_aws_secret_backend" "test" {
path = "%s"
description = "updated description"
default_lease_ttl_seconds = 60
max_lease_ttl_seconds = 1000
access_key = "%s"
secret_key = "%s"
region = "us-central-2"
sts_endpoint = "https://sts.us-central-2.amazonaws.com"
sts_region = "us-central-2"
sts_fallback_regions = ["us-east-2", "eu-central-1"]
sts_fallback_endpoints = ["https://sts.us-east-2.amazonaws.com","https://sts.eu-central-1.amazonaws.com"]
}`, path, accessKey, secretKey)
}

func testAccAWSSecretBackendConfig_wifBasic(path string) string {
return fmt.Sprintf(`
resource "vault_aws_secret_backend" "test" {
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/aws_secret_backend.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ for credentials issued by this backend.

* `sts_endpoint` - (Optional) Specifies a custom HTTP STS endpoint to use.

* `sts_region` - (Optional) Specifies the region of the STS endpoint. Should be included if `sts_endpoint` is supplied. Requires Vault 1.19+

* `sts_fallback_endpoints` - (Optional) Ordered list of `sts_endpoint`s to try if the defined one fails. Requires Vault 1.19+

* `sts_fallback_regions` - (Optional) Ordered list of `sts_region`s matching the fallback endpoints. Should correspond in order with those endpoints. Requires Vault 1.19+

* `username_template` - (Optional) Template describing how dynamic usernames are generated. The username template is used to generate both IAM usernames (capped at 64 characters) and STS usernames (capped at 32 characters). If no template is provided the field defaults to the template:

* `local` - (Optional) Specifies whether the secrets mount will be marked as local. Local mounts are not replicated to performance replicas.
Expand Down

0 comments on commit cac5adf

Please sign in to comment.