Skip to content

Commit

Permalink
refactor: use V2 CloudAccounts for integration_aws_ct resource
Browse files Browse the repository at this point in the history
Signed-off-by: Salim Afiune Maya <afiune@lacework.net>
  • Loading branch information
afiune committed Jun 24, 2021
1 parent e4aa1da commit 0c1cc05
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 137 deletions.
18 changes: 13 additions & 5 deletions lacework/integration_importer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

}
247 changes: 115 additions & 132 deletions lacework/resource_lacework_integration_aws_ct.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,134 +123,125 @@ 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
})
}

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("")
Expand All @@ -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
}

Expand Down

0 comments on commit 0c1cc05

Please sign in to comment.