Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #111 from Scalr/feature/SCALRSCORE-20549
SCALRCORE-20549 > IP Fencing (IP whitelisting) - Provider
- Loading branch information
Showing
7 changed files
with
297 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
--- | ||
layout: "scalr" | ||
page_title: "Scalr: scalr_account_allowed_ips" | ||
sidebar_current: "docs-resource-scalr-account-allowed-ips" | ||
description: |- | ||
Manages allowed ips for account. | ||
--- | ||
|
||
# scalr_account_allowed_ips Resource | ||
|
||
Manage the state of allowed ips for an account in Scalr. Create, update and destroy. | ||
|
||
## Example Usage | ||
|
||
Basic usage: | ||
|
||
```hcl | ||
resource "scalr_account_allowed_ips" "default" { | ||
account_id = "acc-xxxxxxxx" | ||
allowed_ips = ["127.0.0.1", "192.168.0.0/24"] | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
* `account_id` - (Required) ID of the account. | ||
* `allowed_ips` - (Required) The list of allowed IPs or CIDRs. | ||
|
||
## Attribute Reference | ||
|
||
All arguments plus: | ||
|
||
* `id` - The ID of the account. | ||
|
||
## Import | ||
|
||
To import allowed ips for an account use account ID as the import ID. For example: | ||
```shell | ||
terraform import scalr_account_allowed_ips.default acc-xxxxxxxxx | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package scalr | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
scalr "github.com/scalr/go-scalr" | ||
) | ||
|
||
func resourceScalrAccountAllowedIps() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceScalrAccountAllowedIpsCreate, | ||
Read: resourceScalrAccountAllowedIpsRead, | ||
Update: resourceScalrAccountAllowedIpsUpdate, | ||
Delete: resourceScalrAccountAllowedIpsDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"account_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
|
||
"allowed_ips": { | ||
Type: schema.TypeList, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
MinItems: 1, | ||
Required: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func preprocessAllowedIps(allowedIps []interface{}) []string { | ||
ips := make([]string, 0) | ||
for _, v := range allowedIps { | ||
ips = append(ips, v.(string)) | ||
} | ||
|
||
return ips | ||
} | ||
|
||
func resourceScalrAccountAllowedIpsCreate(d *schema.ResourceData, meta interface{}) error { | ||
scalrClient := meta.(*scalr.Client) | ||
|
||
// Get attributes. | ||
accountId := d.Get("account_id").(string) | ||
|
||
allowedIps := preprocessAllowedIps(d.Get("allowed_ips").([]interface{})) | ||
// Create a new options struct. | ||
options := scalr.AccountUpdateOptions{ | ||
ID: accountId, | ||
AllowedIPs: &allowedIps, | ||
} | ||
|
||
log.Printf("[DEBUG] Update allowed ips: %s", accountId) | ||
account, err := scalrClient.Accounts.Update(ctx, accountId, options) | ||
if err != nil { | ||
return fmt.Errorf("Error updating allowed ips for account %s: %v", accountId, err) | ||
} | ||
|
||
d.SetId(account.ID) | ||
|
||
return resourceScalrAccountAllowedIpsRead(d, meta) | ||
} | ||
|
||
func resourceScalrAccountAllowedIpsRead(d *schema.ResourceData, meta interface{}) error { | ||
scalrClient := meta.(*scalr.Client) | ||
|
||
// Get the ID | ||
accountID := d.Id() | ||
|
||
log.Printf("[DEBUG] Read endpoint with ID: %s", accountID) | ||
account, err := scalrClient.Accounts.Read(ctx, accountID) | ||
if err != nil { | ||
if errors.Is(err, scalr.ErrResourceNotFound) { | ||
return fmt.Errorf("Could not find account %s: %v", accountID, err) | ||
} | ||
return fmt.Errorf("Error retrieving account: %v", err) | ||
} | ||
|
||
for i, ip := range account.AllowedIPs { | ||
account.AllowedIPs[i] = strings.TrimSuffix(ip, "/32") | ||
} | ||
|
||
// Update the config. | ||
d.Set("allowed_ips", account.AllowedIPs) | ||
d.Set("account_id", accountID) | ||
|
||
return nil | ||
} | ||
|
||
func resourceScalrAccountAllowedIpsUpdate(d *schema.ResourceData, meta interface{}) error { | ||
scalrClient := meta.(*scalr.Client) | ||
|
||
// Get attributes. | ||
allowedIps := preprocessAllowedIps(d.Get("allowed_ips").([]interface{})) | ||
|
||
// Create a new options struct. | ||
options := scalr.AccountUpdateOptions{ | ||
ID: d.Id(), | ||
AllowedIPs: &allowedIps, | ||
} | ||
|
||
log.Printf("[DEBUG] Update allowed ips for account: %s", d.Id()) | ||
_, err := scalrClient.Accounts.Update(ctx, d.Id(), options) | ||
if err != nil { | ||
return fmt.Errorf("Error updating allowed ips for %s: %v", d.Id(), err) | ||
} | ||
|
||
return resourceScalrAccountAllowedIpsRead(d, meta) | ||
} | ||
|
||
func resourceScalrAccountAllowedIpsDelete(d *schema.ResourceData, meta interface{}) error { | ||
scalrClient := meta.(*scalr.Client) | ||
|
||
log.Printf("[DEBUG] Delete allowed ips for account: %s", d.Id()) | ||
|
||
// Create a new options struct. | ||
options := scalr.AccountUpdateOptions{ | ||
ID: d.Id(), | ||
AllowedIPs: &[]string{}, | ||
} | ||
_, err := scalrClient.Accounts.Update(ctx, d.Id(), options) | ||
if err != nil { | ||
if errors.Is(err, scalr.ErrResourceNotFound) { | ||
return nil | ||
} | ||
return fmt.Errorf("Error deleting allowed ips for account %s: %v", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package scalr | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
) | ||
|
||
func TestAccScalrAccountAllowedIps_basic(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{"192.168.0.12", "0.0.0.0/0"}), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("scalr_account_allowed_ips.test", "id"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.#", "2"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.0", "192.168.0.12"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.1", "0.0.0.0/0"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccScalrAccountAllowedIps_update(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{"192.168.0.12", "0.0.0.0/0"}), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("scalr_account_allowed_ips.test", "id"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.#", "2"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.0", "192.168.0.12"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.1", "0.0.0.0/0"), | ||
), | ||
}, | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{"0.0.0.0/0"}), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttrSet("scalr_account_allowed_ips.test", "id"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.#", "1"), | ||
resource.TestCheckResourceAttr("scalr_account_allowed_ips.test", "allowed_ips.0", "0.0.0.0/0"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccScalrAccountAllowedIps_import(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{"192.168.0.12", "0.0.0.0/0"}), | ||
}, | ||
|
||
{ | ||
ResourceName: "scalr_account_allowed_ips.test", | ||
ImportState: true, | ||
ImportStateVerify: true, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccScalrAccountAllowedIps_empty(t *testing.T) { | ||
rg, _ := regexp.Compile(`config is invalid: allowed_ips: attribute supports 1 item as a minimum, config has 0 declared`) | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{}), | ||
ExpectError: rg, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccScalrAccountAllowedIps_invalid_CIDR(t *testing.T) { | ||
rg, _ := regexp.Compile(`value is not a valid IPv4 network`) | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccScalrAccountAllowedIps([]string{"192.168.0.12/24"}), | ||
ExpectError: rg, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccScalrAccountAllowedIps(allowedIps []string) string { | ||
ips, _ := json.Marshal(allowedIps) | ||
return fmt.Sprintf(` | ||
resource "scalr_account_allowed_ips" "test" { | ||
account_id = "%s" | ||
allowed_ips = %s | ||
}`, defaultAccount, ips) | ||
} |