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

Vault 32530 add external id to aws auth backend sts role #2370

Merged
Merged
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
## Unreleased

FEATURES:
FEATURES:

* Update `vault_database_secret_backend_connection`to support `password_authentication` for PostgreSQL, allowing to encrypt password before being passed to PostgreSQL ([#2371](https://github.com/hashicorp/terraform-provider-vault/pull/2371))
* Add support for `external_id` field for the `vault_aws_auth_backend_sts_role` resource ([#2370](https://github.com/hashicorp/terraform-provider-vault/pull/2370))

## 4.5.0 (Nov 19, 2024)

Expand Down
42 changes: 36 additions & 6 deletions vault/resource_aws_auth_backend_sts_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/consts"
"github.com/hashicorp/terraform-provider-vault/internal/provider"
)

Expand Down Expand Up @@ -52,6 +53,11 @@ func awsAuthBackendSTSRoleResource() *schema.Resource {
return strings.Trim(v.(string), "/")
},
},
consts.FieldExternalID: {
Type: schema.TypeString,
Optional: true,
Description: "External ID expected by the STS role.",
},
},
}
}
Expand All @@ -65,13 +71,20 @@ func awsAuthBackendSTSRoleCreate(d *schema.ResourceData, meta interface{}) error
backend := d.Get("backend").(string)
accountID := d.Get("account_id").(string)
stsRole := d.Get("sts_role").(string)
externalID := d.Get(consts.FieldExternalID).(string)

path := awsAuthBackendSTSRolePath(backend, accountID)

log.Printf("[DEBUG] Writing STS role %q to AWS auth backend", path)
_, err := client.Logical().Write(path, map[string]interface{}{
data := map[string]interface{}{
"sts_role": stsRole,
})
}

if provider.IsAPISupported(meta, provider.VaultVersion117) {
data[consts.FieldExternalID] = externalID
}

log.Printf("[DEBUG] Writing STS role %q to AWS auth backend", path)
_, err := client.Logical().Write(path, data)

d.SetId(path)

Expand Down Expand Up @@ -117,6 +130,15 @@ func awsAuthBackendSTSRoleRead(d *schema.ResourceData, meta interface{}) error {
d.Set("backend", backend)
d.Set("account_id", accountID)
d.Set("sts_role", resp.Data["sts_role"])

if provider.IsAPISupported(meta, provider.VaultVersion117) {
if v, ok := resp.Data[consts.FieldExternalID]; ok {
if err := d.Set(consts.FieldExternalID, v); err != nil {
return err
}
}
}

return nil
}

Expand All @@ -127,12 +149,20 @@ func awsAuthBackendSTSRoleUpdate(d *schema.ResourceData, meta interface{}) error
}

stsRole := d.Get("sts_role").(string)
externalID := d.Get(consts.FieldExternalID).(string)

path := d.Id()

log.Printf("[DEBUG] Updating STS role %q in AWS auth backend", path)
_, err := client.Logical().Write(path, map[string]interface{}{
data := map[string]interface{}{
"sts_role": stsRole,
})
}

if provider.IsAPISupported(meta, provider.VaultVersion117) {
data[consts.FieldExternalID] = externalID
}

log.Printf("[DEBUG] Updating STS role %q in AWS auth backend", path)
_, err := client.Logical().Write(path, data)
if err != nil {
return fmt.Errorf("error updating STS role %q in AWS auth backend", path)
}
Expand Down
73 changes: 57 additions & 16 deletions vault/resource_aws_auth_backend_sts_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,55 @@ package vault
import (
"fmt"
"strconv"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"

"github.com/hashicorp/terraform-provider-vault/internal/consts"
"github.com/hashicorp/terraform-provider-vault/internal/provider"
"github.com/hashicorp/terraform-provider-vault/testutil"
)

func TestAccAWSAuthBackendSTSRole_import(t *testing.T) {
func TestAccAWSAuthBackendSTSRole_withExternalID(t *testing.T) {
backend := acctest.RandomWithPrefix("aws")
accountID := strconv.Itoa(acctest.RandInt())
arn := acctest.RandomWithPrefix("arn:aws:iam::" + accountID + ":role/test-role")
externalID := "external-id"
updatedExternalID := "external-id-updated"
resourceName := "vault_aws_auth_backend_sts_role.role"

resource.Test(t, resource.TestCase{
PreCheck: func() { testutil.TestAccPreCheck(t) },
PreCheck: func() {
testutil.TestAccPreCheck(t)
SkipIfAPIVersionLT(t, testProvider.Meta(), provider.VaultVersion117)
},
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckAWSAuthBackendSTSRoleDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAuthBackendSTSRoleConfig_basic(backend, accountID, arn),
Check: testAccAWSAuthBackendSTSRoleCheck_attrs(backend, accountID, arn),
Config: testAccAWSAuthBackendSTSRoleConfig(backend, accountID, arn, externalID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "backend", backend),
resource.TestCheckResourceAttr(resourceName, "account_id", accountID),
resource.TestCheckResourceAttr(resourceName, "sts_role", arn),
resource.TestCheckResourceAttr(resourceName, consts.FieldExternalID, externalID),
),
},
{
ResourceName: "vault_aws_auth_backend_sts_role.role",
// Update external ID.
Config: testAccAWSAuthBackendSTSRoleConfig(backend, accountID, arn, updatedExternalID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "backend", backend),
resource.TestCheckResourceAttr(resourceName, "account_id", accountID),
resource.TestCheckResourceAttr(resourceName, "sts_role", arn),
resource.TestCheckResourceAttr(resourceName, consts.FieldExternalID, updatedExternalID),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
Expand All @@ -49,13 +73,19 @@ func TestAccAWSAuthBackendSTSRole_basic(t *testing.T) {
CheckDestroy: testAccCheckAWSAuthBackendSTSRoleDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSAuthBackendSTSRoleConfig_basic(backend, accountID, arn),
Config: testAccAWSAuthBackendSTSRoleConfig(backend, accountID, arn, ""),
Check: testAccAWSAuthBackendSTSRoleCheck_attrs(backend, accountID, arn),
},
{
Config: testAccAWSAuthBackendSTSRoleConfig_basic(backend, accountID, updatedArn),
// Update ARN.
Config: testAccAWSAuthBackendSTSRoleConfig(backend, accountID, updatedArn, ""),
Check: testAccAWSAuthBackendSTSRoleCheck_attrs(backend, accountID, updatedArn),
},
{
ResourceName: "vault_aws_auth_backend_sts_role.role",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand Down Expand Up @@ -129,17 +159,28 @@ func testAccAWSAuthBackendSTSRoleCheck_attrs(backend, accountID, stsRole string)
}
}

func testAccAWSAuthBackendSTSRoleConfig_basic(backend, accountID, stsRole string) string {
return fmt.Sprintf(`
func testAccAWSAuthBackendSTSRoleConfig(backend, accountID, stsRole, externalID string) string {
backendResource := fmt.Sprintf(`
resource "vault_auth_backend" "aws" {
type = "aws"
path = "%s"
}
type = "aws"
path = "%s"
}`, backend)

roleResourceOptionalFields := ""
if externalID != "" {
roleResourceOptionalFields += fmt.Sprintf(`
external_id = "%s"`, externalID)
}

roleResource := fmt.Sprintf(`
resource "vault_aws_auth_backend_sts_role" "role" {
backend = vault_auth_backend.aws.path
account_id = "%s"
sts_role = "%s"
backend = vault_auth_backend.aws.path
account_id = "%s"
sts_role = "%s"%s
}
`, backend, accountID, stsRole)
`, accountID, stsRole, roleResourceOptionalFields)

resources := []string{backendResource, roleResource}

return strings.Join(resources, "\n")
}
2 changes: 2 additions & 0 deletions website/docs/r/aws_auth_backend_sts_role.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ The following arguments are supported:
* `backend` - (Optional) The path the AWS auth backend being configured was
mounted at. Defaults to `aws`.

* `external_id` - (Optional) External ID expected by the STS role. The associated STS role must be configured to require the external ID. Requires Vault 1.17+.

## Attributes Reference

No additional attributes are exported by this resource.
Expand Down