From 7765084565143768f10be8519e0712b5b72d9168 Mon Sep 17 00:00:00 2001 From: Zeki Sherif Date: Wed, 2 Aug 2023 13:31:46 -0400 Subject: [PATCH] feat: Add List support --- api/resource_groups.go | 35 ------- api/resource_groups_v2.go | 9 -- api/resource_groups_version_service.go | 136 +++++++++++++++++++------ api/v2.go | 6 +- cli/cmd/alert_rules.go | 2 +- cli/cmd/report_distributions_create.go | 2 +- cli/cmd/report_distributions_update.go | 2 +- 7 files changed, 112 insertions(+), 80 deletions(-) diff --git a/api/resource_groups.go b/api/resource_groups.go index 53b7cd4ab..340afc159 100644 --- a/api/resource_groups.go +++ b/api/resource_groups.go @@ -81,41 +81,6 @@ func (i ResourceGroupType) String() string { return ResourceGroupTypes[i] } -// NewResourceGroup returns an instance of the ResourceGroupData struct with the -// provided ResourceGroup type, name and the props field as an interface{}. -// -// NOTE: This function must be used by any ResourceGroup type. -// -// Basic usage: Initialize a new ContainerResourceGroup struct, then -// use the new instance to do CRUD operations -// -// client, err := api.NewClient("account") -// if err != nil { -// return err -// } -// -// group := api.NewResourceGroup("container resource group", -// api.ContainerResourceGroup, -// api.ContainerResourceGroupData{ -// Props: api.ContainerResourceGroupProps{ -// Description: "all containers, -// ContainerLabels: ContainerResourceGroupAllLabels, -// ContainerTags: ContainerResourceGroupAllTags, -// }, -// }, -// ) -// -// client.V2.ResourceGroups.Create(group) -// -func NewResourceGroup(name string, iType ResourceGroupType, props interface{}) ResourceGroupData { - return ResourceGroupData{ - Name: name, - Type: iType.String(), - Enabled: 1, - Props: props, - } -} - // FindResourceGroupType looks up inside the list of available resource group types // the matching type from the provided string, if none, returns NoneResourceGroup func FindResourceGroupType(resourceGroup string) (ResourceGroupType, bool) { diff --git a/api/resource_groups_v2.go b/api/resource_groups_v2.go index 5810876ae..974c5b82c 100644 --- a/api/resource_groups_v2.go +++ b/api/resource_groups_v2.go @@ -6,15 +6,6 @@ import ( "github.com/pkg/errors" ) -func NewResourceGroupV2(name string, iType ResourceGroupType, query *RGQuery) ResourceGroupV2Data { - return ResourceGroupV2Data{ - Name: name, - Type: iType.String(), - Enabled: 1, - Query: query, - } -} - func (svc *ResourceGroupsV2Service) List() (response ResourceGroupsResponse, err error) { var rawResponse ResourceGroupsV2Response err = svc.client.RequestDecoder("GET", apiV2ResourceGroups, nil, &rawResponse) diff --git a/api/resource_groups_version_service.go b/api/resource_groups_version_service.go index d16548255..98d001142 100644 --- a/api/resource_groups_version_service.go +++ b/api/resource_groups_version_service.go @@ -1,22 +1,20 @@ package api -import ( -"encoding/json" -"github.com/lacework/go-sdk/lwtime" -"github.com/pkg/errors" +import ( + "encoding/json" + "github.com/lacework/go-sdk/lwtime" + "github.com/pkg/errors" ) - - type ResourceGroupsVersionService struct { - client *Client - v1ResourceGroupService *ResourceGroupsService - v2ResourceGroupService *ResourceGroupsV2Service - featureFlagService *FeatureFlagsService + client *Client + v1ResourceGroupService *ResourceGroupsService + v2ResourceGroupService *ResourceGroupsV2Service + featureFlagService *FeatureFlagsService } func NewResourceGroupsVersionService(c *Client) *ResourceGroupsVersionService { - return &ResourceGroupsVersionService { + return &ResourceGroupsVersionService{ c, &ResourceGroupsService{c}, &ResourceGroupsV2Service{c}, @@ -24,6 +22,50 @@ func NewResourceGroupsVersionService(c *Client) *ResourceGroupsVersionService { } } +// NewResourceGroup returns an instance of the ResourceGroupData struct with the +// provided ResourceGroup type, name and the props field as an interface{}. +// +// NOTE: This function must be used by any ResourceGroup type. +// +// Basic usage: Initialize a new ContainerResourceGroup struct, then +// use the new instance to do CRUD operations +// +// client, err := api.NewClient("account") +// if err != nil { +// return err +// } +// +// group := api.NewResourceGroup("container resource group", +// api.ContainerResourceGroup, +// api.ContainerResourceGroupData{ +// Props: api.ContainerResourceGroupProps{ +// Description: "all containers, +// ContainerLabels: ContainerResourceGroupAllLabels, +// ContainerTags: ContainerResourceGroupAllTags, +// }, +// }, +// ) +// +// client.V2.ResourceGroups.Create(group) +// +func NewResourceGroup(name string, iType ResourceGroupType, props interface{}) ResourceGroupVersionUnawareData { + return ResourceGroupVersionUnawareData{ + Name: name, + Type: iType.String(), + Enabled: 1, + Props: props, + } +} + +func NewResourceGroupWithQuery(name string, iType ResourceGroupType, query *RGQuery) ResourceGroupVersionUnawareData { + return ResourceGroupVersionUnawareData{ + Name: name, + Type: iType.String(), + Enabled: 1, + Query: query, + } +} + func isRGV2FlagEnabled(featureFlagService *FeatureFlagsService) (bool, error) { response, err := featureFlagService.GetFeatureFlagsMatchingPrefix("PUBLIC.rgv2.cli") @@ -38,6 +80,10 @@ type ResourceGroupVersionUnawareResponse struct { Data ResourceGroupVersionUnawareData `json:"data"` } +type ResourceGroupsVersionUnawareResponse struct { + Data []ResourceGroupVersionUnawareData `json:"data"` +} + type ResourceGroupVersionUnawareData struct { // RGv1 Fields Guid string `json:"guid,omitempty"` @@ -49,7 +95,7 @@ type ResourceGroupVersionUnawareData struct { Props interface{} `json:"props,omitempty"` // RG v2 Fields. `Enabled` and `Type` fields are the same in RGv1 nd RGv2 - NameV2 string `json:"name,omitempty"` + NameV2 string `json:"name,omitempty"` Query *RGQuery `json:"query,omitempty"` Description string `json:"description,omitempty"` ResourceGroupGuid string `json:"resourceGroupGuid,omitempty"` @@ -62,7 +108,7 @@ type ResourceGroupVersionUnawareData struct { } func castResourceGroupV1Response(data ResourceGroupResponse, response interface{}) error { - group := ResourceGroupVersionUnawareResponse { + group := ResourceGroupVersionUnawareResponse{ Data: ResourceGroupVersionUnawareData{ Guid: data.Data.Guid, IsDefault: data.Data.IsDefault, @@ -75,9 +121,9 @@ func castResourceGroupV1Response(data ResourceGroupResponse, response interface{ } j, err := json.Marshal(group) - if err != nil { - return err - } + if err != nil { + return err + } err = json.Unmarshal(j, &response) if err != nil { @@ -88,20 +134,20 @@ func castResourceGroupV1Response(data ResourceGroupResponse, response interface{ } func castResourceGroupV2Response(data ResourceGroupV2Response, response interface{}) error { - group := ResourceGroupVersionUnawareResponse { + group := ResourceGroupVersionUnawareResponse{ Data: ResourceGroupVersionUnawareData{ - Type: data.Data.Type, - Enabled: data.Data.Enabled, - NameV2: data.Data.Name, - Query: data.Data.Query, - Description: data.Data.Description, + Type: data.Data.Type, + Enabled: data.Data.Enabled, + NameV2: data.Data.Name, + Query: data.Data.Query, + Description: data.Data.Description, ResourceGroupGuid: data.Data.ResourceGroupGuid, - CreatedTime: data.Data.CreatedTime, - CreatedBy: data.Data.CreatedBy, - UpdatedTime: data.Data.UpdatedTime, - UpdatedBy: data.Data.UpdatedBy, - IsDefaultBoolean: data.Data.IsDefaultBoolean, - IsOrg: data.Data.IsOrg, + CreatedTime: data.Data.CreatedTime, + CreatedBy: data.Data.CreatedBy, + UpdatedTime: data.Data.UpdatedTime, + UpdatedBy: data.Data.UpdatedBy, + IsDefaultBoolean: data.Data.IsDefaultBoolean, + IsOrg: data.Data.IsOrg, }, } @@ -272,7 +318,6 @@ func (svc *ResourceGroupsVersionService) Update(group ResourceGroupVersionUnawar return } - err = errors.New("Unable to update resource group") return } @@ -296,4 +341,35 @@ func (svc *ResourceGroupsVersionService) Delete(guid string) error { } return nil -} \ No newline at end of file +} + +// ListV1 returns a list of Resource Groups v1 +// We need this temporary function to only get v1 RGs for alerting. RGv2 not supported in AlertRules/ReportRules yet. +func (svc *ResourceGroupsVersionService) ListV1() (response ResourceGroupsResponse, err error) { + var allGroupsResponse ResourceGroupsVersionUnawareResponse + err = svc.client.RequestDecoder("GET", apiV2ResourceGroups, nil, &allGroupsResponse) + + if err != nil { + return + } + + var v1ResourceGroups []ResourceGroupData + + for _, group := range allGroupsResponse.Data { + if group.Query == nil { + var resourceGroupV1Data ResourceGroupData + err = transformToResourceGroupVersionAwareObject(group, &resourceGroupV1Data) + if err != nil { + return + } + v1ResourceGroups = append(v1ResourceGroups, resourceGroupV1Data) + } + } + + response.Data = v1ResourceGroups + return +} +func (svc *ResourceGroupsVersionService) List() (response ResourceGroupsVersionUnawareResponse, err error) { + err = svc.client.RequestDecoder("GET", apiV2ResourceGroups, nil, &response) + return +} diff --git a/api/v2.go b/api/v2.go index 5fc2a5b17..f7f5e24d0 100644 --- a/api/v2.go +++ b/api/v2.go @@ -42,7 +42,7 @@ type V2Endpoints struct { ContainerRegistries *ContainerRegistriesService Configs *v2ConfigService FeatureFlags *FeatureFlagsService - ResourceGroups *ResourceGroupsService + ResourceGroups *ResourceGroupsVersionService AgentAccessTokens *AgentAccessTokensService AgentInfo *AgentInfoService Inventory *InventoryService @@ -77,7 +77,7 @@ func NewV2Endpoints(c *Client) *V2Endpoints { &ContainerRegistriesService{c}, NewV2ConfigService(c), &FeatureFlagsService{c}, - &ResourceGroupsService{c}, + NewResourceGroupsVersionService(c), &AgentAccessTokensService{c}, &AgentInfoService{c}, &InventoryService{c}, @@ -113,7 +113,7 @@ func NewV2Endpoints(c *Client) *V2Endpoints { AlertRules: &AlertRulesService{c}, CloudAccounts: &CloudAccountsService{c}, ContainerRegistries: &ContainerRegistriesService{c}, - ResourceGroups: NewResourceGroupsVersionService(c), + ResourceGroups: &ResourceGroupsService{c}, TeamMembers: &TeamMembersService{c}, ReportRules: &ReportRulesService{c}, VulnerabilityExceptions: &VulnerabilityExceptionsService{c}, diff --git a/cli/cmd/alert_rules.go b/cli/cmd/alert_rules.go index d9a02eb7e..f9fda9f7d 100644 --- a/cli/cmd/alert_rules.go +++ b/cli/cmd/alert_rules.go @@ -330,7 +330,7 @@ func getAlertChannels() ([]string, map[string]string) { func getResourceGroups() ([]string, map[string]string) { cli.StartProgress("") defer cli.StopProgress() - response, err := cli.LwApi.V2.ResourceGroups.List() + response, err := cli.LwApi.V2.ResourceGroups.ListV1() if err != nil { return nil, nil diff --git a/cli/cmd/report_distributions_create.go b/cli/cmd/report_distributions_create.go index 5b8af9b22..54b400ea1 100644 --- a/cli/cmd/report_distributions_create.go +++ b/cli/cmd/report_distributions_create.go @@ -195,7 +195,7 @@ func promptReportDistributionScope(distribution *api.ReportDistribution, subRepo func promptReportDistributionResourceGroup(distribution *api.ReportDistribution) error { cli.StartProgress("Fetching list of resource groups...") - resourceGroups, err := cli.LwApi.V2.ResourceGroups.List() + resourceGroups, err := cli.LwApi.V2.ResourceGroups.ListV1() cli.StopProgress() if err != nil { return err diff --git a/cli/cmd/report_distributions_update.go b/cli/cmd/report_distributions_update.go index cc2020e5c..ac62decba 100644 --- a/cli/cmd/report_distributions_update.go +++ b/cli/cmd/report_distributions_update.go @@ -208,7 +208,7 @@ func promptUpdateReportDistributionResourceGroup( distribution *api.ReportDistributionUpdate, existing api.ReportDistribution, ) error { cli.StartProgress("Fetching list of resource groups...") - resourceGroups, err := cli.LwApi.V2.ResourceGroups.List() + resourceGroups, err := cli.LwApi.V2.ResourceGroups.ListV1() cli.StopProgress() if err != nil { return err