Skip to content

Commit 4d98872

Browse files
feat(CAD-360): Support Resource Group v2 in CLI (#1340)
* feat(CAD-360): RGv2 CRUD support in CLI Signed-off-by: Zeki Sherif <[email protected]> * style: formatting Signed-off-by: Darren Murray <[email protected]> * Update api/resource_groups.go Co-authored-by: Darren <[email protected]> * chore: address comments Signed-off-by: Zeki Sherif <[email protected]> * fix: fix time issue --------- Signed-off-by: Zeki Sherif <[email protected]> Signed-off-by: Darren Murray <[email protected]> Co-authored-by: Darren Murray <[email protected]> Co-authored-by: Darren <[email protected]>
1 parent edfa213 commit 4d98872

14 files changed

+941
-120
lines changed

api/_examples/resource-groups/main.go

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,17 @@ func main() {
2323
}
2424

2525
for _, account := range res.Data {
26+
var resourceGuid string
27+
resourceType := account.Type
28+
29+
if account.Props != nil {
30+
resourceGuid = account.ResourceGuid
31+
} else {
32+
resourceGuid = account.ResourceGroupGuid
33+
}
34+
2635
support := "Unsupported"
27-
switch account.Type {
36+
switch resourceType {
2837
case api.AwsResourceGroup.String():
2938
support = "Supported"
3039
case api.AzureResourceGroup.String():
@@ -40,8 +49,63 @@ func main() {
4049
}
4150

4251
// Output: RESOURCE_GUID:RESOURCE_TYPE:[Supported|Unsupported]
43-
fmt.Printf("%s:%s:%s\n", account.ResourceGuid, account.Type, support)
52+
fmt.Printf("%s:%s:%s\n", resourceGuid, resourceType, support)
53+
}
54+
55+
rgExpression := api.RGExpression{
56+
Operator: "AND",
57+
Children: []*api.RGChild{
58+
{
59+
FilterName: "filter1",
60+
},
61+
},
62+
}
63+
64+
rgFilter := api.RGFilter{
65+
Field: "Region",
66+
Operation: "STARTS_WITH",
67+
Values: []string{"us-"},
68+
}
69+
70+
rgQuery := api.RGQuery{
71+
Expression: &rgExpression,
72+
Filters: map[string]*api.RGFilter{
73+
"filter1": &rgFilter,
74+
},
75+
}
76+
77+
myResourceGroupWithQuery := api.NewResourceGroupWithQuery(
78+
"resource-group-with-query-from-golang",
79+
api.AwsResourceGroup,
80+
"Resource groups in `us` regions",
81+
&rgQuery,
82+
)
83+
84+
println("Creating a resource group v2")
85+
rgV2Resp, err := lacework.V2.ResourceGroups.Create(myResourceGroupWithQuery)
86+
87+
if err != nil {
88+
log.Fatal(err)
89+
}
90+
91+
fmt.Printf("Succesfully created resource group \n %+v\n", rgV2Resp)
92+
93+
println("Updating v2 resource group name")
94+
rgV2Resp.Data.NameV2 = "resource-group-with-query-from-golang-updated"
95+
96+
updatedResponse, err := lacework.V2.ResourceGroups.UpdateAws(&rgV2Resp.Data)
97+
98+
if err != nil {
99+
log.Fatal(err)
100+
}
101+
fmt.Printf("Succesfully updated resource group \n %+v\n", updatedResponse)
102+
103+
fmt.Printf("Deleting resource group %s\n", updatedResponse.Data.ResourceGroupGuid)
104+
err = lacework.V2.ResourceGroups.Delete(updatedResponse.Data.ResourceGroupGuid)
105+
if err != nil {
106+
log.Fatal(err)
44107
}
108+
println("Successfully deleted resource group")
45109

46110
props := api.LwAccountResourceGroupProps{
47111
Description: "All Lacework accounts",

api/feature_flags.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"fmt"
55
)
66

7+
const ApiV2CliFeatureFlag = "PUBLIC.rgv2.cli"
8+
79
type FeatureFlagsService struct {
810
client *Client
911
}

api/resource_groups.go

Lines changed: 53 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import (
2222
"encoding/json"
2323
"fmt"
2424
"strconv"
25-
26-
"github.com/pkg/errors"
25+
"time"
2726

2827
"github.com/lacework/go-sdk/lwtime"
28+
"github.com/pkg/errors"
2929
)
3030

3131
// ResourceGroupsService is the service that interacts with
@@ -48,6 +48,8 @@ type ResourceGroup interface {
4848
ID() string
4949
ResourceGroupType() ResourceGroupType
5050
ResetResourceGUID()
51+
ResetRGV2Fields()
52+
IsV2Group() bool
5153
}
5254

5355
type ResourceGroupType int
@@ -81,41 +83,6 @@ func (i ResourceGroupType) String() string {
8183
return ResourceGroupTypes[i]
8284
}
8385

84-
// NewResourceGroup returns an instance of the ResourceGroupData struct with the
85-
// provided ResourceGroup type, name and the props field as an interface{}.
86-
//
87-
// NOTE: This function must be used by any ResourceGroup type.
88-
//
89-
// Basic usage: Initialize a new ContainerResourceGroup struct, then
90-
//
91-
// use the new instance to do CRUD operations
92-
//
93-
// client, err := api.NewClient("account")
94-
// if err != nil {
95-
// return err
96-
// }
97-
//
98-
// group := api.NewResourceGroup("container resource group",
99-
// api.ContainerResourceGroup,
100-
// api.ContainerResourceGroupData{
101-
// Props: api.ContainerResourceGroupProps{
102-
// Description: "all containers,
103-
// ContainerLabels: ContainerResourceGroupAllLabels,
104-
// ContainerTags: ContainerResourceGroupAllTags,
105-
// },
106-
// },
107-
// )
108-
//
109-
// client.V2.ResourceGroups.Create(group)
110-
func NewResourceGroup(name string, iType ResourceGroupType, props interface{}) ResourceGroupData {
111-
return ResourceGroupData{
112-
Name: name,
113-
Type: iType.String(),
114-
Enabled: 1,
115-
Props: props,
116-
}
117-
}
118-
11986
// FindResourceGroupType looks up inside the list of available resource group types
12087
// the matching type from the provided string, if none, returns NoneResourceGroup
12188
func FindResourceGroupType(resourceGroup string) (ResourceGroupType, bool) {
@@ -200,24 +167,6 @@ func castResourceGroupResponse(data resourceGroupWorkaroundData, response interf
200167
return nil
201168
}
202169

203-
func setResourceGroupResponse(response resourceGroupWorkaroundData) (ResourceGroupResponse, error) {
204-
isDefault, err := strconv.Atoi(response.IsDefault)
205-
if err != nil {
206-
return ResourceGroupResponse{}, err
207-
}
208-
return ResourceGroupResponse{
209-
Data: ResourceGroupData{
210-
Guid: response.Guid,
211-
IsDefault: isDefault,
212-
ResourceGuid: response.ResourceGuid,
213-
Name: response.Name,
214-
Type: response.Type,
215-
Enabled: response.Enabled,
216-
Props: response.Props,
217-
},
218-
}, nil
219-
}
220-
221170
func setResourceGroupsResponse(workaround resourceGroupsWorkaroundResponse) (ResourceGroupsResponse, error) {
222171
var data []ResourceGroupData
223172
for _, r := range workaround.Data {
@@ -250,9 +199,9 @@ func (svc *ResourceGroupsService) Delete(guid string) error {
250199
// To return a more specific Go struct of a Resource Group, use the proper
251200
// method such as GetContainerResourceGroup() where the function name is composed by:
252201
//
253-
// Get<Type>(guid)
202+
// Get<Type>(guid)
254203
//
255-
// Where <Type> is the Resource Group type.
204+
// Where <Type> is the Resource Group type.
256205
func (svc *ResourceGroupsService) Get(guid string, response interface{}) error {
257206
var rawResponse resourceGroupWorkaroundResponse
258207
err := svc.get(guid, &rawResponse)
@@ -290,11 +239,26 @@ func (group ResourceGroupData) ResourceGroupType() ResourceGroupType {
290239
}
291240

292241
func (group ResourceGroupData) ID() string {
293-
return group.ResourceGuid
242+
if !group.IsV2Group() {
243+
return group.ResourceGuid
244+
} else {
245+
return group.ResourceGroupGuid
246+
}
247+
}
248+
249+
func (group *ResourceGroupData) ResetRGV2Fields() {
250+
group.UpdatedBy = ""
251+
group.UpdatedTime = nil
252+
group.CreatedBy = ""
253+
group.CreatedTime = nil
254+
group.IsDefaultBoolean = nil
255+
group.IsOrg = nil
294256
}
295257

296258
func (group *ResourceGroupData) ResetResourceGUID() {
297259
group.ResourceGuid = ""
260+
group.ResourceGroupGuid = ""
261+
group.ResetRGV2Fields()
298262
}
299263

300264
func (group ResourceGroupData) Status() string {
@@ -304,6 +268,10 @@ func (group ResourceGroupData) Status() string {
304268
return "Disabled"
305269
}
306270

271+
func (group ResourceGroupData) IsV2Group() bool {
272+
return group.Query != nil
273+
}
274+
307275
type ResourceGroupResponse struct {
308276
Data ResourceGroupData `json:"data"`
309277
}
@@ -313,13 +281,26 @@ type ResourceGroupsResponse struct {
313281
}
314282

315283
type ResourceGroupData struct {
284+
// RGv1 Fields
316285
Guid string `json:"guid,omitempty"`
317286
IsDefault int `json:"isDefault,omitempty"`
318287
ResourceGuid string `json:"resourceGuid,omitempty"`
319-
Name string `json:"resourceName"`
288+
Name string `json:"resourceName,omitempty"`
320289
Type string `json:"resourceType"`
321-
Enabled int `json:"enabled,omitempty"`
322-
Props interface{} `json:"props"`
290+
Enabled int `json:"enabled"`
291+
Props interface{} `json:"props,omitempty"`
292+
293+
// RG v2 Fields. `Enabled` and `Type` fields are the same in RGv1 nd RGv2
294+
NameV2 string `json:"name,omitempty"`
295+
Query *RGQuery `json:"query,omitempty"`
296+
Description string `json:"description,omitempty"`
297+
ResourceGroupGuid string `json:"resourceGroupGuid,omitempty"`
298+
CreatedTime *time.Time `json:"lastUpdated,omitempty"`
299+
CreatedBy string `json:"createdBy,omitempty"`
300+
UpdatedTime *time.Time `json:"updatedTime,omitempty"`
301+
UpdatedBy string `json:"updatedBy,omitempty"`
302+
IsDefaultBoolean *bool `json:"isDefaultBoolean,omitempty"`
303+
IsOrg *bool `json:"isOrg,omitempty"`
323304
}
324305

325306
// RAIN-21510 workaround
@@ -339,4 +320,15 @@ type resourceGroupWorkaroundData struct {
339320
Type string `json:"resourceType"`
340321
Enabled int `json:"enabled,omitempty"`
341322
Props interface{} `json:"props"`
323+
324+
NameV2 string `json:"name,omitempty"`
325+
Query *RGQuery `json:"query,omitempty"`
326+
Description string `json:"description,omitempty"`
327+
ResourceGroupGuid string `json:"resourceGroupGuid,omitempty"`
328+
CreatedTime *time.Time `json:"lastUpdated,omitempty"`
329+
CreatedBy string `json:"createdBy,omitempty"`
330+
UpdatedTime *time.Time `json:"updatedTime,omitempty"`
331+
UpdatedBy string `json:"updatedBy,omitempty"`
332+
IsDefaultBoolean *bool `json:"isDefaultBoolean,omitempty"`
333+
IsOrg *bool `json:"isOrg,omitempty"`
342334
}

api/resource_groups_aws.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var (
3333

3434
// GetAws gets a single Aws ResourceGroup matching the
3535
// provided resource guid
36-
func (svc *ResourceGroupsService) GetAws(guid string) (
36+
func (svc *ResourceGroupsVersionService) GetAws(guid string) (
3737
response AwsResourceGroupResponse,
3838
err error,
3939
) {
@@ -47,8 +47,9 @@ func (svc *ResourceGroupsService) GetAws(guid string) (
4747
}
4848

4949
// UpdateAws updates a single Aws ResourceGroup on the Lacework Server
50-
func (svc *ResourceGroupsService) UpdateAws(data ResourceGroup) (
50+
func (svc *ResourceGroupsVersionService) UpdateAws(data ResourceGroup) (
5151
response AwsResourceGroupResponse, err error) {
52+
5253
if data == nil {
5354
err = errors.New("resource group must not be empty")
5455
return
@@ -65,7 +66,7 @@ func (svc *ResourceGroupsService) UpdateAws(data ResourceGroup) (
6566
}
6667

6768
// CreateAws creates a single Aws ResourceGroup on the Lacework Server
68-
func (svc *ResourceGroupsService) CreateAws(data ResourceGroup) (
69+
func (svc *ResourceGroupsVersionService) CreateAws(data ResourceGroup) (
6970
response AwsResourceGroupResponse,
7071
err error,
7172
) {
@@ -118,6 +119,17 @@ type AwsResourceGroupData struct {
118119
Type string `json:"resourceType"`
119120
Enabled int `json:"enabled,omitempty"`
120121
Props AwsResourceGroupProps `json:"props"`
122+
123+
NameV2 string `json:"name"`
124+
Query *RGQuery `json:"query"`
125+
Description string `json:"description,omitempty"`
126+
ResourceGroupGuid string `json:"resourceGroupGuid,omitempty"`
127+
CreatedTime *lwtime.Epoch `json:"lastUpdated,omitempty"`
128+
CreatedBy string `json:"createdBy,omitempty"`
129+
UpdatedTime *lwtime.Epoch `json:"updatedTime,omitempty"`
130+
UpdatedBy string `json:"updatedBy,omitempty"`
131+
IsDefaultBoolean *bool `json:"isDefaultBoolean,omitempty"`
132+
IsOrg *bool `json:"isOrg,omitempty"`
121133
}
122134

123135
type AwsResourceGroupProps struct {

api/resource_groups_azure.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var (
3333

3434
// GetAzure gets a single Azure ResourceGroup matching the
3535
// provided resource guid
36-
func (svc *ResourceGroupsService) GetAzure(guid string) (
36+
func (svc *ResourceGroupsVersionService) GetAzure(guid string) (
3737
response AzureResourceGroupResponse,
3838
err error,
3939
) {
@@ -47,7 +47,7 @@ func (svc *ResourceGroupsService) GetAzure(guid string) (
4747
}
4848

4949
// UpdateAzure updates a single Azure ResourceGroup on the Lacework Server
50-
func (svc *ResourceGroupsService) UpdateAzure(data ResourceGroup) (
50+
func (svc *ResourceGroupsVersionService) UpdateAzure(data ResourceGroup) (
5151
response AzureResourceGroupResponse,
5252
err error,
5353
) {
@@ -67,7 +67,7 @@ func (svc *ResourceGroupsService) UpdateAzure(data ResourceGroup) (
6767
}
6868

6969
// CreateAzure creates a single Azure ResourceGroup on the Lacework Server
70-
func (svc *ResourceGroupsService) CreateAzure(data ResourceGroup) (
70+
func (svc *ResourceGroupsVersionService) CreateAzure(data ResourceGroup) (
7171
response AzureResourceGroupResponse,
7272
err error,
7373
) {

api/resource_groups_container.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var (
3434

3535
// GetContainer gets a single Container ResourceGroup matching the
3636
// provided resource guid
37-
func (svc *ResourceGroupsService) GetContainer(guid string) (
37+
func (svc *ResourceGroupsVersionService) GetContainer(guid string) (
3838
response ContainerResourceGroupResponse,
3939
err error,
4040
) {
@@ -48,7 +48,7 @@ func (svc *ResourceGroupsService) GetContainer(guid string) (
4848
}
4949

5050
// UpdateContainer updates a single Container ResourceGroup on the Lacework Server
51-
func (svc *ResourceGroupsService) UpdateContainer(data ResourceGroup) (
51+
func (svc *ResourceGroupsVersionService) UpdateContainer(data ResourceGroup) (
5252
response ContainerResourceGroupResponse,
5353
err error,
5454
) {
@@ -64,7 +64,7 @@ func (svc *ResourceGroupsService) UpdateContainer(data ResourceGroup) (
6464
}
6565

6666
// CreateContainer creates a single Container ResourceGroup on the Lacework Server
67-
func (svc *ResourceGroupsService) CreateContainer(data ResourceGroup) (
67+
func (svc *ResourceGroupsVersionService) CreateContainer(data ResourceGroup) (
6868
response ContainerResourceGroupResponse,
6969
err error,
7070
) {

0 commit comments

Comments
 (0)