feat: Add is_primary_for_scope attribute to boundary_auth_method and boundary_auth_method_password resources (#753)
This commit is contained in:
1 parent
3e539fec8a
commit
8c933816a5
9 files changed
+283
-5
No files matched your search
@@ -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 -->
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
```
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_auth_method_password.foo <my-id>
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -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{})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -218,6 +250,24 @@ 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...)
|
||||
@@ -225,8 +275,18 @@ func resourceAuthMethodPasswordUpdate(ctx context.Context, d *schema.ResourceDat
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
@@ -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"),
|
||||
@@ -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),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -42,6 +42,16 @@ resource "boundary_auth_method" "foo" {
|
||||
scope_id = boundary_scope.org1.id
|
||||
depends_on = [boundary_role.org1_admin]
|
||||
}`, fooBaseAuthMethodDescUpdate)
|
||||
|
||||
fooBaseAuthMethodIsPrimaryUpdate = fmt.Sprintf(`
|
||||
resource "boundary_auth_method" "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 TestAccBaseAuthMethodPassword(t *testing.T) {
|
||||
@@ -81,6 +91,43 @@ func TestAccBaseAuthMethodPassword(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccBaseAuthMethodPasswordIsPrimary(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, fooBaseAuthMethod),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "description", fooBaseAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method.foo", false),
|
||||
),
|
||||
},
|
||||
importStep("boundary_auth_method.foo"),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, fooBaseAuthMethodIsPrimaryUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "description", fooBaseAuthMethodDesc),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "name", "test"),
|
||||
resource.TestCheckResourceAttr("boundary_auth_method.foo", "type", "password"),
|
||||
testAccCheckAuthMethodResourceExists(provider, "boundary_auth_method.foo"),
|
||||
testAccIsPrimaryForScope(provider, "boundary_auth_method.foo", true),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAuthMethodResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
|
||||
Reference in new issue
Block a user