Skip to content

Commit 779e9c0

Browse files
authored
feat(ip filter) Add ip filter resource for both monitor and secure (#534)
* feat(allowed ip range) Add allowed ip range resource for both monitor and secure SP-3101 * add build tag to acc test * remove unused `allowedIpRangeWrapper` * rename resource: 'allowed_ip_range' > 'ip_filter' * remove check for status 200 when deleting ip filter * minor refactor - change 'Ip' > 'IP' in method names * add ip_filters_settings resource used for enabling/disabling IP filters * update `sysdig_ip_filters_settings` documentation * rename helper methods in tests * add Attributes Reference to docs * rename `ip_filters_settings` resource to `ip_filtering_settings`
1 parent 10d96d7 commit 779e9c0

12 files changed

+637
-7
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ $ cd terraform-provider-sysdig
3535
$ make build
3636
```
3737

38-
If you're a rookie, check [Official Terraform Provider development guides](https://developer.hashicorp.com/terraform/plugin/frameworkO)
38+
If you're a rookie, check [Official Terraform Provider development guides](https://developer.hashicorp.com/terraform/plugin/framework)
3939

4040
### Creating new resource / data sources
4141

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package v2
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
)
8+
9+
const (
10+
IPFiltersSettingsPath = "%s/platform/v1/ip-filters-settings"
11+
)
12+
13+
type IPFilteringSettingsInterface interface {
14+
Base
15+
GetIPFilteringSettings(ctx context.Context) (*IPFiltersSettings, error)
16+
UpdateIPFilteringSettings(ctx context.Context, ipFiltersSettings *IPFiltersSettings) (*IPFiltersSettings, error)
17+
}
18+
19+
func (client *Client) GetIPFilteringSettings(ctx context.Context) (*IPFiltersSettings, error) {
20+
response, err := client.requester.Request(ctx, http.MethodGet, client.GetIPFiltersSettingsURL(), nil)
21+
if err != nil {
22+
return nil, err
23+
}
24+
defer response.Body.Close()
25+
26+
if response.StatusCode != http.StatusOK {
27+
err = client.ErrorFromResponse(response)
28+
return nil, err
29+
}
30+
31+
ipFiltersSettings, err := Unmarshal[IPFiltersSettings](response.Body)
32+
if err != nil {
33+
return nil, err
34+
}
35+
36+
return &ipFiltersSettings, nil
37+
}
38+
39+
func (client *Client) UpdateIPFilteringSettings(ctx context.Context, ipFiltersSettings *IPFiltersSettings) (*IPFiltersSettings, error) {
40+
payload, err := Marshal(ipFiltersSettings)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
response, err := client.requester.Request(ctx, http.MethodPut, client.GetIPFiltersSettingsURL(), payload)
46+
if err != nil {
47+
return nil, err
48+
}
49+
defer response.Body.Close()
50+
51+
if response.StatusCode != http.StatusOK {
52+
return nil, client.ErrorFromResponse(response)
53+
}
54+
55+
updated, err := Unmarshal[IPFiltersSettings](response.Body)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
return &updated, nil
61+
}
62+
63+
func (client *Client) GetIPFiltersSettingsURL() string {
64+
return fmt.Sprintf(IPFiltersSettingsPath, client.config.url)
65+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package v2
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
)
9+
10+
var IPFilterNotFound = errors.New("IP filter not found")
11+
12+
const (
13+
IPFiltersPath = "%s/platform/v1/ip-filters"
14+
IPFilterPath = "%s/platform/v1/ip-filters/%d"
15+
)
16+
17+
type IPFiltersInterface interface {
18+
Base
19+
GetIPFilterById(ctx context.Context, id int) (*IPFilter, error)
20+
CreateIPFilter(ctx context.Context, ipFilter *IPFilter) (*IPFilter, error)
21+
UpdateIPFilter(ctx context.Context, ipFilter *IPFilter, id int) (*IPFilter, error)
22+
DeleteIPFilter(ctx context.Context, id int) error
23+
}
24+
25+
func (client *Client) GetIPFilterById(ctx context.Context, id int) (*IPFilter, error) {
26+
response, err := client.requester.Request(ctx, http.MethodGet, client.GetIPFilterURL(id), nil)
27+
if err != nil {
28+
return nil, err
29+
}
30+
defer response.Body.Close()
31+
32+
if response.StatusCode != http.StatusOK {
33+
err = client.ErrorFromResponse(response)
34+
return nil, err
35+
}
36+
37+
ipFilter, err := Unmarshal[IPFilter](response.Body)
38+
if err != nil {
39+
return nil, err
40+
}
41+
42+
return &ipFilter, nil
43+
}
44+
45+
func (client *Client) CreateIPFilter(ctx context.Context, ipFilter *IPFilter) (*IPFilter, error) {
46+
payload, err := Marshal(ipFilter)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
response, err := client.requester.Request(ctx, http.MethodPost, client.GetIPFiltersURL(), payload)
52+
if err != nil {
53+
return nil, err
54+
}
55+
defer response.Body.Close()
56+
57+
if response.StatusCode != http.StatusCreated {
58+
return nil, client.ErrorFromResponse(response)
59+
}
60+
61+
created, err := Unmarshal[IPFilter](response.Body)
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
return &created, nil
67+
68+
}
69+
70+
func (client *Client) UpdateIPFilter(ctx context.Context, ipFilter *IPFilter, id int) (*IPFilter, error) {
71+
payload, err := Marshal(ipFilter)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
response, err := client.requester.Request(ctx, http.MethodPut, client.GetIPFilterURL(id), payload)
77+
if err != nil {
78+
return nil, err
79+
}
80+
defer response.Body.Close()
81+
82+
if response.StatusCode != http.StatusOK {
83+
return nil, client.ErrorFromResponse(response)
84+
}
85+
86+
updated, err := Unmarshal[IPFilter](response.Body)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
return &updated, nil
92+
}
93+
94+
func (client *Client) DeleteIPFilter(ctx context.Context, id int) error {
95+
response, err := client.requester.Request(ctx, http.MethodDelete, client.GetIPFilterURL(id), nil)
96+
if err != nil {
97+
return err
98+
}
99+
defer response.Body.Close()
100+
101+
if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusNotFound {
102+
return client.ErrorFromResponse(response)
103+
}
104+
105+
return nil
106+
}
107+
108+
func (client *Client) GetIPFilterURL(id int) string {
109+
return fmt.Sprintf(IPFilterPath, client.config.url, id)
110+
}
111+
112+
func (client *Client) GetIPFiltersURL() string {
113+
return fmt.Sprintf(IPFiltersPath, client.config.url)
114+
}

sysdig/internal/client/v2/model.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,18 @@ type GroupMappingConfig struct {
174174
DifferentTeamSameRoleStrategy string `json:"differentRolesSameTeamStrategy"`
175175
}
176176

177+
type IPFilter struct {
178+
ID int `json:"id,omitempty"`
179+
IPRange string `json:"ipRange"`
180+
Note string `json:"note,omitempty"`
181+
Enabled bool `json:"isEnabled"`
182+
LastUpdated string `json:"lastUpdated,omitempty"`
183+
}
184+
185+
type IPFiltersSettings struct {
186+
IPFilteringEnabled bool `json:"isFilteringEnabled"`
187+
}
188+
177189
type alertWrapper struct {
178190
Alert Alert `json:"alert"`
179191
}

sysdig/internal/client/v2/sysdig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ type SysdigCommon interface {
2323
CustomRoleInterface
2424
CustomRolePermissionInterface
2525
TeamServiceAccountInterface
26+
IPFiltersInterface
27+
IPFilteringSettingsInterface
2628
}
2729

2830
type SysdigMonitor interface {

sysdig/provider.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,14 @@ func (p *SysdigProvider) Provider() *schema.Provider {
115115
},
116116
},
117117
ResourcesMap: map[string]*schema.Resource{
118-
"sysdig_user": resourceSysdigUser(),
119-
"sysdig_group_mapping": resourceSysdigGroupMapping(),
120-
"sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(),
121-
"sysdig_custom_role": resourceSysdigCustomRole(),
122-
"sysdig_team_service_account": resourceSysdigTeamServiceAccount(),
123-
"sysdig_agent_access_key": resourceSysdigAgentAccessKey(),
118+
"sysdig_user": resourceSysdigUser(),
119+
"sysdig_group_mapping": resourceSysdigGroupMapping(),
120+
"sysdig_group_mapping_config": resourceSysdigGroupMappingConfig(),
121+
"sysdig_custom_role": resourceSysdigCustomRole(),
122+
"sysdig_team_service_account": resourceSysdigTeamServiceAccount(),
123+
"sysdig_agent_access_key": resourceSysdigAgentAccessKey(),
124+
"sysdig_ip_filter": resourceSysdigIPFilter(),
125+
"sysdig_ip_filtering_settings": resourceSysdigIPFilteringSettings(),
124126

125127
"sysdig_secure_aws_ml_policy": resourceSysdigSecureAWSMLPolicy(),
126128
"sysdig_secure_custom_policy": resourceSysdigSecureCustomPolicy(),
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package sysdig
2+
3+
import (
4+
"context"
5+
v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2"
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"strconv"
9+
)
10+
11+
func resourceSysdigIPFilter() *schema.Resource {
12+
return &schema.Resource{
13+
ReadContext: resourceSysdigIPFilterRead,
14+
CreateContext: resourceSysdigIPFilterCreate,
15+
UpdateContext: resourceSysdigIPFilterUpdate,
16+
DeleteContext: resourceSysdigIPFilterDelete,
17+
Schema: map[string]*schema.Schema{
18+
"ip_range": {
19+
Type: schema.TypeString,
20+
Required: true,
21+
},
22+
"note": {
23+
Type: schema.TypeString,
24+
Optional: true,
25+
},
26+
"enabled": {
27+
Type: schema.TypeBool,
28+
Required: true,
29+
},
30+
},
31+
}
32+
}
33+
34+
func resourceSysdigIPFilterRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
35+
client, err := m.(SysdigClients).sysdigCommonClientV2()
36+
if err != nil {
37+
return diag.FromErr(err)
38+
}
39+
40+
id, err := strconv.Atoi(d.Id())
41+
if err != nil {
42+
return diag.FromErr(err)
43+
}
44+
45+
ipFilter, err := client.GetIPFilterById(ctx, id)
46+
if err != nil {
47+
if err == v2.IPFilterNotFound {
48+
d.SetId("")
49+
return nil
50+
}
51+
return diag.FromErr(err)
52+
}
53+
54+
err = ipFilterToResourceData(ipFilter, d)
55+
if err != nil {
56+
return diag.FromErr(err)
57+
}
58+
59+
return nil
60+
}
61+
62+
func resourceSysdigIPFilterCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
63+
client, err := m.(SysdigClients).sysdigCommonClientV2()
64+
if err != nil {
65+
return diag.FromErr(err)
66+
}
67+
68+
ipFilter, err := ipFilterFromResourceData(d)
69+
if err != nil {
70+
return diag.FromErr(err)
71+
}
72+
73+
createdIPFilter, err := client.CreateIPFilter(ctx, ipFilter)
74+
if err != nil {
75+
return diag.FromErr(err)
76+
}
77+
78+
d.SetId(strconv.Itoa(createdIPFilter.ID))
79+
80+
resourceSysdigIPFilterRead(ctx, d, m)
81+
82+
return nil
83+
}
84+
85+
func resourceSysdigIPFilterUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
86+
client, err := m.(SysdigClients).sysdigCommonClientV2()
87+
if err != nil {
88+
return diag.FromErr(err)
89+
}
90+
91+
ipFilter, err := ipFilterFromResourceData(d)
92+
if err != nil {
93+
return diag.FromErr(err)
94+
}
95+
96+
id, err := strconv.Atoi(d.Id())
97+
if err != nil {
98+
return diag.FromErr(err)
99+
100+
}
101+
102+
ipFilter.ID = id
103+
_, err = client.UpdateIPFilter(ctx, ipFilter, id)
104+
if err != nil {
105+
return diag.FromErr(err)
106+
}
107+
108+
resourceSysdigIPFilterRead(ctx, d, m)
109+
110+
return nil
111+
}
112+
113+
func resourceSysdigIPFilterDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
114+
client, err := m.(SysdigClients).sysdigCommonClientV2()
115+
if err != nil {
116+
return diag.FromErr(err)
117+
}
118+
119+
id, err := strconv.Atoi(d.Id())
120+
if err != nil {
121+
return diag.FromErr(err)
122+
}
123+
124+
err = client.DeleteIPFilter(ctx, id)
125+
if err != nil {
126+
return diag.FromErr(err)
127+
}
128+
129+
return nil
130+
}
131+
132+
func ipFilterToResourceData(ipFilter *v2.IPFilter, d *schema.ResourceData) error {
133+
err := d.Set("ip_range", ipFilter.IPRange)
134+
if err != nil {
135+
return err
136+
}
137+
err = d.Set("note", ipFilter.Note)
138+
if err != nil {
139+
return err
140+
}
141+
err = d.Set("enabled", ipFilter.Enabled)
142+
if err != nil {
143+
return err
144+
}
145+
146+
return nil
147+
}
148+
149+
func ipFilterFromResourceData(d *schema.ResourceData) (*v2.IPFilter, error) {
150+
return &v2.IPFilter{
151+
IPRange: d.Get("ip_range").(string),
152+
Note: d.Get("note").(string),
153+
Enabled: d.Get("enabled").(bool),
154+
}, nil
155+
}

0 commit comments

Comments
 (0)