From 0c1cc05b1c29c5abc81a872ba2441f51652cb50d Mon Sep 17 00:00:00 2001 From: Salim Afiune Maya Date: Thu, 24 Jun 2021 12:38:16 -0700 Subject: [PATCH] refactor: use V2 CloudAccounts for integration_aws_ct resource Signed-off-by: Salim Afiune Maya --- lacework/integration_importer.go | 18 +- .../resource_lacework_integration_aws_ct.go | 247 ++++++++---------- 2 files changed, 128 insertions(+), 137 deletions(-) diff --git a/lacework/integration_importer.go b/lacework/integration_importer.go index f92daaff..df10d1e6 100644 --- a/lacework/integration_importer.go +++ b/lacework/integration_importer.go @@ -25,9 +25,17 @@ func importLaceworkIntegration(d *schema.ResourceData, meta interface{}) ([]*sch } } - log.Printf("[INFO] Raw integration response: %v\n", response) - return nil, fmt.Errorf( - "Unable to import Lacework resource. Integration with guid '%s' was not found.", - d.Id(), - ) + log.Printf("[INFO] Raw APIv1 integration response: %v\n", response) + + log.Println("[WARN] Trying APIv2") + cloudAccount, err := lacework.V2.CloudAccounts.Get(d.Id()) + if err != nil { + return nil, fmt.Errorf( + "Unable to import Lacework resource. Integration with guid '%s' was not found.", + d.Id(), + ) + } + log.Printf("[INFO] Cloud account integration found using APIv2 with guid: %v\n", cloudAccount.Data.IntgGuid) + return []*schema.ResourceData{d}, nil + } diff --git a/lacework/resource_lacework_integration_aws_ct.go b/lacework/resource_lacework_integration_aws_ct.go index bedfb094..1c421e3e 100644 --- a/lacework/resource_lacework_integration_aws_ct.go +++ b/lacework/resource_lacework_integration_aws_ct.go @@ -123,78 +123,70 @@ func resourceLaceworkIntegrationAwsCloudTrail() *schema.Resource { func resourceLaceworkIntegrationAwsCloudTrailCreate(d *schema.ResourceData, meta interface{}) error { var ( - lacework = meta.(*api.Client) - retries = d.Get("retries").(int) - aws = api.NewAwsIntegration(d.Get("name").(string), - api.AwsCloudTrailIntegration, - api.AwsIntegrationData{ - QueueUrl: d.Get("queue_url").(string), - Credentials: &api.AwsCrossAccountCreds{ - RoleArn: d.Get("credentials.0.role_arn").(string), - ExternalID: d.Get("credentials.0.external_id").(string), - }, + lacework = meta.(*api.Client) + retries = d.Get("retries").(int) + awsCtSqsData = api.AwsCtSqsData{ + QueueUrl: d.Get("queue_url").(string), + Credentials: api.AwsCtSqsCredentials{ + RoleArn: d.Get("credentials.0.role_arn").(string), + ExternalID: d.Get("credentials.0.external_id").(string), }, - ) + } ) - if !d.Get("enabled").(bool) { - aws.Enabled = 0 - } - // verify if the user provided an account mapping accountMapFile := getResourceOrgAccountMappings(d) - accountMapFileBytes, err := json.Marshal(accountMapFile) - if err != nil { - return err + if !accountMapFile.Empty() { + accountMapFileBytes, err := json.Marshal(accountMapFile) + if err != nil { + return err + } + + awsCtSqsData.EncodeAccountMappingFile(accountMapFileBytes) } - if !accountMapFile.Empty() { - aws.Data.EncodeAccountMappingFile(accountMapFileBytes) + awsCtSqs := api.NewCloudAccount(d.Get("name").(string), + api.AwsCtSqsCloudAccount, + awsCtSqsData, + ) - // switch this integration to be at the organization level - aws.IsOrg = 1 + if !d.Get("enabled").(bool) { + awsCtSqs.Enabled = 0 } return resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { retries-- - log.Printf("[INFO] Creating %s integration\n", api.AwsCloudTrailIntegration.String()) - response, err := lacework.Integrations.CreateAws(aws) + log.Printf("[INFO] Creating %s cloud account integration\n", api.AwsCtSqsCloudAccount.String()) + response, err := lacework.V2.CloudAccounts.Create(awsCtSqs) if err != nil { if retries <= 0 { return resource.NonRetryableError( - fmt.Errorf("Error creating %s integration: %s", - api.AwsCloudTrailIntegration.String(), err, + fmt.Errorf("Error creating %s cloud account integration: %s", + api.AwsCtSqsCloudAccount.String(), err, )) } log.Printf( - "[INFO] Unable to create %s integration. (retrying %d more time(s))\n%s\n", - api.AwsCloudTrailIntegration.String(), retries, err, + "[INFO] Unable to create %s cloud account integration. (retrying %d more time(s))\n%s\n", + api.AwsCtSqsCloudAccount.String(), retries, err, ) return resource.RetryableError(fmt.Errorf( - "Unable to create %s integration (retrying %d more time(s))", - api.AwsCloudTrailIntegration.String(), retries, + "Unable to create %s cloud account integration (retrying %d more time(s))", + api.AwsCtSqsCloudAccount.String(), retries, )) } - log.Println("[INFO] Verifying server response data") - err = validateAwsIntegrationResponse(&response) - if err != nil { - return resource.NonRetryableError(err) - } + cloudAccount := response.Data + d.SetId(cloudAccount.IntgGuid) + d.Set("name", cloudAccount.Name) + d.Set("intg_guid", cloudAccount.IntgGuid) + d.Set("enabled", cloudAccount.Enabled == 1) - // @afiune at this point of time, we know the data field has a single value - integration := response.Data[0] - d.SetId(integration.IntgGuid) - d.Set("name", integration.Name) - d.Set("intg_guid", integration.IntgGuid) - d.Set("enabled", integration.Enabled == 1) + d.Set("created_or_updated_time", cloudAccount.CreatedOrUpdatedTime) + d.Set("created_or_updated_by", cloudAccount.CreatedOrUpdatedBy) + d.Set("type_name", cloudAccount.Type) // @afiune should we deprecate? + d.Set("org_level", cloudAccount.IsOrg == 1) - d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime) - d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy) - d.Set("type_name", integration.TypeName) - d.Set("org_level", integration.IsOrg == 1) - - log.Printf("[INFO] Created %s integration with guid: %v\n", - api.AwsCloudTrailIntegration.String(), integration.IntgGuid) + log.Printf("[INFO] Created %s cloud account integration with guid: %v\n", + api.AwsCtSqsCloudAccount.String(), cloudAccount.IntgGuid) return nil }) } @@ -202,55 +194,54 @@ func resourceLaceworkIntegrationAwsCloudTrailCreate(d *schema.ResourceData, meta func resourceLaceworkIntegrationAwsCloudTrailRead(d *schema.ResourceData, meta interface{}) error { lacework := meta.(*api.Client) - log.Printf("[INFO] Reading %s integration with guid: %v\n", api.AwsCloudTrailIntegration.String(), d.Id()) - response, err := lacework.Integrations.GetAws(d.Id()) + log.Printf("[INFO] Reading %s cloud account integration with guid: %v\n", api.AwsCtSqsCloudAccount.String(), d.Id()) + response, err := lacework.V2.CloudAccounts.GetAwsCtSqs(d.Id()) if err != nil { return err } - for _, integration := range response.Data { - if integration.IntgGuid == d.Id() { - d.Set("name", integration.Name) - d.Set("intg_guid", integration.IntgGuid) - d.Set("enabled", integration.Enabled == 1) - d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime) - d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy) - d.Set("type_name", integration.TypeName) - d.Set("org_level", integration.IsOrg == 1) - - creds := make(map[string]string) - credentials := integration.Data.GetCredentials() - creds["role_arn"] = credentials.RoleArn - creds["external_id"] = credentials.ExternalID - d.Set("credentials", []map[string]string{creds}) - d.Set("queue_url", integration.Data.QueueUrl) - - accountMapFileBytes, err := integration.Data.DecodeAccountMappingFile() - if err != nil { - return err - } - - accountMapFile := new(accountMappingsFile) - if len(accountMapFileBytes) != 0 { - // The integration has an account mapping file - // unmarshal its content into the account mapping struct - err := json.Unmarshal(accountMapFileBytes, accountMapFile) - if err != nil { - return fmt.Errorf("Error decoding organization account mapping: %s", err) - } - - } + cloudAccount := response.Data + if cloudAccount.IntgGuid == d.Id() { + d.Set("name", cloudAccount.Name) + d.Set("intg_guid", cloudAccount.IntgGuid) + d.Set("enabled", cloudAccount.Enabled == 1) + d.Set("created_or_updated_time", cloudAccount.CreatedOrUpdatedTime) + d.Set("created_or_updated_by", cloudAccount.CreatedOrUpdatedBy) + d.Set("type_name", cloudAccount.Type) + d.Set("org_level", cloudAccount.IsOrg == 1) + + creds := make(map[string]string) + credentials := cloudAccount.Data.Credentials + creds["role_arn"] = credentials.RoleArn + creds["external_id"] = credentials.ExternalID + d.Set("credentials", []map[string]string{creds}) + d.Set("queue_url", cloudAccount.Data.QueueUrl) + + accountMapFileBytes, err := cloudAccount.Data.DecodeAccountMappingFile() + if err != nil { + return err + } - err = d.Set("org_account_mappings", flattenOrgAccountMappings(accountMapFile)) + accountMapFile := new(accountMappingsFile) + if len(accountMapFileBytes) != 0 { + // The integration has an account mapping file + // unmarshal its content into the account mapping struct + err := json.Unmarshal(accountMapFileBytes, accountMapFile) if err != nil { - return fmt.Errorf("Error flattening organization account mapping: %s", err) + return fmt.Errorf("Error decoding organization account mapping: %s", err) } - log.Printf("[INFO] Read %s integration with guid: %v\n", - api.AwsCloudTrailIntegration.String(), integration.IntgGuid, - ) - return nil } + + err = d.Set("org_account_mappings", flattenOrgAccountMappings(accountMapFile)) + if err != nil { + return fmt.Errorf("Error flattening organization account mapping: %s", err) + } + + log.Printf("[INFO] Read %s cloud account integration with guid: %v\n", + api.AwsCtSqsCloudAccount.String(), cloudAccount.IntgGuid, + ) + return nil } d.SetId("") @@ -259,75 +250,67 @@ func resourceLaceworkIntegrationAwsCloudTrailRead(d *schema.ResourceData, meta i func resourceLaceworkIntegrationAwsCloudTrailUpdate(d *schema.ResourceData, meta interface{}) error { var ( - lacework = meta.(*api.Client) - aws = api.NewAwsIntegration(d.Get("name").(string), - api.AwsCloudTrailIntegration, - api.AwsIntegrationData{ - QueueUrl: d.Get("queue_url").(string), - Credentials: &api.AwsCrossAccountCreds{ - RoleArn: d.Get("credentials.0.role_arn").(string), - ExternalID: d.Get("credentials.0.external_id").(string), - }, + lacework = meta.(*api.Client) + awsCtSqsData = api.AwsCtSqsData{ + QueueUrl: d.Get("queue_url").(string), + Credentials: api.AwsCtSqsCredentials{ + RoleArn: d.Get("credentials.0.role_arn").(string), + ExternalID: d.Get("credentials.0.external_id").(string), }, - ) + } ) - if !d.Get("enabled").(bool) { - aws.Enabled = 0 - } - - aws.IntgGuid = d.Id() - // verify if the user provided an account mapping accountMapFile := getResourceOrgAccountMappings(d) - accountMapFileBytes, err := json.Marshal(accountMapFile) - if err != nil { - return err - } - if !accountMapFile.Empty() { - aws.Data.EncodeAccountMappingFile(accountMapFileBytes) + accountMapFileBytes, err := json.Marshal(accountMapFile) + if err != nil { + return err + } - // switch this integration to be at the organization level - aws.IsOrg = 1 + awsCtSqsData.EncodeAccountMappingFile(accountMapFileBytes) } - log.Printf("[INFO] Updating %s integration with data:\n%+v\n", api.AwsCloudTrailIntegration.String(), aws) - response, err := lacework.Integrations.UpdateAws(aws) - if err != nil { - return err + awsCtSqs := api.NewCloudAccount(d.Get("name").(string), + api.AwsCtSqsCloudAccount, + awsCtSqsData, + ) + + if !d.Get("enabled").(bool) { + awsCtSqs.Enabled = 0 } - log.Println("[INFO] Verifying server response data") - err = validateAwsIntegrationResponse(&response) + awsCtSqs.IntgGuid = d.Id() + + log.Printf("[INFO] Updating %s integration with data:\n%+v\n", api.AwsCtSqsCloudAccount.String(), awsCtSqs.IntgGuid) + response, err := lacework.V2.CloudAccounts.UpdateAwsCtSqs(awsCtSqs) if err != nil { return err } - // @afiune at this point of time, we know the data field has a single value - integration := response.Data[0] - d.Set("name", integration.Name) - d.Set("intg_guid", integration.IntgGuid) - d.Set("enabled", integration.Enabled == 1) - d.Set("created_or_updated_time", integration.CreatedOrUpdatedTime) - d.Set("created_or_updated_by", integration.CreatedOrUpdatedBy) - d.Set("type_name", integration.TypeName) - d.Set("org_level", integration.IsOrg == 1) - - log.Printf("[INFO] Updated %s integration with guid: %v\n", api.AwsCloudTrailIntegration.String(), d.Id()) + cloudAccount := response.Data + d.Set("name", cloudAccount.Name) + d.Set("intg_guid", cloudAccount.IntgGuid) + d.Set("enabled", cloudAccount.Enabled == 1) + d.Set("created_or_updated_time", cloudAccount.CreatedOrUpdatedTime) + d.Set("created_or_updated_by", cloudAccount.CreatedOrUpdatedBy) + d.Set("type_name", cloudAccount.Type) + d.Set("org_level", cloudAccount.IsOrg == 1) + + log.Printf("[INFO] Updated %s cloud account integration with guid: %v\n", api.AwsCtSqsCloudAccount.String(), d.Id()) return nil } func resourceLaceworkIntegrationAwsCloudTrailDelete(d *schema.ResourceData, meta interface{}) error { lacework := meta.(*api.Client) - log.Printf("[INFO] Deleting %s integration with guid: %v\n", api.AwsCloudTrailIntegration.String(), d.Id()) - _, err := lacework.Integrations.DeleteAws(d.Id()) + log.Printf("[INFO] Deleting %s cloud account integration with guid: %v\n", api.AwsCtSqsCloudAccount.String(), d.Id()) + err := lacework.V2.CloudAccounts.Delete(d.Id()) if err != nil { return err } - log.Printf("[INFO] Deleted %s integration with guid: %v\n", api.AwsCloudTrailIntegration.String(), d.Id()) + log.Printf("[INFO] Deleted %s cloud account integration with guid: %v\n", api.AwsCtSqsCloudAccount.String(), d.Id()) return nil }