Skip to content

Commit 4d52e1d

Browse files
authored
INBOX-2403 - Add support for global IP whitelist
2 parents 7256ceb + f88c305 commit 4d52e1d

8 files changed

Lines changed: 357 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.0.6 (September 18, 2023)
2+
ENHANCEMENTS
3+
* Added support for global IP whitelist
4+
15
## 2.0.5 (July 27, 2023)
26
* Version Bump Golang SDK v2.7.7 => v2.7.8 to fix monitor creation
37

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ require (
77
github.com/hashicorp/go-retryablehttp v0.7.2
88
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.1
99
github.com/stretchr/testify v1.8.1
10-
gopkg.in/ns1/ns1-go.v2 v2.7.8
10+
gopkg.in/ns1/ns1-go.v2 v2.7.9
1111
)
1212

1313
require (

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJE
1717
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
1818
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
1919
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
20+
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
2021
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
2122
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2223
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2324
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2425
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
2526
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
27+
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
2628
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
2729
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
2830
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
@@ -38,6 +40,7 @@ github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6
3840
github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4=
3941
github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc=
4042
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
43+
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
4144
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4245
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
4346
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -252,6 +255,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
252255
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
253256
gopkg.in/ns1/ns1-go.v2 v2.7.8 h1:1ocy22Xb+KF4g6JNlPFoivyYRdJfeQjs+omb/wIzQAU=
254257
gopkg.in/ns1/ns1-go.v2 v2.7.8/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
258+
gopkg.in/ns1/ns1-go.v2 v2.7.9 h1:enj8dKPIoElOIv8cSzRHd5sTHsLgHapvOIKK8uLXK7c=
259+
gopkg.in/ns1/ns1-go.v2 v2.7.9/go.mod h1:pfaU0vECVP7DIOr453z03HXS6dFJpXdNRwOyRzwmPSc=
255260
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
256261
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
257262
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

ns1/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
)
2020

2121
var (
22-
clientVersion = "2.0.5"
22+
clientVersion = "2.0.6"
2323
providerUserAgent = "tf-ns1" + "/" + clientVersion
2424
defaultRetryMax = 3
2525
)

ns1/provider.go

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,21 @@ func Provider() *schema.Provider {
6262
"ns1_networks": dataSourceNetworks(),
6363
},
6464
ResourcesMap: map[string]*schema.Resource{
65-
"ns1_zone": resourceZone(),
66-
"ns1_record": recordResource(),
67-
"ns1_datasource": dataSourceResource(),
68-
"ns1_datafeed": dataFeedResource(),
69-
"ns1_monitoringjob": monitoringJobResource(),
70-
"ns1_notifylist": notifyListResource(),
71-
"ns1_user": userResource(),
72-
"ns1_apikey": apikeyResource(),
73-
"ns1_team": teamResource(),
74-
"ns1_application": resourceApplication(),
75-
"ns1_pulsarjob": pulsarJobResource(),
76-
"ns1_tsigkey": tsigKeyResource(),
77-
"ns1_subnet": resourceSubnet(),
78-
"ns1_dnsview": dnsView(),
65+
"ns1_zone": resourceZone(),
66+
"ns1_record": recordResource(),
67+
"ns1_datasource": dataSourceResource(),
68+
"ns1_datafeed": dataFeedResource(),
69+
"ns1_monitoringjob": monitoringJobResource(),
70+
"ns1_notifylist": notifyListResource(),
71+
"ns1_user": userResource(),
72+
"ns1_apikey": apikeyResource(),
73+
"ns1_team": teamResource(),
74+
"ns1_application": resourceApplication(),
75+
"ns1_pulsarjob": pulsarJobResource(),
76+
"ns1_tsigkey": tsigKeyResource(),
77+
"ns1_subnet": resourceSubnet(),
78+
"ns1_dnsview": dnsView(),
79+
"ns1_account_whitelist": accountWhitelistResource(),
7980
},
8081
ConfigureFunc: ns1Configure,
8182
}

ns1/resource_account_whitelist.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package ns1
2+
3+
import (
4+
"log"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
8+
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
9+
"gopkg.in/ns1/ns1-go.v2/rest/model/account"
10+
)
11+
12+
func accountWhitelistResource() *schema.Resource {
13+
s := map[string]*schema.Schema{
14+
"name": {
15+
Type: schema.TypeString,
16+
Required: true,
17+
},
18+
"values": {
19+
Type: schema.TypeList,
20+
Elem: &schema.Schema{Type: schema.TypeString},
21+
Required: true,
22+
},
23+
}
24+
25+
return &schema.Resource{
26+
Schema: s,
27+
Create: accountWhitelistCreate,
28+
Read: accountWhitelistRead,
29+
Update: accountWhitelistUpdate,
30+
Delete: accountWhitelistDelete,
31+
Importer: &schema.ResourceImporter{},
32+
SchemaVersion: 1,
33+
}
34+
}
35+
36+
func accountWhitelistToResourceData(d *schema.ResourceData, wl *account.IPWhitelist) error {
37+
d.SetId(wl.ID)
38+
d.Set("name", wl.Name)
39+
d.Set("values", wl.Values)
40+
return nil
41+
}
42+
43+
func resourceDataToWhitelist(wl *account.IPWhitelist, d *schema.ResourceData) error {
44+
wl.ID = d.Id()
45+
wl.Name = d.Get("name").(string)
46+
47+
if v, ok := d.GetOk("values"); ok {
48+
ipWhitelistRaw := v.([]interface{})
49+
wl.Values = make([]string, len(ipWhitelistRaw))
50+
for i, ip := range ipWhitelistRaw {
51+
wl.Values[i] = ip.(string)
52+
}
53+
}
54+
55+
return nil
56+
}
57+
58+
func accountWhitelistCreate(d *schema.ResourceData, meta interface{}) error {
59+
client := meta.(*ns1.Client)
60+
wl := account.IPWhitelist{}
61+
if err := resourceDataToWhitelist(&wl, d); err != nil {
62+
return err
63+
}
64+
if resp, err := client.GlobalIPWhitelist.Create(&wl); err != nil {
65+
return ConvertToNs1Error(resp, err)
66+
}
67+
68+
return accountWhitelistToResourceData(d, &wl)
69+
}
70+
71+
func accountWhitelistRead(d *schema.ResourceData, meta interface{}) error {
72+
client := meta.(*ns1.Client)
73+
wl, resp, err := client.GlobalIPWhitelist.Get(d.Id())
74+
if err != nil {
75+
if err == ns1.ErrIPWhitelistMissing {
76+
log.Printf("[DEBUG] NS1 global whitelist (%s) not found", d.Id())
77+
d.SetId("")
78+
return nil
79+
}
80+
return ConvertToNs1Error(resp, err)
81+
}
82+
83+
return accountWhitelistToResourceData(d, wl)
84+
}
85+
86+
func accountWhitelistUpdate(d *schema.ResourceData, meta interface{}) error {
87+
client := meta.(*ns1.Client)
88+
wl := account.IPWhitelist{
89+
ID: d.Id(),
90+
}
91+
92+
if err := resourceDataToWhitelist(&wl, d); err != nil {
93+
return err
94+
}
95+
96+
if resp, err := client.GlobalIPWhitelist.Update(&wl); err != nil {
97+
return ConvertToNs1Error(resp, err)
98+
}
99+
100+
return accountWhitelistToResourceData(d, &wl)
101+
}
102+
103+
func accountWhitelistDelete(d *schema.ResourceData, meta interface{}) error {
104+
client := meta.(*ns1.Client)
105+
resp, err := client.GlobalIPWhitelist.Delete(d.Id())
106+
d.SetId("")
107+
return ConvertToNs1Error(resp, err)
108+
}
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package ns1
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
10+
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
11+
"gopkg.in/ns1/ns1-go.v2/rest/model/account"
12+
)
13+
14+
func TestAccAccountWhitelist_basic(t *testing.T) {
15+
var wl account.IPWhitelist
16+
var name = fmt.Sprintf("it-%s", acctest.RandStringFromCharSet(15, acctest.CharSetAlphaNum))
17+
18+
resource.Test(t, resource.TestCase{
19+
PreCheck: func() { testAccPreCheck(t) },
20+
Providers: testAccProviders,
21+
CheckDestroy: testAccAccountWhitelistDestroy,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccAccountWhitelistBasic(name),
25+
Check: resource.ComposeTestCheckFunc(
26+
testAccCheckAccountWhitelistExists(fmt.Sprintf("ns1_account_whitelist.%s", name), &wl),
27+
),
28+
},
29+
},
30+
})
31+
}
32+
33+
func TestAccAccountWhitelist_ManualDelete(t *testing.T) {
34+
var wl account.IPWhitelist
35+
var name = fmt.Sprintf("it-%s", acctest.RandStringFromCharSet(15, acctest.CharSetAlphaNum))
36+
37+
resource.Test(t, resource.TestCase{
38+
PreCheck: func() { testAccPreCheck(t) },
39+
Providers: testAccProviders,
40+
CheckDestroy: testAccAccountWhitelistDestroy,
41+
Steps: []resource.TestStep{
42+
{
43+
Config: testAccAccountWhitelistBasic(name),
44+
Check: testAccCheckAccountWhitelistExists(fmt.Sprintf("ns1_account_whitelist.%s", name), &wl),
45+
},
46+
// Simulate a manual deletion of the whitelist and verify that the plan has a diff.
47+
{
48+
PreConfig: testAccManualDeleteAccountWhitelist(t, &wl),
49+
Config: testAccAccountWhitelistBasic(name),
50+
PlanOnly: true,
51+
ExpectNonEmptyPlan: true,
52+
},
53+
// Then re-create and make sure it is there again.
54+
{
55+
Config: testAccAccountWhitelistBasic(name),
56+
Check: testAccCheckAccountWhitelistExists(fmt.Sprintf("ns1_account_whitelist.%s", name), &wl),
57+
},
58+
},
59+
})
60+
}
61+
62+
func TestAccAccountWhitelist_updated(t *testing.T) {
63+
var wl account.IPWhitelist
64+
var name = fmt.Sprintf("it-%s", acctest.RandStringFromCharSet(15, acctest.CharSetAlphaNum))
65+
66+
resource.Test(t, resource.TestCase{
67+
PreCheck: func() { testAccPreCheck(t) },
68+
Providers: testAccProviders,
69+
CheckDestroy: testAccAccountWhitelistDestroy,
70+
Steps: []resource.TestStep{
71+
{
72+
Config: testAccAccountWhitelistBasic(name),
73+
Check: resource.ComposeTestCheckFunc(
74+
testAccCheckAccountWhitelistExists(fmt.Sprintf("ns1_account_whitelist.%s", name), &wl),
75+
testAccCheckAccountWhitelistValues(&wl, 5),
76+
),
77+
},
78+
{
79+
Config: testAccAccountWhitelistUpdated(name),
80+
Check: resource.ComposeTestCheckFunc(
81+
testAccCheckAccountWhitelistExists(fmt.Sprintf("ns1_account_whitelist.%s", name), &wl),
82+
testAccCheckAccountWhitelistValues(&wl, 1),
83+
),
84+
},
85+
},
86+
})
87+
}
88+
89+
// Other stuff passed here
90+
91+
func testAccCheckAccountWhitelistExists(n string, accountWhitelist *account.IPWhitelist) resource.TestCheckFunc {
92+
return func(s *terraform.State) error {
93+
rs, ok := s.RootModule().Resources[n]
94+
95+
if !ok {
96+
return fmt.Errorf("not found: %s", n)
97+
}
98+
99+
if rs.Primary.ID == "" {
100+
return fmt.Errorf("no ID is set")
101+
}
102+
103+
client := testAccProvider.Meta().(*ns1.Client)
104+
105+
foundAccountwhitelist, _, err := client.GlobalIPWhitelist.Get(rs.Primary.Attributes["id"])
106+
107+
p := rs.Primary
108+
109+
if err != nil {
110+
return err
111+
}
112+
113+
if foundAccountwhitelist.ID != p.Attributes["id"] {
114+
return fmt.Errorf("Global allow list not found")
115+
}
116+
117+
*accountWhitelist = *foundAccountwhitelist
118+
119+
return nil
120+
}
121+
}
122+
123+
func testAccManualDeleteAccountWhitelist(t *testing.T, wl *account.IPWhitelist) func() {
124+
return func() {
125+
client := testAccProvider.Meta().(*ns1.Client)
126+
_, err := client.GlobalIPWhitelist.Delete(wl.ID)
127+
128+
// Not a big deal if this fails, it will get caught in the test conditions and fail the test.
129+
if err != nil {
130+
t.Logf("failed to delete global white list: %v", err)
131+
}
132+
}
133+
}
134+
135+
func testAccAccountWhitelistDestroy(s *terraform.State) error {
136+
client := testAccProvider.Meta().(*ns1.Client)
137+
138+
for _, rs := range s.RootModule().Resources {
139+
if rs.Type != "ns1_account_whitelist" {
140+
continue
141+
}
142+
143+
wl, _, err := client.GlobalIPWhitelist.Get(rs.Primary.Attributes["id"])
144+
if err == nil {
145+
return fmt.Errorf("global ip allow list still exists %#v: %#v", err, wl)
146+
}
147+
}
148+
149+
return nil
150+
}
151+
152+
func testAccCheckAccountWhitelistValues(wl *account.IPWhitelist, expected int) resource.TestCheckFunc {
153+
return func(s *terraform.State) error {
154+
values := len(wl.Values)
155+
156+
if values != expected {
157+
return fmt.Errorf("IPWhitelist.Values: got: %v want: %v", values, expected)
158+
}
159+
160+
return nil
161+
}
162+
}
163+
164+
func testAccAccountWhitelistBasic(name string) string {
165+
return fmt.Sprintf(`resource "ns1_account_whitelist" "%s" {
166+
name = "%s"
167+
values = [
168+
"0.0.0.0/0",
169+
"192.0.0.0/8",
170+
"192.168.0.0/16",
171+
"192.168.1.0/24",
172+
"192.168.1.1"
173+
]
174+
}`, name, name)
175+
}
176+
177+
func testAccAccountWhitelistUpdated(name string) string {
178+
return fmt.Sprintf(`resource "ns1_account_whitelist" "%s" {
179+
name = "%s"
180+
values = [
181+
"0.0.0.0/0",
182+
]
183+
}`, name, name)
184+
}

0 commit comments

Comments
 (0)