Skip to content

Commit 3a3368b

Browse files
Implementation of response policy support
Introduce `aquasec_response_policy` resource and `aquasec_response_policies`/`aquasec_response_policy_config` data sources with full client CRUD, utils, docs, and tests. - **Resource** - Add `aquasec_response_policy` with schema (`title`, `description`, `enabled`, `application_scopes`, `trigger`, `outputs`) and full CRUD in `aquasec/resource_response_policy.go`. - **Data Sources** - Add list data source `aquasec_response_policies` and config data source `aquasec_response_policy_config` in `aquasec/data_response_policy.go` (pagination/filtering + config fields). - **Provider Wiring** - Register new resource and data sources in `aquasec/provider.go`. - **Client API** - Implement `client/response_policy.go` with types and endpoints: get/list/create/update/delete, delete-all, status update, and config fetch. - **Utils** - Extend `aquasec/utils.go` with flatten/expand helpers for response policy schemas and config. - **Docs** - Add docs: `docs/resources/response_policy.md`, `docs/data-sources/response_policies.md`, `docs/data-sources/response_policy_config.md`. - **Tests** - Add acceptance tests for resource and data sources in `aquasec/resource_response_policy_test.go` and `aquasec/data_response_policy_test.go`.
1 parent f764ddd commit 3a3368b

File tree

12 files changed

+1809
-0
lines changed

12 files changed

+1809
-0
lines changed

aquasec/data_response_policy.go

Lines changed: 352 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,352 @@
1+
package aquasec
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"strings"
8+
9+
"github.com/aquasecurity/terraform-provider-aquasec/client"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
)
13+
14+
func dataResponsePolicy() *schema.Resource {
15+
return &schema.Resource{
16+
ReadContext: dataResponsePolicyRead,
17+
Schema: map[string]*schema.Schema{
18+
"page": {
19+
Type: schema.TypeInt,
20+
Optional: true,
21+
Default: 1,
22+
},
23+
"page_size": {
24+
Type: schema.TypeInt,
25+
Optional: true,
26+
Default: 10,
27+
},
28+
"scope": {
29+
Type: schema.TypeString,
30+
Optional: true,
31+
},
32+
"title": {
33+
Type: schema.TypeString,
34+
Optional: true,
35+
},
36+
"pagination_data": {
37+
Type: schema.TypeBool,
38+
Optional: true,
39+
Default: false,
40+
},
41+
"data": {
42+
Type: schema.TypeList,
43+
Computed: true,
44+
Elem: &schema.Resource{
45+
Schema: map[string]*schema.Schema{
46+
"id": {
47+
Type: schema.TypeInt,
48+
Computed: true,
49+
},
50+
"title": {
51+
Type: schema.TypeString,
52+
Computed: true,
53+
},
54+
"description": {
55+
Type: schema.TypeString,
56+
Computed: true,
57+
},
58+
"enabled": {
59+
Type: schema.TypeBool,
60+
Computed: true,
61+
},
62+
"application_scopes": {
63+
Type: schema.TypeSet,
64+
Elem: &schema.Schema{Type: schema.TypeString},
65+
Computed: true,
66+
},
67+
"last_updated_by": {
68+
Type: schema.TypeString,
69+
Computed: true,
70+
},
71+
"last_update": {
72+
Type: schema.TypeInt,
73+
Computed: true,
74+
},
75+
"created_at": {
76+
Type: schema.TypeInt,
77+
Computed: true,
78+
},
79+
"trigger": {
80+
Type: schema.TypeList,
81+
Computed: true,
82+
Elem: &schema.Resource{
83+
Schema: map[string]*schema.Schema{
84+
"predefined": {
85+
Type: schema.TypeString,
86+
Computed: true,
87+
},
88+
"input": {
89+
Type: schema.TypeList,
90+
Computed: true,
91+
Elem: &schema.Resource{
92+
Schema: map[string]*schema.Schema{
93+
"name": {
94+
Type: schema.TypeString,
95+
Computed: true,
96+
},
97+
"attributes": {
98+
Type: schema.TypeList,
99+
Computed: true,
100+
Elem: &schema.Resource{
101+
Schema: map[string]*schema.Schema{
102+
"name": {
103+
Type: schema.TypeString,
104+
Computed: true,
105+
},
106+
"value": {
107+
Type: schema.TypeString,
108+
Computed: true,
109+
},
110+
"operation": {
111+
Type: schema.TypeString,
112+
Computed: true,
113+
},
114+
},
115+
},
116+
},
117+
},
118+
},
119+
},
120+
"custom": {
121+
Type: schema.TypeList,
122+
Computed: true,
123+
Elem: &schema.Resource{
124+
Schema: map[string]*schema.Schema{
125+
"rego": {
126+
Type: schema.TypeString,
127+
Computed: true,
128+
},
129+
},
130+
},
131+
},
132+
},
133+
},
134+
},
135+
"outputs": {
136+
Type: schema.TypeList,
137+
Computed: true,
138+
Elem: &schema.Resource{
139+
Schema: map[string]*schema.Schema{
140+
"name": {
141+
Type: schema.TypeString,
142+
Computed: true,
143+
},
144+
"type": {
145+
Type: schema.TypeString,
146+
Computed: true,
147+
},
148+
},
149+
},
150+
},
151+
},
152+
},
153+
},
154+
},
155+
}
156+
}
157+
158+
func dataResponsePolicyRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
159+
ac := m.(*client.Client)
160+
policyResp := client.ResponsePolicyResp{
161+
Page: d.Get("page").(int),
162+
PageSize: d.Get("page_size").(int),
163+
Scope: d.Get("scope").(string),
164+
Title: d.Get("title").(string),
165+
}
166+
167+
respPol, err := ac.GetResponsePolicies(policyResp)
168+
if err != nil {
169+
if strings.Contains(fmt.Sprintf("%s", err), "not found") {
170+
d.SetId("")
171+
return nil
172+
}
173+
return diag.FromErr(err)
174+
}
175+
176+
// If API returned no content (204) GetResponsePolicies may return nil
177+
if respPol == nil {
178+
// set empty data and a stable id
179+
if err := d.Set("data", []interface{}{}); err != nil {
180+
return diag.FromErr(err)
181+
}
182+
d.SetId("all")
183+
return nil
184+
}
185+
186+
var polList []client.ResponsePolicy
187+
for _, polItem := range respPol.Data {
188+
b, merr := json.Marshal(polItem)
189+
if merr != nil {
190+
return diag.FromErr(merr)
191+
}
192+
var pol client.ResponsePolicy
193+
if err := json.Unmarshal(b, &pol); err != nil {
194+
return diag.FromErr(err)
195+
}
196+
polList = append(polList, pol)
197+
}
198+
policy, _ := flattenResponsePolicies(&polList)
199+
200+
if err := d.Set("data", policy); err != nil {
201+
return diag.FromErr(err)
202+
}
203+
d.SetId("all")
204+
return nil
205+
}
206+
207+
func dataResponsePolicyConfig() *schema.Resource {
208+
return &schema.Resource{
209+
ReadContext: dataResponsePolicyConfigRead,
210+
Schema: map[string]*schema.Schema{
211+
"triggers": {
212+
Type: schema.TypeList,
213+
Computed: true,
214+
Elem: &schema.Resource{
215+
Schema: map[string]*schema.Schema{
216+
"name": {
217+
Type: schema.TypeString,
218+
Computed: true,
219+
},
220+
"type": {
221+
Type: schema.TypeString,
222+
Computed: true,
223+
},
224+
},
225+
},
226+
},
227+
"input": {
228+
Type: schema.TypeList,
229+
Computed: true,
230+
Elem: &schema.Resource{
231+
Schema: map[string]*schema.Schema{
232+
"asset_types": {
233+
Type: schema.TypeList,
234+
Computed: true,
235+
Elem: &schema.Resource{
236+
Schema: map[string]*schema.Schema{
237+
"display_name": {
238+
Type: schema.TypeString,
239+
Computed: true,
240+
},
241+
"field": {
242+
Type: schema.TypeString,
243+
Computed: true,
244+
},
245+
"value": {
246+
Type: schema.TypeString,
247+
Computed: true,
248+
},
249+
},
250+
},
251+
},
252+
"attributes": {
253+
Type: schema.TypeList,
254+
Computed: true,
255+
Elem: &schema.Resource{
256+
Schema: map[string]*schema.Schema{
257+
"name": {
258+
Type: schema.TypeString,
259+
Computed: true,
260+
},
261+
"type": {
262+
Type: schema.TypeString,
263+
Computed: true,
264+
},
265+
"input_type": {
266+
Type: schema.TypeString,
267+
Computed: true,
268+
},
269+
"asset_types": {
270+
Type: schema.TypeList,
271+
Elem: &schema.Schema{Type: schema.TypeString},
272+
Computed: true,
273+
},
274+
"display_name": {
275+
Type: schema.TypeString,
276+
Computed: true,
277+
},
278+
"enabled": {
279+
Type: schema.TypeBool,
280+
Computed: true,
281+
},
282+
"options": {
283+
Type: schema.TypeList,
284+
Computed: true,
285+
Elem: &schema.Resource{
286+
Schema: map[string]*schema.Schema{
287+
"display_name": {
288+
Type: schema.TypeString,
289+
Computed: true,
290+
},
291+
"value": {
292+
Type: schema.TypeString,
293+
Computed: true,
294+
},
295+
},
296+
},
297+
},
298+
},
299+
},
300+
},
301+
"operations": {
302+
Type: schema.TypeList,
303+
Computed: true,
304+
Elem: &schema.Resource{
305+
Schema: map[string]*schema.Schema{
306+
"name": {
307+
Type: schema.TypeString,
308+
Computed: true,
309+
},
310+
"type": {
311+
Type: schema.TypeString,
312+
Computed: true,
313+
},
314+
"display_name": {
315+
Type: schema.TypeString,
316+
Computed: true,
317+
},
318+
"enabled": {
319+
Type: schema.TypeBool,
320+
Computed: true,
321+
},
322+
},
323+
},
324+
},
325+
},
326+
},
327+
},
328+
},
329+
}
330+
}
331+
332+
func dataResponsePolicyConfigRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
333+
ac := m.(*client.Client)
334+
335+
respPolConfig, err := ac.GetResponsePolicyConfig()
336+
if err != nil {
337+
return diag.FromErr(err)
338+
}
339+
if respPolConfig == nil {
340+
// no config returned (204), treat as empty and set ID
341+
d.SetId("config")
342+
return nil
343+
}
344+
if err := d.Set("triggers", flattenResponsePolicyTriggerConfigs(respPolConfig.Triggers)); err != nil {
345+
return diag.FromErr(err)
346+
}
347+
if err := d.Set("input", flattenResponsePolicyInputsConfig(respPolConfig.Input)); err != nil {
348+
return diag.FromErr(err)
349+
}
350+
d.SetId("config")
351+
return nil
352+
}

0 commit comments

Comments
 (0)