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

Add Account lockout arguments to vcd_org resource and data source #1304

Merged
merged 14 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from 10 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
2 changes: 2 additions & 0 deletions .changes/v3.14.0/1304-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Add `account_lockout` block to `vcd_org` resource and data source, that specifies the account locking mechanism with the
sub-arguments `enabled`, `invalid_logins_before_lockout` and `lockout_interval_minutes` [GH-1304]
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@ require (
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.34.0 // indirect
)

replace github.com/vmware/go-vcloud-director/v2 => github.com/adambarreiro/go-vcloud-director/v2 v2.17.0-alpha.1.0.20240809100409-de99a975faa9
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/adambarreiro/go-vcloud-director/v2 v2.17.0-alpha.1.0.20240809100409-de99a975faa9 h1:UbgPdVhtUQcsYmziFRncAI8L5YQ1sy1DVVpcGVBs7OU=
github.com/adambarreiro/go-vcloud-director/v2 v2.17.0-alpha.1.0.20240809100409-de99a975faa9/go.mod h1:7Of1qJja+LLNKVegjZG7uuhhy6xgGg3q7Fkw2CEP+Tw=
github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
Expand Down Expand Up @@ -150,8 +152,6 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/vmware/go-vcloud-director/v2 v2.26.0-alpha.3 h1:0s1ygVB38eWYX+sHLR/hO4bsV/C506fbx72sFsZoIwo=
github.com/vmware/go-vcloud-director/v2 v2.26.0-alpha.3/go.mod h1:7Of1qJja+LLNKVegjZG7uuhhy6xgGg3q7Fkw2CEP+Tw=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
24 changes: 24 additions & 0 deletions vcd/datasource_vcd_org.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,30 @@ func datasourceVcdOrg() *schema.Resource {
Deprecated: "Use metadata_entry instead",
},
"metadata_entry": metadataEntryDatasourceSchema("Organization"),
"account_lockout": {
Type: schema.TypeList,
Computed: true,
Description: "The account lockout properties set in this organization",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Computed: true,
Description: "Whether account lockout is enabled or not",
},
"invalid_logins_before_lockout": {
Type: schema.TypeInt,
Computed: true,
Description: "Number of login attempts that will trigger an account lockout for the given user",
},
"lockout_interval_minutes": {
Type: schema.TypeInt,
Computed: true,
Description: "Once a user is locked out, they will not be able to log back in for this time period",
},
},
},
},
},
}
}
Expand Down
53 changes: 53 additions & 0 deletions vcd/resource_vcd_org.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,34 @@ func resourceOrg() *schema.Resource {
ConflictsWith: []string{"metadata_entry"},
},
"metadata_entry": metadataEntryResourceSchemaDeprecated("Organization"),
"account_lockout": {
Type: schema.TypeList,
Optional: true,
Computed: true, // Exists even if it is not set
MaxItems: 1,
Description: "Defines account lockout properties in this organization",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
Description: "Whether account lockout is enabled or not",
},
"invalid_logins_before_lockout": {
Type: schema.TypeInt,
Required: true,
Description: "Number of login attempts that will trigger an account lockout for the given user",
ValidateDiagFunc: validation.ToDiagFunc(validation.IntBetween(1, 20)),
},
"lockout_interval_minutes": {
Type: schema.TypeInt,
Required: true,
Description: "Once a user is locked out, they will not be able to log back in for this time period",
ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(1)),
},
},
},
},
},
}
}
Expand Down Expand Up @@ -329,6 +357,18 @@ func getSettings(d *schema.ResourceData) *types.OrgSettings {
settings.OrgVAppTemplateSettings = vappTemplateLeaseSettings
}

accountLockoutBlock, ok := d.GetOk("account_lockout")
if ok {
vappTemplateLeaseInputProvided = true
accountLockout := accountLockoutBlock.([]interface{})[0].(map[string]interface{})
settings.OrgPasswordPolicySettings = &types.OrgPasswordPolicySettings{
Xmlns: types.XMLNamespaceVCloud,
AccountLockoutEnabled: accountLockout["enabled"].(bool),
InvalidLoginsBeforeLockout: accountLockout["invalid_logins_before_lockout"].(int),
AccountLockoutIntervalMinutes: accountLockout["lockout_interval_minutes"].(int),
}
}

return settings
}

Expand Down Expand Up @@ -407,6 +447,7 @@ func resourceOrgUpdate(ctx context.Context, d *schema.ResourceData, m interface{
adminOrg.AdminOrg.OrgSettings.OrgGeneralSettings = settings.OrgGeneralSettings
adminOrg.AdminOrg.OrgSettings.OrgVAppTemplateSettings = settings.OrgVAppTemplateSettings
adminOrg.AdminOrg.OrgSettings.OrgVAppLeaseSettings = settings.OrgVAppLeaseSettings
adminOrg.AdminOrg.OrgSettings.OrgPasswordPolicySettings = settings.OrgPasswordPolicySettings

log.Printf("[TRACE] Org with id %s found", orgName)
// Check if the LDAP settings are correct.
Expand Down Expand Up @@ -545,6 +586,18 @@ func setOrgData(d *schema.ResourceData, vcdClient *VCDClient, adminOrg *govcd.Ad
}
}

passwordPolicySettings := adminOrg.AdminOrg.OrgSettings.OrgPasswordPolicySettings
if passwordPolicySettings != nil {
var accountLockout = make(map[string]interface{})
accountLockout["enabled"] = passwordPolicySettings.AccountLockoutEnabled
accountLockout["invalid_logins_before_lockout"] = passwordPolicySettings.InvalidLoginsBeforeLockout
accountLockout["lockout_interval_minutes"] = passwordPolicySettings.AccountLockoutIntervalMinutes
err = d.Set("account_lockout", []map[string]interface{}{accountLockout})
if err != nil {
return diag.FromErr(err)
}
}

diags = append(diags, updateMetadataInStateDeprecated(d, vcdClient, "vcd_org", adminOrg)...)
if diags != nil && diags.HasError() {
log.Printf("[DEBUG] Unable to set Org metadata")
Expand Down
46 changes: 44 additions & 2 deletions vcd/resource_vcd_org_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func TestAccVcdOrgFull(t *testing.T) {
templDeleteOnLeaseExp bool
metadataKey string
metadataValue string
accountLockout bool
}
var orgList = []testOrgData{
{
Expand Down Expand Up @@ -172,6 +173,24 @@ func TestAccVcdOrgFull(t *testing.T) {
metadataKey: "key5",
metadataValue: "value5",
},
{
name: "org6",
enabled: true,
canPublishCatalogs: true,
canPublishExternalCatalogs: false,
canSubscribeExternalCatalogs: true,
deployedVmQuota: 200,
storedVmQuota: 200,
runtimeLease: 3600 * 24 * 7, // 7 days (the default)
powerOffonLeaseExp: false,
vappStorageLease: 3600 * 24 * 14, // 14 days (the default)
templDeleteOnLeaseExp: false,
templStorageLease: 3600 * 24 * 30, // 30 days (the default)
vappDeleteOnLeaseExp: false,
metadataKey: "key6",
metadataValue: "value6",
accountLockout: true,
},
}
willSkip := false

Expand All @@ -197,13 +216,30 @@ func TestAccVcdOrgFull(t *testing.T) {
"MetadataKey": od.metadataKey,
"MetadataValue": od.metadataValue,
"SkipDirective": " ", // one whitespace to avoid skipping test in `testParamsNotEmpty()`
"AccountLockout": " ",
}
testParamsNotEmpty(t, params)

if createEnabledOrg && !params["IsEnabled"].(bool) {
params["SkipDirective"] = "# skip-binary-test: VCD 10.4.2 cannot create disabled Orgs"
}

if od.accountLockout {
params["AccountLockout"] = "account_lockout {\n enabled = true\n invalid_logins_before_lockout = 7\n lockout_interval_minutes = 77\n}"
}
accountLockoutCheck := func(resourceName string, attempts, interval int) resource.TestCheckFunc {
if !od.accountLockout {
return func(state *terraform.State) error {
return nil
}
}
return resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "account_lockout.0.enabled", "true"),
resource.TestCheckResourceAttr(resourceName, "account_lockout.0.invalid_logins_before_lockout", fmt.Sprintf("%d", attempts)),
resource.TestCheckResourceAttr(resourceName, "account_lockout.0.lockout_interval_minutes", fmt.Sprintf("%d", interval)),
)
}

configText := templateFill(testAccCheckVcdOrgFull, params)
// Prepare update
var updateParams = make(StringMap)
Expand All @@ -226,16 +262,19 @@ func TestAccVcdOrgFull(t *testing.T) {
if createEnabledOrg && !updateParams["IsEnabled"].(bool) {
updateParams["SkipDirective"] = "# skip-binary-test: VCD 10.4.2 cannot create disabled Orgs"
}
if od.accountLockout {
updateParams["AccountLockout"] = "account_lockout {\n enabled = true\n invalid_logins_before_lockout = 19\n lockout_interval_minutes = 55\n}"
}

configTextUpdated := templateFill(testAccCheckVcdOrgFull, updateParams)
if vcdShortTest {
willSkip = true
continue
}
fmt.Printf("org: %-5s - enabled %-5v - catalogs %-5v - externalCatalogs %-5v - subscribeExternalCatalogs %-5v - quotas [%3d %3d] - vapp {%10d %5v %10d %5v} - tmpl {%10d %5v}\n",
fmt.Printf("org: %-5s - enabled %-5v - catalogs %-5v - externalCatalogs %-5v - subscribeExternalCatalogs %-5v - quotas [%3d %3d] - vapp {%10d %5v %10d %5v} - tmpl {%10d %5v} - accountLockout %-5v\n",
od.name, od.enabled, od.canPublishCatalogs, od.canPublishExternalCatalogs, od.canSubscribeExternalCatalogs,
od.deployedVmQuota, od.storedVmQuota, od.runtimeLease, od.powerOffonLeaseExp, od.vappStorageLease,
od.vappDeleteOnLeaseExp, od.templStorageLease, od.templDeleteOnLeaseExp)
od.vappDeleteOnLeaseExp, od.templStorageLease, od.templDeleteOnLeaseExp, od.accountLockout)
debugPrintf("#[DEBUG] CONFIGURATION: %s", configText)
debugPrintf("#[DEBUG] CONFIGURATION: %s", configTextUpdated)

Expand Down Expand Up @@ -280,6 +319,7 @@ func TestAccVcdOrgFull(t *testing.T) {
resourceName, "vapp_template_lease.0.delete_on_storage_lease_expiration", fmt.Sprintf("%v", od.templDeleteOnLeaseExp)),
resource.TestCheckResourceAttr(
resourceName, "metadata."+od.metadataKey, od.metadataValue),
accountLockoutCheck(resourceName, 7, 77),
),
},
{
Expand Down Expand Up @@ -307,6 +347,7 @@ func TestAccVcdOrgFull(t *testing.T) {
resourceName, fmt.Sprintf("metadata.%s", od.metadataKey)),
resource.TestCheckResourceAttr(
resourceName, "metadata."+updateParams["MetadataKey"].(string), updateParams["MetadataValue"].(string)),
accountLockoutCheck(resourceName, 19, 55),
),
},
{
Expand Down Expand Up @@ -394,6 +435,7 @@ resource "vcd_org" "{{.OrgName}}" {
metadata = {
{{.MetadataKey}} = "{{.MetadataValue}}"
}
{{.AccountLockout}}
}
`

Expand Down
4 changes: 4 additions & 0 deletions website/docs/d/org.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ The following arguments are supported:
* `list_of_catalogs` - (*v3.11+*) List of catalogs (sorted alphabetically), owned or shared, available to this organization.
* `number_of_vdcs` - (*v3.11+*) Number of VDCs owned or shared, available to this organization.
* `list_of_vdcs` - (*v3.11+*) List of VDCs (sorted alphabetically), owned or shared, available to this organization.
* `account_lockout` - (*v3.14+*) Contains the account lockout properties of the read organization:
* `enabled` - (*v3.14+*) Whether account lockout is enabled or not
* `invalid_logins_before_lockout` - (*v3.14+*) Number of login attempts that will trigger an account lockout for the given user
* `lockout_interval_minutes` - (*v3.14+*) Once a user is locked out, they will not be able to log back in for this time period
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved

<a id="vapp-lease"></a>
## vApp Lease
Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/org.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ resource "vcd_org" "my-org" {
maximum_storage_lease_in_sec = 604800 # 1 week
delete_on_storage_lease_expiration = true
}
account_lockout {
enabled = true
invalid_logins_before_lockout = 10
lockout_interval_minutes = 60
}
}
```

Expand All @@ -64,6 +69,10 @@ The following arguments are supported:
* `metadata_entry` - (Optional; *v3.8+*) A set of metadata entries to assign. See [Metadata](#metadata) section for details.
* `vapp_lease` - (Optional; *v2.7+*) Defines lease parameters for vApps created in this organization. See [vApp Lease](#vapp-lease) below for details.
* `vapp_template_lease` - (Optional; *v2.7+*) Defines lease parameters for vApp templates created in this organization. See [vApp Template Lease](#vapp-template-lease) below for details.
* `account_lockout` - (*v3.14+*) Defines account lockout properties in this organization:
* `enabled` - (*v3.14+*) Whether account lockout is enabled or not
* `invalid_logins_before_lockout` - (*v3.14+*) Number of login attempts that will trigger an account lockout for the given user
* `lockout_interval_minutes` - (*v3.14+*) Once a user is locked out, they will not be able to log back in for this time period
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved

## Attribute Reference

Expand Down
Loading