Skip to content

Commit 9cb4cbe

Browse files
committed
use public api for creating zones in sysdig_secure_posture_zone resource
1 parent fad3656 commit 9cb4cbe

File tree

3 files changed

+184
-32
lines changed

3 files changed

+184
-32
lines changed

sysdig/internal/client/v2/model.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,11 @@ type PostureZoneRequest struct {
11541154
Scopes []PostureZoneScope `json:"scopes"`
11551155
}
11561156

1157+
type ZonePoliciesRequest struct {
1158+
ZoneID int `json:"zoneId"`
1159+
PolicyIDs []int `json:"policyIds"`
1160+
}
1161+
11571162
type PostureZoneResponse struct {
11581163
Data PostureZone `json:"data"`
11591164
}

sysdig/internal/client/v2/posture_zones.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ import (
77
)
88

99
const (
10-
PostureZonesPath = "%s/api/cspm/v1/policy/zones"
11-
PostureZonePath = "%s/api/cspm/v1/policy/zones/%d"
10+
PostureZonesPath = "%s/api/cspm/v1/policy/zones"
11+
PostureZonePath = "%s/api/cspm/v1/policy/zones/%d"
12+
PostureZonePoliciesPath = "%s/api/cspm/v1/policy/zone-policies"
1213
)
1314

1415
type PostureZoneInterface interface {
1516
Base
1617
CreateOrUpdatePostureZone(ctx context.Context, z *PostureZoneRequest) (*PostureZone, string, error)
1718
GetPostureZone(ctx context.Context, id int) (*PostureZone, error)
1819
DeletePostureZone(ctx context.Context, id int) error
20+
BindZoneToPolicies(ctx context.Context, r *ZonePoliciesRequest) error
1921
}
2022

2123
func (client *Client) CreateOrUpdatePostureZone(ctx context.Context, r *PostureZoneRequest) (*PostureZone, string, error) {
@@ -76,10 +78,35 @@ func (client *Client) DeletePostureZone(ctx context.Context, id int) error {
7678
return nil
7779
}
7880

81+
func (client *Client) BindZoneToPolicies(ctx context.Context, r *ZonePoliciesRequest) error {
82+
83+
payload, err := Marshal(r)
84+
if err != nil {
85+
return err
86+
}
87+
88+
response, err := client.requester.Request(ctx, http.MethodPost, client.getZonePoliciesURL(), payload)
89+
if err != nil {
90+
return err
91+
}
92+
93+
defer response.Body.Close()
94+
95+
if response.StatusCode != http.StatusOK {
96+
return client.ErrorFromResponse(response)
97+
}
98+
99+
return nil
100+
}
101+
79102
func (client *Client) createPostureZoneURL() string {
80103
return fmt.Sprintf(PostureZonesPath, client.config.url)
81104
}
82105

83106
func (client *Client) getPostureZoneURL(id int) string {
84107
return fmt.Sprintf(PostureZonePath, client.config.url, id)
85108
}
109+
110+
func (client *Client) getZonePoliciesURL() string {
111+
return fmt.Sprintf(PostureZonePoliciesPath, client.config.url)
112+
}

sysdig/resource_sysdig_secure_posture_zone.go

Lines changed: 150 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package sysdig
22

33
import (
44
"context"
5+
"fmt"
6+
"github.com/rs/zerolog/log"
57
"strconv"
68
"time"
79

@@ -14,8 +16,8 @@ func resourceSysdigSecurePostureZone() *schema.Resource {
1416
timeout := 5 * time.Minute
1517

1618
return &schema.Resource{
17-
CreateContext: resourceCreateOrUpdatePostureZone,
18-
UpdateContext: resourceCreateOrUpdatePostureZone,
19+
CreateContext: resourceCreatePostureZone,
20+
UpdateContext: resourceUpdatePostureZone,
1921
DeleteContext: resourceSysdigSecurePostureZoneDelete,
2022
ReadContext: resourceSysdigSecurePostureZoneRead,
2123
Importer: &schema.ResourceImporter{
@@ -105,48 +107,113 @@ func getPostureZoneClient(c SysdigClients) (v2.PostureZoneInterface, error) {
105107
return client, nil
106108
}
107109

108-
func resourceCreateOrUpdatePostureZone(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
109-
policiesData := d.Get(SchemaPolicyIDsKey).(*schema.Set).List()
110-
policies := make([]string, len(policiesData))
111-
for i, p := range policiesData {
112-
policies[i] = strconv.Itoa(p.(int))
110+
func resourceCreatePostureZone(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
111+
policies, err := getPolicies(d)
112+
if err != nil {
113+
return diag.FromErr(err)
113114
}
114115

115-
scopesList := d.Get(SchemaScopesKey).(*schema.Set).List()
116-
scopes := make([]v2.PostureZoneScope, 0)
117-
if len(scopesList) > 0 {
118-
scopeList := scopesList[0].(map[string]interface{})[SchemaScopeKey].(*schema.Set).List()
119-
for _, attr := range scopeList {
120-
s := attr.(map[string]interface{})
121-
scopes = append(scopes, v2.PostureZoneScope{
122-
TargetType: s[SchemaTargetTypeKey].(string),
123-
Rules: s[SchemaRulesKey].(string),
124-
})
125-
}
116+
scopes, err := getScopes(d)
117+
if err != nil {
118+
return diag.FromErr(err)
119+
}
120+
121+
zoneClient, err := getZoneClient(meta.(SysdigClients))
122+
postureZoneClient, err := getPostureZoneClient(meta.(SysdigClients))
123+
if err != nil {
124+
return diag.FromErr(err)
126125
}
127126

128-
req := &v2.PostureZoneRequest{
129-
ID: d.Id(),
127+
zoneRequest := &v2.ZoneRequest{
130128
Name: d.Get(SchemaNameKey).(string),
131129
Description: d.Get(SchemaDescriptionKey).(string),
132-
PolicyIDs: policies,
133130
Scopes: scopes,
134131
}
135132

136-
zoneClient, err := getPostureZoneClient(meta.(SysdigClients))
133+
zone, err := zoneClient.CreateZone(ctx, zoneRequest)
134+
if err != nil {
135+
return diag.Errorf("Error creating resource: %s", err)
136+
}
137+
138+
policyIDs, err := convertPoliciesToInt(policies)
137139
if err != nil {
138140
return diag.FromErr(err)
139141
}
140142

141-
zone, errStatus, err := zoneClient.CreateOrUpdatePostureZone(ctx, req)
143+
req := &v2.ZonePoliciesRequest{
144+
ZoneID: zone.ID,
145+
PolicyIDs: policyIDs,
146+
}
147+
148+
err = postureZoneClient.BindZoneToPolicies(ctx, req)
142149
if err != nil {
143-
return diag.Errorf("Error creating resource: %s %s", errStatus, err)
150+
log.Err(err).Int("zone_id", zone.ID).Msg("Error attaching zone to policies... deleting created zone")
151+
err2 := zoneClient.DeleteZone(ctx, zone.ID)
152+
if err2 != nil {
153+
return diag.Errorf("Error deleting zone [zone ID = %d] after failed attaching to policies: %s", zone.ID, err2)
154+
}
155+
return diag.Errorf("Error attaching zone to policies: %s", err)
144156
}
145157

146-
d.SetId(zone.ID)
158+
d.SetId(strconv.Itoa(zone.ID))
159+
return resourceSysdigSecurePostureZoneRead(ctx, d, meta)
160+
}
147161

148-
resourceSysdigSecurePostureZoneRead(ctx, d, meta)
149-
return nil
162+
func resourceUpdatePostureZone(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
163+
policies, err := getPolicies(d)
164+
if err != nil {
165+
return diag.FromErr(err)
166+
}
167+
168+
scopes, err := getScopes(d)
169+
if err != nil {
170+
return diag.FromErr(err)
171+
}
172+
173+
zoneClient, err := getZoneClient(meta.(SysdigClients))
174+
postureZoneClient, err := getPostureZoneClient(meta.(SysdigClients))
175+
if err != nil {
176+
return diag.FromErr(err)
177+
}
178+
179+
id, err := strconv.Atoi(d.Id())
180+
if err != nil {
181+
return diag.Errorf("Error updating posture zone resource, ID is not integer: %s", d.Id())
182+
}
183+
184+
zoneRequest := &v2.ZoneRequest{
185+
ID: id,
186+
Name: d.Get(SchemaNameKey).(string),
187+
Description: d.Get(SchemaDescriptionKey).(string),
188+
Scopes: scopes,
189+
}
190+
191+
if d.HasChange(SchemaNameKey) || d.HasChange(SchemaDescriptionKey) || d.HasChange(SchemaScopesKey) {
192+
_, err = zoneClient.UpdateZone(ctx, zoneRequest)
193+
if err != nil {
194+
return diag.Errorf("Error updating resource: %s", err)
195+
}
196+
}
197+
198+
policyIDs, err := convertPoliciesToInt(policies)
199+
if err != nil {
200+
return diag.FromErr(err)
201+
}
202+
203+
if d.HasChange(SchemaPolicyIDsKey) {
204+
req := &v2.ZonePoliciesRequest{
205+
ZoneID: id,
206+
PolicyIDs: policyIDs,
207+
}
208+
209+
err = postureZoneClient.BindZoneToPolicies(ctx, req)
210+
if err != nil {
211+
log.Err(err).Int("zone_id", id).Msg("Error attaching zone to policies")
212+
return diag.Errorf("Error attaching zone to policies: %s", err)
213+
}
214+
}
215+
216+
return resourceSysdigSecurePostureZoneRead(ctx, d, meta)
150217
}
151218

152219
func resourceSysdigSecurePostureZoneRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
@@ -225,7 +292,8 @@ func resourceSysdigSecurePostureZoneRead(ctx context.Context, d *schema.Resource
225292
}
226293

227294
func resourceSysdigSecurePostureZoneDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
228-
client, err := getPostureZoneClient(meta.(SysdigClients))
295+
postureClient, err := getPostureZoneClient(meta.(SysdigClients))
296+
zoneClient, err := getZoneClient(meta.(SysdigClients))
229297
if err != nil {
230298
return diag.FromErr(err)
231299
}
@@ -235,10 +303,62 @@ func resourceSysdigSecurePostureZoneDelete(ctx context.Context, d *schema.Resour
235303
return diag.FromErr(err)
236304
}
237305

238-
err = client.DeletePostureZone(ctx, id)
306+
err = removeZoneFromPolicies(ctx, postureClient, id)
239307
if err != nil {
240-
return diag.FromErr(err)
308+
return diag.Errorf("Error removing zone from policies: %s", err)
309+
}
310+
311+
err = zoneClient.DeleteZone(ctx, id)
312+
if err != nil {
313+
314+
return diag.Errorf("Error deleting zone: %s", err)
241315
}
242316

243317
return nil
244318
}
319+
320+
func removeZoneFromPolicies(ctx context.Context, client v2.PostureZoneInterface, zoneID int) error {
321+
req := &v2.ZonePoliciesRequest{
322+
ZoneID: zoneID,
323+
PolicyIDs: []int{},
324+
}
325+
326+
return client.BindZoneToPolicies(ctx, req)
327+
}
328+
329+
func getPolicies(d *schema.ResourceData) ([]string, error) {
330+
policiesData := d.Get(SchemaPolicyIDsKey).(*schema.Set).List()
331+
policies := make([]string, len(policiesData))
332+
for i, p := range policiesData {
333+
policies[i] = strconv.Itoa(p.(int))
334+
}
335+
return policies, nil
336+
}
337+
338+
func getScopes(d *schema.ResourceData) ([]v2.ZoneScope, error) {
339+
scopesList := d.Get(SchemaScopesKey).(*schema.Set).List()
340+
scopes := make([]v2.ZoneScope, 0)
341+
if len(scopesList) > 0 {
342+
scopeList := scopesList[0].(map[string]interface{})[SchemaScopeKey].(*schema.Set).List()
343+
for _, attr := range scopeList {
344+
s := attr.(map[string]interface{})
345+
scopes = append(scopes, v2.ZoneScope{
346+
TargetType: s[SchemaTargetTypeKey].(string),
347+
Rules: s[SchemaRulesKey].(string),
348+
})
349+
}
350+
}
351+
return scopes, nil
352+
}
353+
354+
func convertPoliciesToInt(policies []string) ([]int, error) {
355+
policyIDs := make([]int, len(policies))
356+
for i, p := range policies {
357+
id, err := strconv.Atoi(p)
358+
if err != nil {
359+
return nil, fmt.Errorf("error converting policy ID to int: %s", err)
360+
}
361+
policyIDs[i] = id
362+
}
363+
return policyIDs, nil
364+
}

0 commit comments

Comments
 (0)