Skip to content
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
7 changes: 7 additions & 0 deletions docs/resources/auth_method.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ resource "boundary_auth_method" "password" {
scope_id = boundary_scope.org.id
type = "password"
}

resource "boundary_auth_method" "password_is_primary" {
scope_id = boundary_scope.org.id
type = "password"
is_primary_for_scope = true
}
```

<!-- schema generated by tfplugindocs -->
Expand All @@ -38,6 +44,7 @@ resource "boundary_auth_method" "password" {
### Optional

- `description` (String) The auth method description.
- `is_primary_for_scope` (Boolean) When true, makes this auth method the primary auth method for the scope in which it resides.
- `min_login_name_length` (Number, Deprecated) The minimum login name length.
- `min_password_length` (Number, Deprecated) The minimum password length.
- `name` (String) The auth method name. Defaults to the resource name.
Expand Down
32 changes: 31 additions & 1 deletion docs/resources/auth_method_password.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,26 @@ description: |-

The auth method resource allows you to configure a Boundary auth_method_password.


## Example Usage

```terraform
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first scope!"
scope_id = "global"
auto_create_admin_role = true
auto_create_default_role = true
}

resource "boundary_auth_method_password" "password" {
scope_id = boundary_scope.org.id
}

resource "boundary_auth_method_password" "password_is_primary" {
scope_id = boundary_scope.org.id
is_primary_for_scope = true
}
```

<!-- schema generated by tfplugindocs -->
## Schema
Expand All @@ -22,6 +41,7 @@ The auth method resource allows you to configure a Boundary auth_method_password
### Optional

- `description` (String) The auth method description.
- `is_primary_for_scope` (Boolean) When true, makes this auth method the primary auth method for the scope in which it resides.
- `min_login_name_length` (Number) The minimum login name length.
- `min_password_length` (Number) The minimum password length.
- `name` (String) The auth method name. Defaults to the resource name.
Expand All @@ -30,3 +50,13 @@ The auth method resource allows you to configure a Boundary auth_method_password
### Read-Only

- `id` (String) The ID of the account.

## Import

Import is supported using the following syntax:

The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example:

```shell
terraform import boundary_auth_method_password.foo <my-id>
```
6 changes: 6 additions & 0 deletions examples/resources/boundary_auth_method/resource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ resource "boundary_auth_method" "password" {
scope_id = boundary_scope.org.id
type = "password"
}

resource "boundary_auth_method" "password_is_primary" {
scope_id = boundary_scope.org.id
type = "password"
is_primary_for_scope = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import boundary_auth_method_password.foo <my-id>
16 changes: 16 additions & 0 deletions examples/resources/boundary_auth_method_password/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first scope!"
scope_id = "global"
auto_create_admin_role = true
auto_create_default_role = true
}

resource "boundary_auth_method_password" "password" {
scope_id = boundary_scope.org.id
}

resource "boundary_auth_method_password" "password_is_primary" {
scope_id = boundary_scope.org.id
is_primary_for_scope = true
}
72 changes: 67 additions & 5 deletions internal/provider/resource_auth_method.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ func resourceAuthMethod() *schema.Resource {
Computed: true,
Deprecated: "Will be removed in favor of using attributes parameter",
},
authmethodIsPrimaryForScopeKey: {
Description: "When true, makes this auth method the primary auth method for the scope in which it resides.",
Type: schema.TypeBool,
Optional: true,
},
},
}
}
Expand All @@ -91,6 +96,10 @@ func setFromAuthMethodResponseMap(d *schema.ResourceData, raw map[string]interfa
return err
}

if p, ok := raw[authmethodIsPrimaryForScopeKey]; ok {
d.Set(authmethodIsPrimaryForScopeKey, p.(bool))
}

switch raw["type"].(string) {
case authmethodTypePassword:
if attrsVal, ok := raw["attributes"]; ok {
Expand Down Expand Up @@ -160,6 +169,19 @@ func resourceAuthMethodCreate(ctx context.Context, d *schema.ResourceData, meta
return diag.Errorf("nil auth method after create")
}

amid := amcr.GetResponse().Map["id"].(string)

// update scope when set to primary
if p, ok := d.GetOk(authmethodIsPrimaryForScopeKey); ok {
if p.(bool) {
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, amid, meta); err != nil {
return diag.Errorf("%v", err)
}

amcr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
}
}

if err := setFromAuthMethodResponseMap(d, amcr.GetResponse().Map); err != nil {
return diag.FromErr(err)
}
Expand All @@ -183,6 +205,15 @@ func resourceAuthMethodRead(ctx context.Context, d *schema.ResourceData, meta in
return diag.Errorf("auth method nil after read")
}

serr, isPrimary := readScopeIsPrimaryAuthMethodId(ctx, amrr.GetResponse().Map["scope_id"].(string), amrr.GetResponse().Map["id"].(string), meta)
if serr != nil {
return diag.Errorf("%v", serr)
}

if isPrimary {
amrr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
}

if err := setFromAuthMethodResponseMap(d, amrr.GetResponse().Map); err != nil {
return diag.FromErr(err)
}
Expand Down Expand Up @@ -225,13 +256,44 @@ func resourceAuthMethodUpdate(ctx context.Context, d *schema.ResourceData, meta
}
}

opts = append(opts, authmethods.WithAutomaticVersioning(true))
amu, err := amClient.Update(ctx, d.Id(), 0, opts...)
if err != nil {
return diag.Errorf("error updating auth method: %v", err)
if d.HasChange(authmethodIsPrimaryForScopeKey) {
amrr, err := amClient.Read(ctx, d.Id())
if err != nil {
return diag.Errorf("error updating auth method: %v", err)
}
if amrr == nil {
return diag.Errorf("error updating auth method: nil resource")
}
scopeId := amrr.GetResponse().Map["scope_id"].(string)
authMethodId := amrr.GetResponse().Map["id"].(string)

isPrimary := d.Get(authmethodIsPrimaryForScopeKey).(bool)

if isPrimary {
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, authMethodId, meta); err != nil {
return diag.Errorf("%v", err)
}
}
}

setFromAuthMethodResponseMap(d, amu.GetResponse().Map)
if len(opts) > 0 {
opts = append(opts, authmethods.WithAutomaticVersioning(true))
amu, err := amClient.Update(ctx, d.Id(), 0, opts...)
if err != nil {
return diag.Errorf("error updating auth method: %v", err)
}

if d.HasChange(authmethodIsPrimaryForScopeKey) {
amu.GetResponse().Map[authmethodIsPrimaryForScopeKey] = d.Get(authmethodIsPrimaryForScopeKey).(bool)
}

setFromAuthMethodResponseMap(d, amu.GetResponse().Map)
}

// If only is_primary_for_scope changed
if d.HasChange(authmethodIsPrimaryForScopeKey) {
return resourceAuthMethodPasswordRead(ctx, d, meta)
}

return nil
}
Expand Down
60 changes: 60 additions & 0 deletions internal/provider/resource_auth_method_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
authmethodTypePassword = "password"
authmethodMinLoginNameLengthKey = "min_login_name_length"
authmethodMinPasswordLengthKey = "min_password_length"
authmethodIsPrimaryForScopeKey = "is_primary_for_scope"
)

func resourceAuthMethodPassword() *schema.Resource {
Expand Down Expand Up @@ -72,6 +73,11 @@ func resourceAuthMethodPassword() *schema.Resource {
Optional: true,
Computed: true,
},
authmethodIsPrimaryForScopeKey: {
Description: "When true, makes this auth method the primary auth method for the scope in which it resides.",
Type: schema.TypeBool,
Optional: true,
},
},
}
}
Expand All @@ -82,6 +88,10 @@ func setFromPasswordAuthMethodResponseMap(d *schema.ResourceData, raw map[string
d.Set(ScopeIdKey, raw[ScopeIdKey])
d.Set(TypeKey, raw[TypeKey])

if p, ok := raw[authmethodIsPrimaryForScopeKey]; ok {
d.Set(authmethodIsPrimaryForScopeKey, p.(bool))
}

if attrsVal, ok := raw["attributes"]; ok {
attrs := attrsVal.(map[string]interface{})

Expand Down Expand Up @@ -158,6 +168,19 @@ func resourceAuthMethodPasswordCreate(ctx context.Context, d *schema.ResourceDat
return diag.Errorf("nil auth method after create")
}

amid := amcr.GetResponse().Map["id"].(string)

// update scope when set to primary
if p, ok := d.GetOk(authmethodIsPrimaryForScopeKey); ok {
if p.(bool) {
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, amid, meta); err != nil {
return diag.Errorf("%v", err)
}

amcr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
}
}

return setFromPasswordAuthMethodResponseMap(d, amcr.GetResponse().Map)
}

Expand All @@ -177,6 +200,15 @@ func resourceAuthMethodPasswordRead(ctx context.Context, d *schema.ResourceData,
return diag.Errorf("auth method nil after read")
}

serr, isPrimary := readScopeIsPrimaryAuthMethodId(ctx, amrr.GetResponse().Map["scope_id"].(string), amrr.GetResponse().Map["id"].(string), meta)
if serr != nil {
return diag.Errorf("%v", serr)
}

if isPrimary {
amrr.GetResponse().Map[authmethodIsPrimaryForScopeKey] = true
}

return setFromPasswordAuthMethodResponseMap(d, amrr.GetResponse().Map)
}

Expand Down Expand Up @@ -218,15 +250,43 @@ func resourceAuthMethodPasswordUpdate(ctx context.Context, d *schema.ResourceDat
}
}

if d.HasChange(authmethodIsPrimaryForScopeKey) {
amrr, err := amClient.Read(ctx, d.Id())
if err != nil {
return diag.Errorf("error updating auth method: %v", err)
}
if amrr == nil {
return diag.Errorf("error updating auth method: nil resource")
}
scopeId := amrr.GetResponse().Map["scope_id"].(string)
authMethodId := amrr.GetResponse().Map["id"].(string)

if d.Get(authmethodIsPrimaryForScopeKey).(bool) {
if err := updateScopeWithPrimaryAuthMethodId(ctx, scopeId, authMethodId, meta); err != nil {
return diag.Errorf("%v", err)
}
}
}

if len(opts) > 0 {
opts = append(opts, authmethods.WithAutomaticVersioning(true))
amur, err := amClient.Update(ctx, d.Id(), 0, opts...)
if err != nil {
return diag.Errorf("error updating auth method: %v", err)
}

if d.HasChange(authmethodIsPrimaryForScopeKey) {
amur.GetResponse().Map[authmethodIsPrimaryForScopeKey] = d.Get(authmethodIsPrimaryForScopeKey).(bool)
}

return setFromPasswordAuthMethodResponseMap(d, amur.GetResponse().Map)
}

// If only is_primary_for_scope changed
if d.HasChange(authmethodIsPrimaryForScopeKey) {
return resourceAuthMethodPasswordRead(ctx, d, meta)
}

return nil
}

Expand Down
49 changes: 49 additions & 0 deletions internal/provider/resource_auth_method_password_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ resource "boundary_auth_method_password" "foo" {
scope_id = boundary_scope.org1.id
depends_on = [boundary_role.org1_admin]
}`, fooAuthMethodDescUpdate)

fooAuthMethodIsPrimaryUpdate = fmt.Sprintf(`
resource "boundary_auth_method_password" "foo" {
name = "test"
description = "%s"
type = "password"
scope_id = boundary_scope.org1.id
is_primary_for_scope = true
depends_on = [boundary_role.org1_admin]
}`, fooAuthMethodDesc)
)

func TestAccAuthMethodPassword(t *testing.T) {
Expand All @@ -55,6 +65,7 @@ func TestAccAuthMethodPassword(t *testing.T) {
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
),
},
importStep("boundary_auth_method_password.foo"),
Expand All @@ -66,9 +77,47 @@ func TestAccAuthMethodPassword(t *testing.T) {
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
),
},
importStep("boundary_auth_method_password.foo"),
},
})
}

func TestAccAuthMethodPasswordIsPrimary(t *testing.T) {
tc := controller.NewTestController(t, tcConfig...)
defer tc.Shutdown()
url := tc.ApiAddrs()[0]

var provider *schema.Provider
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories(&provider),
CheckDestroy: testAccCheckAuthMethodResourceDestroy(t, provider, passwordAuthMethodType),
Steps: []resource.TestStep{
{
// create
Config: testConfig(url, fooOrg, fooAuthMethod),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "description", fooAuthMethodDesc),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", false),
),
},
importStep("boundary_auth_method_password.foo"),
{
// update
Config: testConfig(url, fooOrg, fooAuthMethodIsPrimaryUpdate),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "description", fooAuthMethodDesc),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "name", "test"),
resource.TestCheckResourceAttr("boundary_auth_method_password.foo", "type", "password"),
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method_password.foo"),
testAccIsPrimaryForScope(provider, "boundary_auth_method_password.foo", true),
),
},
},
})
}
Loading
Loading