diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 536cede6..df3d86ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,4 +45,5 @@ jobs: OCI_TENANCY_ID: ${{ secrets.OCI_TENANCY_ID }} OCI_HOME_REGION: ${{ secrets.OCI_HOME_REGION }} OCI_USER_OCID: ${{ secrets.OCI_USER_OCID }} + AWP_EXTERNAL_ID: ${{ secrets.AWP_EXTERNAL_ID }} run: go test -v -timeout 2400s ./... \ No newline at end of file diff --git a/dome9/common/providerconst/const.go b/dome9/common/providerconst/const.go index a59ba93d..8791928b 100644 --- a/dome9/common/providerconst/const.go +++ b/dome9/common/providerconst/const.go @@ -109,13 +109,13 @@ const ( AF_SOUTH_1 = "26" EU_SOUTH_1 = "27" AP_NORTHEAST_3 = "28" - ME_CENTRAL_1 = "29" - AP_SOUTH_2 = "30" - AP_SOUTHEAST_3 = "31" - AP_SOUTHEAST_4 = "32" - EU_CENTRAL_2 = "33" - EU_SOUTH_2 = "34" - IL_CENTRAL_1 = "35" + ME_CENTRAL_1 = "29" + AP_SOUTH_2 = "30" + AP_SOUTHEAST_3 = "31" + AP_SOUTHEAST_4 = "32" + EU_CENTRAL_2 = "33" + EU_SOUTH_2 = "34" + IL_CENTRAL_1 = "35" ) // Azure consts @@ -185,11 +185,11 @@ var AWSRegionsEnum = map[string]string{ "af_south_1": AF_SOUTH_1, "eu_south_1": EU_SOUTH_1, "ap_northeast_3": AP_NORTHEAST_3, - "me_central_1": ME_CENTRAL_1, - "ap_south_2": AP_SOUTH_2, - "ap_southeast_3": AP_SOUTHEAST_3, - "ap_southeast_4": AP_SOUTHEAST_4, - "eu_central_2": EU_CENTRAL_2, + "me_central_1": ME_CENTRAL_1, + "ap_south_2": AP_SOUTH_2, + "ap_southeast_3": AP_SOUTHEAST_3, + "ap_southeast_4": AP_SOUTHEAST_4, + "eu_central_2": EU_CENTRAL_2, "eu_south_2": EU_SOUTH_2, "il_central_1": IL_CENTRAL_1, } @@ -201,3 +201,12 @@ var PermissionTrafficType = map[string]string{ // All Assessments Cloud Accounts Types var AssessmentCloudAccountType = []string{"Aws", "Azure", "GCP", "Kubernetes", "Terraform", "Generic", "KubernetesRuntimeAssurance", "ShiftLeft", "SourceCodeAssurance", "ImageAssurance", "Alibaba", "Cft", "ContainerRegistry", "Ers"} + +// AWP AWS Constants +const ( + DefaultScanMachineIntervalInHoursSaas = 24 + DefaultScanMachineIntervalInHoursInAccount = 4 + DefaultMaxConcurrentScansPerRegion = 20 + MinMaxConcurrentScansPerRegion = 1 + MaxScanMachineIntervalInHours = 1000 +) diff --git a/dome9/common/resourcetype/resource_type.go b/dome9/common/resourcetype/resource_type.go index da5b1887..40817ead 100644 --- a/dome9/common/resourcetype/resource_type.go +++ b/dome9/common/resourcetype/resource_type.go @@ -27,4 +27,6 @@ const ( AdmissionControlPolicy = "dome9_admission_control_policy" Assessment = "dome9_assessment" ImageAssurancePolicy = "dome9_image_assurance_policy" + AwpAwsOnboardingData = "dome9_awp_aws_onboarding_data" + AwpAwsOnboarding = "dome9_awp_aws_onboarding" ) diff --git a/dome9/common/testing/environmentvariable/environment_variable.go b/dome9/common/testing/environmentvariable/environment_variable.go index e1f02f87..fc708e39 100644 --- a/dome9/common/testing/environmentvariable/environment_variable.go +++ b/dome9/common/testing/environmentvariable/environment_variable.go @@ -20,9 +20,10 @@ const ( // AWS environment variable const ( - CloudAccountAWSEnvVarArn = "ARN" - CloudAccountUpdatedAWSEnvVarArn = "ARN_UPDATE" - CloudAccountAWSEnvVarSecret = "SECRET" + CloudAccountAWSEnvVarArn = "ARN" + CloudAccountUpdatedAWSEnvVarArn = "ARN_UPDATE" + CloudAccountAWSEnvVarSecret = "SECRET" + AwpAwsCrossAccountRoleExternalIdEnvVar = "AWP_EXTERNAL_ID" ) // Azure environment variable diff --git a/dome9/common/testing/variable/variable.go b/dome9/common/testing/variable/variable.go index 39ce5b3b..fbdedc97 100644 --- a/dome9/common/testing/variable/variable.go +++ b/dome9/common/testing/variable/variable.go @@ -211,3 +211,25 @@ const ( HasErrors = "false" HasDataSyncStatusIssues = "false" ) + +// awp aws onboarding data resource/data source +const ( + OnboardedAwsCloudGuardAccountID = "36f79243-5456-4aa7-88c1-6637cad1f426" + AwpAwsCrossAccountRoleName = "CloudGuardAWPCrossAccountRole" + ScanMode = "inAccount" + DisabledRegions = `["us-east-1", "us-west-1"]` + DisabledRegionsUpdate = `["us-east-1", "us-west-1", "ap-northeast-1", "ap-southeast-2"]` + ScanMachineIntervalInHours = "6" + ScanMachineIntervalInHoursUpdate = "10" + MaxConcurrentScansPerRegion = "4" + MaxConcurrentScansPerRegionUpdate = "8" + CustomTags = `{ + tag1 = "value1" + tag2 = "value2" + }` + CustomTagsUpdate = `{ + tag1 = "value1" + tag2 = "value2" + tag3 = "value3" + }` +) diff --git a/dome9/config.go b/dome9/config.go index a41706be..08eac0e3 100644 --- a/dome9/config.go +++ b/dome9/config.go @@ -2,6 +2,7 @@ package dome9 import ( "github.com/dome9/dome9-sdk-go/services/assessment" + "github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding" "log" "github.com/dome9/dome9-sdk-go/dome9" @@ -52,6 +53,7 @@ type Client struct { admissionControlPolicy admission_policy.Service imageAssurancePolicy imageassurance_policy.Service assessment assessment.Service + awpAwsOnboarding awp_aws_onboarding.Service } type Config struct { @@ -87,6 +89,7 @@ func (c *Config) Client() (*Client, error) { admissionControlPolicy: *admission_policy.New(config), imageAssurancePolicy: *imageassurance_policy.New(config), assessment: *assessment.New(config), + awpAwsOnboarding: *awp_aws_onboarding.New(config), } log.Println("[INFO] initialized Dome9 client") diff --git a/dome9/data_source_dome9_assessment.go b/dome9/data_source_dome9_assessment.go index 26e3ff8c..5b915b17 100644 --- a/dome9/data_source_dome9_assessment.go +++ b/dome9/data_source_dome9_assessment.go @@ -8,7 +8,7 @@ import ( func dataSourceAssessment() *schema.Resource { return &schema.Resource{ - Read: dataSourceAssessmentRead, + Read: dataSourceAssessmentRead, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, @@ -31,7 +31,7 @@ func dataSourceAssessment() *schema.Resource { Computed: true, }, "cloud_account_type": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, "should_minimize_result": { @@ -720,4 +720,3 @@ func dataSourceAssessmentRead(d *schema.ResourceData, meta interface{}) error { return nil } - diff --git a/dome9/data_source_dome9_awp_aws_onboarding.go b/dome9/data_source_dome9_awp_aws_onboarding.go new file mode 100644 index 00000000..e38c2f12 --- /dev/null +++ b/dome9/data_source_dome9_awp_aws_onboarding.go @@ -0,0 +1,136 @@ +package dome9 + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "log" +) + +func dataSourceAwpAwsOnboarding() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwpAwsOnboardingRead, + + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Required: true, + }, + "scan_mode": { + Type: schema.TypeString, + Computed: true, + }, + "agentless_account_settings": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled_regions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "scan_machine_interval_in_hours": { + Type: schema.TypeInt, + Computed: true, + }, + "max_concurrent_scans_per_region": { + Type: schema.TypeInt, + Computed: true, + }, + "custom_tags": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + }, + }, + }, + }, + "missing_awp_private_network_regions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "account_issues": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "regions": { + Type: schema.TypeMap, + Optional: true, + }, + "account": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "issue_type": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "cloud_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "agentless_protection_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "cloud_provider": { + Type: schema.TypeString, + Computed: true, + }, + "should_update": { + Type: schema.TypeBool, + Computed: true, + }, + "is_org_onboarding": { + Type: schema.TypeBool, + Computed: true, + }, + }, + } +} + +func dataSourceAwpAwsOnboardingRead(d *schema.ResourceData, meta interface{}) error { + d9Client := meta.(*Client) + + cloudguardAccountId := d.Get("id").(string) + log.Printf("Getting data for AWP AWS Onboarding id: %s\n", cloudguardAccountId) + + resp, _, err := d9Client.awpAwsOnboarding.GetAWPOnboarding("aws", cloudguardAccountId) + if err != nil { + return err + } + + d.SetId(resp.CloudAccountId) + // Set other schema fields here + _ = d.Set("scan_mode", resp.ScanMode) + _ = d.Set("missing_awp_private_network_regions", resp.MissingAwpPrivateNetworkRegions) + _ = d.Set("cloud_account_id", resp.CloudAccountId) + _ = d.Set("agentless_protection_enabled", resp.AgentlessProtectionEnabled) + _ = d.Set("cloud_provider", resp.Provider) + _ = d.Set("should_update", resp.ShouldUpdate) + _ = d.Set("is_org_onboarding", resp.IsOrgOnboarding) + + if resp.AgentlessAccountSettings != nil { + if err := d.Set("agentless_account_settings", flattenAgentlessAccountSettings(resp.AgentlessAccountSettings)); err != nil { + return err + } + } + if resp.AccountIssues != nil { + if err := d.Set("account_issues", flattenAccountIssues(resp.AccountIssues)); err != nil { + return err + } + } + return nil +} diff --git a/dome9/data_source_dome9_awp_aws_onboarding_data.go b/dome9/data_source_dome9_awp_aws_onboarding_data.go new file mode 100644 index 00000000..a56bdc46 --- /dev/null +++ b/dome9/data_source_dome9_awp_aws_onboarding_data.go @@ -0,0 +1,93 @@ +package dome9 + +import ( + "encoding/base64" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceAwpAwsOnboardingData() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwpAwsOnboardingDataRead, + + Schema: map[string]*schema.Schema{ + "cloud_account_id": { + Type: schema.TypeString, + Required: true, + }, + "stage": { + Type: schema.TypeString, + Computed: true, + }, + "region": { + Type: schema.TypeString, + Computed: true, + }, + "cloud_guard_backend_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "agentless_bucket_name": { + Type: schema.TypeString, + Computed: true, + }, + "remote_functions_prefix_key": { + Type: schema.TypeString, + Computed: true, + }, + "remote_snapshots_utils_function_name": { + Type: schema.TypeString, + Computed: true, + }, + "remote_snapshots_utils_function_run_time": { + Type: schema.TypeString, + Computed: true, + }, + "remote_snapshots_utils_function_time_out": { + Type: schema.TypeInt, + Computed: true, + }, + "awp_client_side_security_group_name": { + Type: schema.TypeString, + Computed: true, + }, + "cross_account_role_external_id": { + Type: schema.TypeString, + Computed: true, + }, + "remote_snapshots_utils_function_s3_pre_signed_url": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceAwpAwsOnboardingDataRead(d *schema.ResourceData, meta interface{}) error { + d9Client := meta.(*Client) + + resp, _, err := d9Client.awpAwsOnboarding.Get() + if err != nil { + return err + } + + d.SetId(resp.CloudGuardBackendAccountId) + _ = d.Set("stage", resp.Stage) + _ = d.Set("region", resp.Region) + _ = d.Set("cloud_guard_backend_account_id", resp.CloudGuardBackendAccountId) + _ = d.Set("agentless_bucket_name", resp.AgentlessBucketName) + _ = d.Set("remote_functions_prefix_key", resp.RemoteFunctionsPrefixKey) + _ = d.Set("remote_snapshots_utils_function_name", resp.RemoteSnapshotsUtilsFunctionName) + _ = d.Set("remote_snapshots_utils_function_run_time", resp.RemoteSnapshotsUtilsFunctionRunTime) + _ = d.Set("remote_snapshots_utils_function_time_out", resp.RemoteSnapshotsUtilsFunctionTimeOut) + _ = d.Set("awp_client_side_security_group_name", resp.AwpClientSideSecurityGroupName) + cloudAccountID, _, err := d9Client.awpAwsOnboarding.GetCloudAccountId(d.Get("cloud_account_id").(string)) + if err != nil { + return err + } + combinedString := resp.CloudGuardBackendAccountId + "-" + cloudAccountID + encodedString := base64.StdEncoding.EncodeToString([]byte(combinedString)) + _ = d.Set("cross_account_role_external_id", encodedString) + _ = d.Set("remote_snapshots_utils_function_s3_pre_signed_url", resp.RemoteSnapshotsUtilsFunctionS3PreSignedUrl) + + return nil +} diff --git a/dome9/data_source_dome9_awp_aws_onboarding_data_test.go b/dome9/data_source_dome9_awp_aws_onboarding_data_test.go new file mode 100644 index 00000000..12cbd1c1 --- /dev/null +++ b/dome9/data_source_dome9_awp_aws_onboarding_data_test.go @@ -0,0 +1,56 @@ +package dome9 + +import ( + "fmt" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/resourcetype" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/method" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/variable" + "log" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDataSourceAwpAwsOnboardingDataBasic(t *testing.T) { + // Get dome9_awp_aws_onboarding_data resource names + _, awpAwsOnboardingDataSourceTypeAndName, awpAwsOnboardingDataGeneratedName := method.GenerateRandomSourcesTypeAndName(resourcetype.AwpAwsOnboardingData) + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckAwpAwsOnboardingDataBasic(awpAwsOnboardingDataGeneratedName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(awpAwsOnboardingDataSourceTypeAndName, "cloud_account_id", variable.OnboardedAwsCloudGuardAccountID), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "stage"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "region"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "cloud_guard_backend_account_id"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "agentless_bucket_name"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "remote_functions_prefix_key"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "remote_snapshots_utils_function_name"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "remote_snapshots_utils_function_run_time"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "remote_snapshots_utils_function_time_out"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "awp_client_side_security_group_name"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "cross_account_role_external_id"), + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "remote_snapshots_utils_function_s3_pre_signed_url"), + ), + }, + }, + }) +} + +func testAccCheckAwpAwsOnboardingDataBasic(awpAwsOnboardingDataGeneratedName string) string { + res := fmt.Sprintf(` +data "%s" "%s" { + cloud_account_id = "%s" +} + `, + resourcetype.AwpAwsOnboardingData, + awpAwsOnboardingDataGeneratedName, + variable.OnboardedAwsCloudGuardAccountID, + ) + log.Printf("[INFO] testAccCheckAwpAwsOnboardingDataBasic:%+v\n", res) + return res +} diff --git a/dome9/data_source_dome9_awp_aws_onboarding_test.go b/dome9/data_source_dome9_awp_aws_onboarding_test.go new file mode 100644 index 00000000..72eebe1b --- /dev/null +++ b/dome9/data_source_dome9_awp_aws_onboarding_test.go @@ -0,0 +1,63 @@ +package dome9 + +import ( + "fmt" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/resourcetype" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/environmentvariable" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/method" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDataSourceAwpAwsOnboardingBasic(t *testing.T) { + // Get dome9_awp_aws_onboarding resource names and values + awpAwsOnboardingResourceTypeAndName, awpAwsOnboardingDataSourceTypeAndName, resourceGeneratedName := method.GenerateRandomSourcesTypeAndName(resourcetype.AwpAwsOnboarding) + CrossAccountRoleExternalId := os.Getenv(environmentvariable.AwpAwsCrossAccountRoleExternalIdEnvVar) + + // Generate the Awp AWS onboarding HCL Resources + awpAwsOnboardingHcl := getAwpAwsOnboardingResourceHCL(resourceGeneratedName, CrossAccountRoleExternalId, false) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAwpAwsEnvVarsPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwpAwsOnboardingConfig(awpAwsOnboardingHcl, resourceGeneratedName, awpAwsOnboardingResourceTypeAndName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(awpAwsOnboardingDataSourceTypeAndName, "id"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "scan_mode", awpAwsOnboardingResourceTypeAndName, "scan_mode"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "cloud_account_id", awpAwsOnboardingResourceTypeAndName, "cloudguard_account_id"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_account_settings.0.disabled_regions.0", awpAwsOnboardingResourceTypeAndName, "agentless_account_settings.0.disabled_regions.0"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_account_settings.0.disabled_regions.1", awpAwsOnboardingResourceTypeAndName, "agentless_account_settings.0.disabled_regions.1"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_account_settings.0.scan_machine_interval_in_hours", awpAwsOnboardingResourceTypeAndName, "agentless_account_settings.0.scan_machine_interval_in_hours"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_account_settings.0.max_concurrent_scans_per_region", awpAwsOnboardingResourceTypeAndName, "agentless_account_settings.0.max_concurrent_scans_per_region"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_account_settings.0.custom_tags.%", awpAwsOnboardingResourceTypeAndName, "agentless_account_settings.0.custom_tags.%"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "missing_awp_private_network_regions", awpAwsOnboardingResourceTypeAndName, "missing_awp_private_network_regions"), + resource.TestCheckResourceAttrPair(awpAwsOnboardingDataSourceTypeAndName, "agentless_protection_enabled", awpAwsOnboardingResourceTypeAndName, "agentless_protection_enabled"), + ), + }, + }, + }) +} + +func testAccDataSourceAwpAwsOnboardingConfig(awpAwsOnboardingHcl, dataSourceGeneratedName, awpAwsOnboardingResourceTypeAndName string) string { + return fmt.Sprintf(` +// awp aws onboarding resource +%s + +// awp aws onboarding data source +data "%s" "%s" { + id = %s.cloudguard_account_id +} +`, + awpAwsOnboardingHcl, + resourcetype.AwpAwsOnboarding, + dataSourceGeneratedName, + awpAwsOnboardingResourceTypeAndName, + ) +} diff --git a/dome9/data_source_dome9_aws_unified_onboarding.go b/dome9/data_source_dome9_aws_unified_onboarding.go index ed7fe19b..9ba1d130 100644 --- a/dome9/data_source_dome9_aws_unified_onboarding.go +++ b/dome9/data_source_dome9_aws_unified_onboarding.go @@ -6,7 +6,6 @@ import ( "github.com/terraform-providers/terraform-provider-dome9/dome9/common/providerconst" ) - func dataSourceAwsUnifiedOnboarding() *schema.Resource { return &schema.Resource{ Read: dataSourceAwsUnifiedOnboardingReadInfo, @@ -175,12 +174,12 @@ func expendStatuses(statuses aws_unified_onboarding.Statuses) interface{} { for i, statusItem := range statuses { statusesList[i] = map[string]interface{}{ - providerconst.Module : statusItem.Module, - providerconst.Feature: statusItem.Feature, - providerconst.Status: statusItem.Status, - providerconst.StatusMessage: statusItem.StackMessage, - providerconst.StackStatus: statusItem.StackStatus, - providerconst.StackMessage: statusItem.StackMessage, + providerconst.Module: statusItem.Module, + providerconst.Feature: statusItem.Feature, + providerconst.Status: statusItem.Status, + providerconst.StatusMessage: statusItem.StackMessage, + providerconst.StackStatus: statusItem.StackStatus, + providerconst.StackMessage: statusItem.StackMessage, providerconst.RemediationRecommendation: statusItem.RemediationRecommendation, } } diff --git a/dome9/data_source_dome9_aws_unified_onboarding_test.go b/dome9/data_source_dome9_aws_unified_onboarding_test.go index c0754f8e..242f324f 100644 --- a/dome9/data_source_dome9_aws_unified_onboarding_test.go +++ b/dome9/data_source_dome9_aws_unified_onboarding_test.go @@ -34,4 +34,4 @@ func TestAccDataSourceAWSUnifiedOnboardingBasic(t *testing.T) { func testAccCheckAWSUnifiedOnboardingDestroy(state *terraform.State) error { return nil -} \ No newline at end of file +} diff --git a/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config.go b/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config.go index 696ed4a1..64ef5741 100644 --- a/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config.go +++ b/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config.go @@ -5,7 +5,6 @@ import ( "github.com/terraform-providers/terraform-provider-dome9/dome9/common/providerconst" ) - func dataSourceAwsUnifiedOnboardingUpdateVersionStackConfig() *schema.Resource { return &schema.Resource{ Read: dataSourceAwsUnifiedOnboardingReadConfig, diff --git a/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config_test.go b/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config_test.go index 5e20cd72..0d9c960b 100644 --- a/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config_test.go +++ b/dome9/data_source_dome9_aws_unified_onbording_update_version_stack_config_test.go @@ -13,7 +13,7 @@ import ( func TestAccDataSourceAWSUnifiedOnboardingUpdateVersionStackConfogurationBasic(t *testing.T) { resourceTypeAndName, _, resourceName := method.GenerateRandomSourcesTypeAndName(resourcetype.AwsUnifiedOnboarding) dataTypeAndName := fmt.Sprintf("data.%s.%s", resourcetype.AwsUnifiedOnboardingUpdateVersionStackConfig, resourceName) - log.Println("TestAccDataSourceAWSUnifiedOnboardingUpdateVersionStackConfogurationBasic ",resourceTypeAndName, dataTypeAndName, resourceName) + log.Println("TestAccDataSourceAWSUnifiedOnboardingUpdateVersionStackConfogurationBasic ", resourceTypeAndName, dataTypeAndName, resourceName) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) diff --git a/dome9/data_source_dome9_cloudaccount_alibaba.go b/dome9/data_source_dome9_cloudaccount_alibaba.go index 3dd34d16..5ff920d9 100644 --- a/dome9/data_source_dome9_cloudaccount_alibaba.go +++ b/dome9/data_source_dome9_cloudaccount_alibaba.go @@ -87,7 +87,7 @@ func dataSourceAlibabaRead(d *schema.ResourceData, meta interface{}) error { return nil } -func setCredentials(credentials alibaba.CloudAccountCredentialsResponse) map[string]interface{}{ +func setCredentials(credentials alibaba.CloudAccountCredentialsResponse) map[string]interface{} { return map[string]interface{}{ "access_key": credentials.AccessKey, } diff --git a/dome9/data_source_dome9_cloudaccount_alibaba_test.go b/dome9/data_source_dome9_cloudaccount_alibaba_test.go index 36eed7ee..762e4d55 100644 --- a/dome9/data_source_dome9_cloudaccount_alibaba_test.go +++ b/dome9/data_source_dome9_cloudaccount_alibaba_test.go @@ -32,7 +32,6 @@ func TestAccDataSourceCloudAccountAlibabaBasic(t *testing.T) { resource.TestCheckResourceAttrPair(dataSourceTypeAndName, "organizational_unit_path", resourceTypeAndName, "organizational_unit_path"), resource.TestCheckResourceAttrPair(dataSourceTypeAndName, "organizational_unit_name", resourceTypeAndName, "organizational_unit_name"), resource.TestCheckResourceAttrPair(dataSourceTypeAndName, "vendor", resourceTypeAndName, "vendor"), - ), }, }, diff --git a/dome9/data_source_dome9_continuous_compliance_notification.go b/dome9/data_source_dome9_continuous_compliance_notification.go index ef7e1837..b28da6ca 100644 --- a/dome9/data_source_dome9_continuous_compliance_notification.go +++ b/dome9/data_source_dome9_continuous_compliance_notification.go @@ -91,11 +91,11 @@ func dataSourceContinuousComplianceNotification() *schema.Resource { Computed: true, }, "slack_integration_state": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, "teams_integration_state": { - Type: schema.TypeString, + Type: schema.TypeString, Computed: true, }, "email_data": { @@ -317,11 +317,11 @@ func dataSourceContinuousComplianceNotificationRead(d *schema.ResourceData, meta } } - flattenChangeDetection, err:= flattenChangeDetection(&resp.ChangeDetection) + flattenChangeDetection, err := flattenChangeDetection(&resp.ChangeDetection) if err != nil { return err } - if err := d.Set("change_detection", flattenChangeDetection); err != nil{ + if err := d.Set("change_detection", flattenChangeDetection); err != nil { return err } diff --git a/dome9/provider.go b/dome9/provider.go index 47113694..121512e1 100644 --- a/dome9/provider.go +++ b/dome9/provider.go @@ -60,6 +60,7 @@ func Provider() terraform.ResourceProvider { resourcetype.AdmissionControlPolicy: resourceAdmissionPolicy(), resourcetype.Assessment: resourceAssessment(), resourcetype.ImageAssurancePolicy: resourceImageAssurancePolicy(), + resourcetype.AwpAwsOnboarding: resourceAwpAwsOnboarding(), }, DataSourcesMap: map[string]*schema.Resource{ // terraform date source name: data source schema @@ -85,6 +86,8 @@ func Provider() terraform.ResourceProvider { resourcetype.AdmissionControlPolicy: dataSourceAdmissionControlPolicy(), resourcetype.Assessment: dataSourceAssessment(), resourcetype.ImageAssurancePolicy: dataSourceImageAssurancePolicy(), + resourcetype.AwpAwsOnboardingData: dataSourceAwpAwsOnboardingData(), + resourcetype.AwpAwsOnboarding: dataSourceAwpAwsOnboarding(), }, ConfigureFunc: providerConfigure, } diff --git a/dome9/resource_dome9_assessment.go b/dome9/resource_dome9_assessment.go index e290b88d..0f5223aa 100644 --- a/dome9/resource_dome9_assessment.go +++ b/dome9/resource_dome9_assessment.go @@ -44,7 +44,7 @@ func resourceAssessment() *schema.Resource { }, "should_minimize_result": { Type: schema.TypeBool, - Default: true, + Default: true, Optional: true, }, "name": { diff --git a/dome9/resource_dome9_awp_aws_onboarding.go b/dome9/resource_dome9_awp_aws_onboarding.go new file mode 100644 index 00000000..4f00d1ca --- /dev/null +++ b/dome9/resource_dome9_awp_aws_onboarding.go @@ -0,0 +1,402 @@ +package dome9 + +import ( + "errors" + "fmt" + "log" + "strconv" + "strings" + + "github.com/dome9/dome9-sdk-go/dome9/client" + "github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/providerconst" +) + +func resourceAwpAwsOnboarding() *schema.Resource { + return &schema.Resource{ + Create: resourceAWPAWSOnboardingCreate, + Read: resourceAWPAWSOnboardingRead, + Update: resourceAWPAWSOnboardingUpdate, + Delete: resourceAWPAWSOnboardingDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Schema: map[string]*schema.Schema{ + "cloudguard_account_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "cross_account_role_name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "cross_account_role_external_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "scan_mode": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{ + "inAccount", + "saas", + "inAccountHub", + "inAccountSub", + }, false), + }, + "agentless_account_settings": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled_regions": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "scan_machine_interval_in_hours": { + Type: schema.TypeInt, + Optional: true, + Default: 24, + }, + "max_concurrent_scans_per_region": { + Type: schema.TypeInt, + Optional: true, + Default: 20, + }, + "custom_tags": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{}, + }, + }, + }, + }, + }, + "missing_awp_private_network_regions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "account_issues": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "regions": { + Type: schema.TypeMap, + Optional: true, + }, + "account": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "issue_type": { + Type: schema.TypeString, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + "cloud_account_id": { + Type: schema.TypeString, + Computed: true, + }, + "agentless_protection_enabled": { + Type: schema.TypeBool, + Computed: true, + }, + "cloud_provider": { + Type: schema.TypeString, + Computed: true, + }, + "should_update": { + Type: schema.TypeBool, + Computed: true, + }, + "is_org_onboarding": { + Type: schema.TypeBool, + Computed: true, + }, + "should_create_policy": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "force_delete": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + }, + } +} + +func resourceAWPAWSOnboardingCreate(d *schema.ResourceData, meta interface{}) error { + d9client := meta.(*Client) + cloudguardAccountId := d.Get("cloudguard_account_id").(string) + req, err := expandAWPOnboardingRequest(d) + if err != nil { + return err + } + log.Printf("[INFO] Creating AWP AWS Onboarding request %+v\n", req) + options := awp_aws_onboarding.CreateOptions{ + ShouldCreatePolicy: strconv.FormatBool(d.Get("should_create_policy").(bool)), + } + _, err = d9client.awpAwsOnboarding.CreateAWPOnboarding(cloudguardAccountId, req, options) + if err != nil { + return err + } + d.SetId(cloudguardAccountId) // set the resource ID to the CloudGuard Account ID + log.Printf("[INFO] Created AWP AWS Onboarding with CloudGuard Account ID: %v\n", cloudguardAccountId) + + return resourceAWPAWSOnboardingRead(d, meta) +} + +func expandAWPOnboardingRequest(d *schema.ResourceData) (awp_aws_onboarding.CreateAWPOnboardingRequest, error) { + agentlessAccountSettings, err := expandAgentlessAccountSettings(d) + if err != nil { + return awp_aws_onboarding.CreateAWPOnboardingRequest{}, err + } + return awp_aws_onboarding.CreateAWPOnboardingRequest{ + CrossAccountRoleName: d.Get("cross_account_role_name").(string), + CrossAccountRoleExternalId: d.Get("cross_account_role_external_id").(string), + ScanMode: d.Get("scan_mode").(string), + IsTerraform: true, + AgentlessAccountSettings: agentlessAccountSettings, + }, nil +} + +func resourceAWPAWSOnboardingRead(d *schema.ResourceData, meta interface{}) error { + d9client := meta.(*Client) + resp, _, err := d9client.awpAwsOnboarding.GetAWPOnboarding("aws", d.Id()) + if err != nil { + if err.(*client.ErrorResponse).IsObjectNotFound() { + log.Printf("[WARN] Removing AWS cloud account %s from state because it no longer exists in Dome9", d.Id()) + d.SetId("") + return nil + } + return err + } + + log.Printf("[INFO] Reading AWP AWS Onbaording account data: %+v\n", resp) + + // set the schema fields from the response + _ = d.Set("missing_awp_private_network_regions", resp.MissingAwpPrivateNetworkRegions) + _ = d.Set("cloud_account_id", resp.CloudAccountId) + _ = d.Set("agentless_protection_enabled", resp.AgentlessProtectionEnabled) + _ = d.Set("scan_mode", resp.ScanMode) + _ = d.Set("cloud_provider", resp.Provider) + _ = d.Set("should_update", resp.ShouldUpdate) + _ = d.Set("is_org_onboarding", resp.IsOrgOnboarding) + + err = setAgentlessAccountSettings(resp, d) + if err != nil { + return err + } + + if resp.AccountIssues != nil { + if err := d.Set("account_issues", flattenAccountIssues(resp.AccountIssues)); err != nil { + return err + } + } + + return nil +} + +func resourceAWPAWSOnboardingDelete(d *schema.ResourceData, meta interface{}) error { + d9client := meta.(*Client) + log.Printf("[INFO] Offboarding AWP Account with cloud guard id : %v\n", d.Id()) + options := awp_aws_onboarding.DeleteOptions{ + ForceDelete: strconv.FormatBool(d.Get("force_delete").(bool)), + } + _, err := d9client.awpAwsOnboarding.DeleteAWPOnboarding(d.Id(), options) + if err != nil { + return err + } + return nil +} + +func expandAgentlessAccountSettings(d *schema.ResourceData) (*awp_aws_onboarding.AgentlessAccountSettings, error) { + if _, ok := d.GetOk("agentless_account_settings"); !ok { + // If "agentless_account_settings" key doesn't exist, return nil (since these settings are optional) + return nil, nil + } + agentlessAccountSettingsList := d.Get("agentless_account_settings").([]interface{}) + agentlessAccountSettingsMap := agentlessAccountSettingsList[0].(map[string]interface{}) + scanMode := d.Get("scan_mode").(string) + + var scanMachineIntervalInHours int + if scanMode == "saas" { + scanMachineIntervalInHours = providerconst.DefaultScanMachineIntervalInHoursSaas + } else { + scanMachineIntervalInHours = providerconst.DefaultScanMachineIntervalInHoursInAccount + } + + // Initialize the AgentlessAccountSettings struct with default values + agentlessAccountSettings := &awp_aws_onboarding.AgentlessAccountSettings{ + DisabledRegions: make([]string, 0), + CustomTags: make(map[string]string), + ScanMachineIntervalInHours: scanMachineIntervalInHours, + MaxConcurrenceScansPerRegion: providerconst.DefaultMaxConcurrentScansPerRegion, + } + + // Check if the key exists and is not nil + if disabledRegionsInterface, ok := agentlessAccountSettingsMap["disabled_regions"].([]interface{}); ok { + disabledRegions := make([]string, len(disabledRegionsInterface)) + for i, disabledRegion := range disabledRegionsInterface { + disabledRegions[i] = disabledRegion.(string) + } + _, err := validateDisabledRegions(disabledRegions) + if err != nil { + return agentlessAccountSettings, err + } + agentlessAccountSettings.DisabledRegions = disabledRegions + } + + if scanMachineInterval, ok := agentlessAccountSettingsMap["scan_machine_interval_in_hours"].(int); ok { + if scanMode == "saas" && (scanMachineInterval < providerconst.DefaultScanMachineIntervalInHoursSaas || scanMachineInterval > providerconst.MaxScanMachineIntervalInHours) { + return nil, fmt.Errorf("scan_machine_interval_in_hours must be between %d and %d for saas mode", providerconst.DefaultScanMachineIntervalInHoursSaas, providerconst.MaxScanMachineIntervalInHours) + } else if scanMode == "inAccount" && (scanMachineInterval < providerconst.DefaultScanMachineIntervalInHoursInAccount || scanMachineInterval > providerconst.MaxScanMachineIntervalInHours) { + return nil, fmt.Errorf("scan_machine_interval_in_hours must be between %d and %d for inAccount mode", providerconst.DefaultScanMachineIntervalInHoursInAccount, providerconst.MaxScanMachineIntervalInHours) + } + agentlessAccountSettings.ScanMachineIntervalInHours = scanMachineInterval + } + + if maxConcurrentScans, ok := agentlessAccountSettingsMap["max_concurrent_scans_per_region"].(int); ok { + if maxConcurrentScans < providerconst.MinMaxConcurrentScansPerRegion || maxConcurrentScans > providerconst.DefaultMaxConcurrentScansPerRegion { + return nil, fmt.Errorf("max_concurrent_scans_per_region must be between 1 and 20") + } + agentlessAccountSettings.MaxConcurrenceScansPerRegion = maxConcurrentScans + } + + if customTagsInterface, ok := agentlessAccountSettingsMap["custom_tags"].(map[string]interface{}); ok { + customTags := make(map[string]string) + for k, v := range customTagsInterface { + customTags[k] = v.(string) + } + agentlessAccountSettings.CustomTags = customTags + } + + return agentlessAccountSettings, nil +} + +func setAgentlessAccountSettings(resp *awp_aws_onboarding.GetAWPOnboardingResponse, d *schema.ResourceData) error { + if resp.AgentlessAccountSettings != nil { + // Check if all fields of AgentlessAccountSettings are nil + if resp.AgentlessAccountSettings.DisabledRegions != nil || + resp.AgentlessAccountSettings.ScanMachineIntervalInHours != 0 || + resp.AgentlessAccountSettings.MaxConcurrenceScansPerRegion != 0 || + resp.AgentlessAccountSettings.CustomTags != nil { + if err := d.Set("agentless_account_settings", flattenAgentlessAccountSettings(resp.AgentlessAccountSettings)); err != nil { + return err + } + } + } + return nil +} + +func flattenAgentlessAccountSettings(settings *awp_aws_onboarding.AgentlessAccountSettings) []interface{} { + + m := map[string]interface{}{ + "disabled_regions": settings.DisabledRegions, + "scan_machine_interval_in_hours": settings.ScanMachineIntervalInHours, + "max_concurrent_scans_per_region": settings.MaxConcurrenceScansPerRegion, + "custom_tags": settings.CustomTags, + } + return []interface{}{m} +} + +func flattenAccountIssues(accountIssues *awp_aws_onboarding.AccountIssues) []interface{} { + m := map[string]interface{}{ + "regions": accountIssues.Regions, + "account": accountIssues.Account, + } + + return []interface{}{m} +} + +func resourceAWPAWSOnboardingUpdate(d *schema.ResourceData, meta interface{}) error { + d9Client := meta.(*Client) + log.Println("An update occurred") + + if d.HasChange("delete_force") { + log.Println("delete_force has been changed") + if err := d.Set("delete_force", d.Get("delete_force").(bool)); err != nil { + return err + } + } + + if d.HasChange("should_create_policy") { + log.Println("should_create_policy has been changed") + if err := d.Set("should_create_policy", d.Get("should_create_policy").(bool)); err != nil { + return err + } + } + // Check if there are changes in the AgentlessAccountSettings fields + if d.HasChange("agentless_account_settings") { + log.Println("agentless_account_settings has been changed") + // Build the update request + newAgentlessAccountSettings, err := expandAgentlessAccountSettings(d) + if err != nil { + return err + } + // Send the update request + _, err = d9Client.awpAwsOnboarding.UpdateAWPSettings(d.Get("cloud_provider").(string), d.Id(), *newAgentlessAccountSettings) + if err != nil { + return err + } + log.Printf("[INFO] Updated agentless account settings for cloud account %s\n", d.Id()) + } + + return nil +} + +func validateDisabledRegions(regions []string) (bool, error) { + hyphenatedAWSRegions := convertRegionsFormat(providerconst.AWSRegions) + validate, invalidRegions := checkDisabledRegions(regions, hyphenatedAWSRegions) + if !validate { + errorMsg := fmt.Sprintf("Expected disabled-regions to be one of %v, got %v", hyphenatedAWSRegions, invalidRegions) + return false, errors.New(errorMsg) + } + return true, nil +} + +func convertRegionsFormat(regions []string) []string { + hyphenatedRegions := make([]string, len(regions)) + for i, region := range regions { + hyphenatedRegions[i] = strings.ReplaceAll(region, "_", "-") + } + return hyphenatedRegions +} + +func checkDisabledRegions(regions []string, regionsToCompare []string) (bool, []string) { + invalidRegions := make([]string, 0) + for _, val := range regions { + flag := false + for _, region := range regionsToCompare { + if val == region { + flag = true + break + } + } + if !flag { + invalidRegions = append(invalidRegions, val) + } + } + return len(invalidRegions) == 0, invalidRegions +} diff --git a/dome9/resource_dome9_awp_aws_onboarding_test.go b/dome9/resource_dome9_awp_aws_onboarding_test.go new file mode 100644 index 00000000..2c700df0 --- /dev/null +++ b/dome9/resource_dome9_awp_aws_onboarding_test.go @@ -0,0 +1,190 @@ +package dome9 + +import ( + "encoding/json" + "fmt" + "github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/environmentvariable" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/variable" + "os" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/resourcetype" + "github.com/terraform-providers/terraform-provider-dome9/dome9/common/testing/method" +) + +func TestAccResourceAWPAWSOnboardingBasic(t *testing.T) { + var awpCloudAccountInfo awp_aws_onboarding.GetAWPOnboardingResponse + // Generate All Required Random Names for Testing + resourceTypeAndName, _, generatedName := method.GenerateRandomSourcesTypeAndName(resourcetype.AwpAwsOnboarding) + CrossAccountRoleExternalId := os.Getenv(environmentvariable.AwpAwsCrossAccountRoleExternalIdEnvVar) + disabledRegion1, _ := getRegionByIndex(variable.DisabledRegions, 0) + disabledRegion2, _ := getRegionByIndex(variable.DisabledRegions, 1) + disabledRegionUpdate3, _ := getRegionByIndex(variable.DisabledRegionsUpdate, 2) + disabledRegionUpdate4, _ := getRegionByIndex(variable.DisabledRegionsUpdate, 3) + + // Generate the Awp AWS onboarding HCL Resources + awpAwsOnboardingHcl := getAwpAwsOnboardingResourceHCL(generatedName, CrossAccountRoleExternalId, false) + awpAwsOnboardingUpdateHcl := getAwpAwsOnboardingResourceHCL(generatedName, CrossAccountRoleExternalId, true) + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAwpAwsEnvVarsPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWPAWSOnboardingDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckAWPAWSOnboardingBasic(awpAwsOnboardingHcl), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwpAccountExists(resourceTypeAndName, &awpCloudAccountInfo), + resource.TestCheckResourceAttr(resourceTypeAndName, "cloudguard_account_id", variable.OnboardedAwsCloudGuardAccountID), + resource.TestCheckResourceAttr(resourceTypeAndName, "cross_account_role_name", variable.AwpAwsCrossAccountRoleName), + resource.TestCheckResourceAttr(resourceTypeAndName, "cross_account_role_external_id", CrossAccountRoleExternalId), + resource.TestCheckResourceAttr(resourceTypeAndName, "scan_mode", variable.ScanMode), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.0", disabledRegion1), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.1", disabledRegion2), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.scan_machine_interval_in_hours", variable.ScanMachineIntervalInHours), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.max_concurrent_scans_per_region", variable.MaxConcurrentScansPerRegion), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.custom_tags.%", "2"), + resource.TestCheckResourceAttrSet(resourceTypeAndName, "id"), + resource.TestCheckResourceAttr(resourceTypeAndName, "cloud_provider", "aws"), + resource.TestCheckResourceAttr(resourceTypeAndName, "force_delete", "true"), + resource.TestCheckResourceAttr(resourceTypeAndName, "should_create_policy", "true"), + ), + }, + { + Config: testAccCheckAWPAWSOnboardingBasic(awpAwsOnboardingUpdateHcl), + Check: resource.ComposeTestCheckFunc( + testAccCheckAwpAccountExists(resourceTypeAndName, &awpCloudAccountInfo), + resource.TestCheckResourceAttr(resourceTypeAndName, "cloudguard_account_id", variable.OnboardedAwsCloudGuardAccountID), + resource.TestCheckResourceAttr(resourceTypeAndName, "cross_account_role_name", variable.AwpAwsCrossAccountRoleName), + resource.TestCheckResourceAttr(resourceTypeAndName, "cross_account_role_external_id", CrossAccountRoleExternalId), + resource.TestCheckResourceAttr(resourceTypeAndName, "scan_mode", variable.ScanMode), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.0", disabledRegion1), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.1", disabledRegion2), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.2", disabledRegionUpdate3), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.disabled_regions.3", disabledRegionUpdate4), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.scan_machine_interval_in_hours", variable.ScanMachineIntervalInHoursUpdate), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.max_concurrent_scans_per_region", variable.MaxConcurrentScansPerRegionUpdate), + resource.TestCheckResourceAttr(resourceTypeAndName, "agentless_account_settings.0.custom_tags.%", "3"), + resource.TestCheckResourceAttrSet(resourceTypeAndName, "id"), + resource.TestCheckResourceAttr(resourceTypeAndName, "cloud_provider", "aws"), + resource.TestCheckResourceAttr(resourceTypeAndName, "force_delete", "true"), + resource.TestCheckResourceAttr(resourceTypeAndName, "should_create_policy", "true"), + ), + }, + }, + }) +} + +func testAccCheckAWPAWSOnboardingDestroy(state *terraform.State) error { + apiClient := testAccProvider.Meta().(*Client) + for _, rs := range state.RootModule().Resources { + if rs.Type != resourcetype.AwpAwsOnboarding { + continue + } + maxRetries := 3 + retryInterval := time.Second * 5 + var getOnboardingResponse *awp_aws_onboarding.GetAWPOnboardingResponse + var err error + for i := 0; i < maxRetries; i++ { + getOnboardingResponse, _, err = apiClient.awpAwsOnboarding.GetAWPOnboarding("aws", rs.Primary.ID) + if err == nil || getOnboardingResponse != nil { + // If the request was successful or the resource still exists, wait for the retry interval before trying again + time.Sleep(retryInterval) + } else { + // If the request failed with a 404 status code, break the loop + break + } + } + if err == nil { + return fmt.Errorf("error Awp Aws Onboarding still exists, ID: %s", rs.Primary.ID) + } + // verify the getOnboardingResponse also is not exists + if getOnboardingResponse != nil { + return fmt.Errorf("error Awp Aws Onboarding still exists and wasn't destroyed, ID: %s", rs.Primary.ID) + } + } + return nil +} + +func testAccCheckAWPAWSOnboardingBasic(awpAwsOnboardingHcl string) string { + return fmt.Sprintf(` +// awp aws onboarding resource +%s +`, + awpAwsOnboardingHcl, + ) +} + +func testAccCheckAwpAccountExists(resource string, awpAccount *awp_aws_onboarding.GetAWPOnboardingResponse) resource.TestCheckFunc { + return func(state *terraform.State) error { + rs, ok := state.RootModule().Resources[resource] + if !ok { + return fmt.Errorf("didn't find resource: %s", resource) + } + if rs.Primary.ID == "" { + return fmt.Errorf("no record ID is set") + } + + apiClient := testAccProvider.Meta().(*Client) + receivedCloudAccountResponse, _, err := apiClient.awpAwsOnboarding.GetAWPOnboarding("aws", rs.Primary.ID) + + if err != nil { + return fmt.Errorf("failed fetching resource %s. Recevied error: %s", resource, err) + } + *awpAccount = *receivedCloudAccountResponse + return nil + } +} + +func getAwpAwsOnboardingResourceHCL(generatedResourceName string, externalId string, updateAction bool) string { + return fmt.Sprintf(` +// awp aws onboarding resource +resource "%s" "%s" { + cloudguard_account_id = "%s" + cross_account_role_name = "%s" + cross_account_role_external_id = "%s" + scan_mode = "%s" + agentless_account_settings { + disabled_regions = %s + scan_machine_interval_in_hours = "%s" + max_concurrent_scans_per_region = "%s" + custom_tags = %s + } +} +`, + resourcetype.AwpAwsOnboarding, + generatedResourceName, + variable.OnboardedAwsCloudGuardAccountID, + variable.AwpAwsCrossAccountRoleName, + externalId, + variable.ScanMode, + IfThenElse(updateAction, variable.DisabledRegionsUpdate, variable.DisabledRegions), + IfThenElse(updateAction, variable.ScanMachineIntervalInHoursUpdate, variable.ScanMachineIntervalInHours), + IfThenElse(updateAction, variable.MaxConcurrentScansPerRegionUpdate, variable.MaxConcurrentScansPerRegion), + IfThenElse(updateAction, variable.CustomTagsUpdate, variable.CustomTags), + ) +} + +func testAwpAwsEnvVarsPreCheck(t *testing.T) { + if v := os.Getenv(environmentvariable.AwpAwsCrossAccountRoleExternalIdEnvVar); v == "" { + t.Fatalf("%s must be set for acceptance tests", environmentvariable.AwpAwsCrossAccountRoleExternalIdEnvVar) + } +} + +func getRegionByIndex(regionsRaw string, index int) (string, error) { + var regions []string + err := json.Unmarshal([]byte(regionsRaw), ®ions) + if err != nil { + return "", err + } + if index < 0 || index >= len(regions) { + return "", fmt.Errorf("index out of range") + } + return regions[index], nil +} diff --git a/dome9/resource_dome9_cloudaccount_aws.go b/dome9/resource_dome9_cloudaccount_aws.go index 813d4091..fdc8750c 100644 --- a/dome9/resource_dome9_cloudaccount_aws.go +++ b/dome9/resource_dome9_cloudaccount_aws.go @@ -375,7 +375,7 @@ func validateAwsGovVendor(credentials aws.CloudAccountCredentials, regions []str } func validateAwsVendor(credentials aws.CloudAccountCredentials, regions []string) (bool, error) { - validate := checkRegions(regions, providerconst.AWSRegions) + validate := checkRegions(regions, providerconst.AWSRegions) if !validate { return validate, fmt.Errorf("aws vendor has an unsutibule regions") } diff --git a/dome9/resource_dome9_cloudaccount_aws_test.go b/dome9/resource_dome9_cloudaccount_aws_test.go index a1d0931a..5f397ee9 100644 --- a/dome9/resource_dome9_cloudaccount_aws_test.go +++ b/dome9/resource_dome9_cloudaccount_aws_test.go @@ -62,7 +62,7 @@ func TestAccResourceCloudAccountAWSBasic(t *testing.T) { resource.TestCheckResourceAttr(resourceTypeAndName, "net_sec.0.regions.2.new_group_behavior", originalGroupBehavior), ), }, - }, + }, }) } diff --git a/dome9/resource_dome9_cloudaccount_oci_test.go b/dome9/resource_dome9_cloudaccount_oci_test.go index 574d9ac5..a25bf198 100644 --- a/dome9/resource_dome9_cloudaccount_oci_test.go +++ b/dome9/resource_dome9_cloudaccount_oci_test.go @@ -56,7 +56,7 @@ func testAccCheckCloudAccountOciDestroy(s *terraform.State) error { return fmt.Errorf("cloudaccounts with id %s exists and wasn't destroyed", rs.Primary.ID) } } - + return nil } diff --git a/dome9/resource_dome9_continuous_compliance_notification.go b/dome9/resource_dome9_continuous_compliance_notification.go index ef0c1a1d..0bcd0bef 100644 --- a/dome9/resource_dome9_continuous_compliance_notification.go +++ b/dome9/resource_dome9_continuous_compliance_notification.go @@ -263,10 +263,10 @@ func resourceContinuousComplianceNotification() *schema.Resource { Required: true, }, "http_method": { - Type: schema.TypeString, - Optional: true, - Default: "Post", - ForceNew: true, + Type: schema.TypeString, + Optional: true, + Default: "Post", + ForceNew: true, ValidateFunc: validation.StringInSlice([]string{"Post", "Put"}, true), }, "auth_method": { @@ -408,7 +408,7 @@ func resourceContinuousComplianceNotificationRead(d *schema.ResourceData, meta i } } - flattenChangeDetection, err:= flattenChangeDetection(&resp.ChangeDetection) + flattenChangeDetection, err := flattenChangeDetection(&resp.ChangeDetection) if err != nil { return err } @@ -613,7 +613,6 @@ func expandWebhookData(webhookData *schema.Set) (*continuous_compliance_notifica webhookDataItem := webhookDataLst[0] webhookData := webhookDataItem.(map[string]interface{}) - PayloadFormatJson := make(map[string]interface{}) err := json.Unmarshal([]byte(webhookData["payload_format"].(string)), &PayloadFormatJson) if err != nil { @@ -871,4 +870,4 @@ func ValidatePayloadFormatJSON(v interface{}, k string) (ws []string, errors []e return } return -} \ No newline at end of file +} diff --git a/dome9/resource_dome9_image_assurance_policy_test.go b/dome9/resource_dome9_image_assurance_policy_test.go index 210fb6a8..ab9da7c6 100644 --- a/dome9/resource_dome9_image_assurance_policy_test.go +++ b/dome9/resource_dome9_image_assurance_policy_test.go @@ -175,4 +175,4 @@ resource "%s" "%s" { IfThenElse(updateAction, variable.ImageAssurancePolicyPreventAction, variable.ImageAssurancePolicyDetectAction), IfThenElse(updateAction, variable.ImageAssurancePolicyPreventAction, variable.ImageAssurancePolicyDetectAction), ) -} \ No newline at end of file +} diff --git a/dome9/resource_dome9_unified_onbording.go b/dome9/resource_dome9_unified_onbording.go index d4bc7dcf..a2d31ccd 100644 --- a/dome9/resource_dome9_unified_onbording.go +++ b/dome9/resource_dome9_unified_onbording.go @@ -157,7 +157,7 @@ func getEnabledFromMap(configurations map[string]interface{}) bool { if len(configurations) > 0 { enabled := configurations[providerconst.Enabled] - if enabled != "" && enabled != nil { + if enabled != "" && enabled != nil { v := enabled.(string) b, _ = strconv.ParseBool(v) } @@ -209,8 +209,7 @@ func addOnboardingIdAsSchemaId(d *schema.ResourceData, resp *aws_unified_onboard } } -func -resourceUnifiedOnboardingDelete(data *schema.ResourceData, i interface{}) error { +func resourceUnifiedOnboardingDelete(data *schema.ResourceData, i interface{}) error { return nil } diff --git a/examples/awp_aws_onboarding/README.md b/examples/awp_aws_onboarding/README.md new file mode 100644 index 00000000..90a74d60 --- /dev/null +++ b/examples/awp_aws_onboarding/README.md @@ -0,0 +1,22 @@ +# AWP AWS Onboarding Example + +This example will show you how to use Terraform to onboarding AWP AWS cloud account that protected by dome9. +This example codifies [this API](https://docs.cgn.portal.checkpoint.com/reference/agentless). + +To run, configure your Dome9 provider as described in https://www.terraform.io/docs/providers/dome9/index.html + +## Run the example + +From inside of this directory: + +```bash +terraform init +terraform plan -out theplan +terraform apply theplan +``` + +## Destroy 💥 + +```bash +terraform destroy +``` diff --git a/examples/awp_aws_onboarding/main.tf b/examples/awp_aws_onboarding/main.tf new file mode 100644 index 00000000..c18bf8a2 --- /dev/null +++ b/examples/awp_aws_onboarding/main.tf @@ -0,0 +1,86 @@ +terraform { + required_providers { + dome9 = { + source = "dome9/dome9" + version = ">=1.29.7" + } + aws = { + source = "hashicorp/aws" + version = ">= 3.0" + } + } +} + +# The Dome9 provider is used to interact with the resources supported by Dome9. +# The provider needs to be configured with the proper credentials before it can be used. +# Use the dome9_access_id and dome9_secret_key attributes of the provider to provide the Dome9 access key and secret key. +# The base_url attribute is used to specify the base URL of the Dome9 API. +# The Dome9 provider supports several options for providing these credentials. The following example demonstrates the use of static credentials: +#you can read the Dome9 provider documentation to understand the full set of options available for providing credentials. +#https://registry.terraform.io/providers/dome9/dome9/latest/docs#authentication +provider "dome9" { + dome9_access_id = "DOME9_ACCESS_ID" + dome9_secret_key = "DOME9_SECRET_KEY" + base_url = "https://api.dome9.com/v2/" +} + +# AWS Provider Configurations +# The AWS provider is used to interact with the resources supported by AWS. +# The provider needs to be configured with the proper credentials before it can be used. +# Use the access_key, secret_key, and token attributes of the provider to provide the credentials. +# also you can use the shared_credentials_file attribute to provide the path to the shared credentials file. +# The AWS provider supports several options for providing these credentials. The following example demonstrates the use of static credentials: +#you can read the AWS provider documentation to understand the full set of options available for providing credentials. +#https://registry.terraform.io/providers/hashicorp/aws/latest/docs#authentication-and-configuration +provider "aws" { + region = "AWS_REGION" + access_key = "AWS_ACCESS_KEY" + secret_key = "AWS_SECRET_KEY" + token = "AWS_SESSION_TOKEN" +} + +# Onboarding AWS Account to CloudGuard Dome9 Account +# This resource is optional and can be ignored and you need to pass CloudGuard account id to the module directly at the parameter awp_cloud_account_id. +# to know how to get the credentials for the onboarding process, please refer to the following link: +## https://sc1.checkpoint.com/documents/CloudGuard_Dome9/Documentation/Assets/AWS/OnboardAWS.htm +resource "dome9_cloudaccount_aws" "aws_onboarding_account_test" { + name = "aws_onboarding_account_test" + credentials { + arn = "CloudGuard Connect Role ARN" + secret = "CloudGuard Connect Role Secret" + type = "RoleBased" + } + net_sec { + regions { + new_group_behavior = "ReadOnly" + region = "us_west_2" + } + } +} + +# There is a need to use this terraform module [terraform-dome9-awp-aws] to create all the prerequisites for the onboarding process (All the needed AWS Resources) +# Example for the module use: +module "terraform-dome9-awp-aws" { + source = "github.com/dome9/terraform-dome9-awp-aws" + awp_cloud_account_id = " or " + awp_scan_mode = "" # Valid Values = "inAccount" or "saas" + + # Optional customizations: + # e.g: + # awp_cross_account_role_name = "" + # awp_cross_account_role_external_id = "" + + # Optional account Settings + # e.g: + # awp_account_settings_aws = { + # scan_machine_interval_in_hours = 24 + # disabled_regions = ["ap-northeast-1", "ap-northeast-2", ...] # List of regions to disable + # max_concurrent_scans_per_region = 20 + # custom_tags = { + # tag1 = "value1" + # tag2 = "value2" + # tag3 = "value3" + # ... + # } + # } +} \ No newline at end of file diff --git a/go.mod b/go.mod index cf80996d..b4a287ee 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,6 @@ module github.com/terraform-providers/terraform-provider-dome9 go 1.13 require ( - github.com/dome9/dome9-sdk-go v1.18.3 + github.com/dome9/dome9-sdk-go v1.18.4 github.com/hashicorp/terraform-plugin-sdk v1.1.0 ) diff --git a/go.sum b/go.sum index 3057c5ca..a130febd 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dome9/dome9-sdk-go v1.18.3 h1:KqGg1OQzAxLmwTCkx64GZU8J/mrCeZKYrWfOyyVFn1A= -github.com/dome9/dome9-sdk-go v1.18.3/go.mod h1:CF7nXCQk74ApsoG2i1+ziC/pnnnsyMeG6Mpho8cRAGM= +github.com/dome9/dome9-sdk-go v1.18.4 h1:Krml7YzbGRLHp4O3hNh1/a12Xk5pPJpya7W0ixIyIVQ= +github.com/dome9/dome9-sdk-go v1.18.4/go.mod h1:CF7nXCQk74ApsoG2i1+ziC/pnnnsyMeG6Mpho8cRAGM= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/awp_aws_onboarding.go b/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/awp_aws_onboarding.go new file mode 100644 index 00000000..c643039c --- /dev/null +++ b/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/awp_aws_onboarding.go @@ -0,0 +1,203 @@ +package awp_aws_onboarding + +import ( + "fmt" + "log" + "net/http" + "time" +) + +const ( + awpAWSGetOnboardingDataPath = "workload/agentless/aws/terraform/onboarding" + awsOnboardingResourcePath = "workload/agentless/aws/accounts" + cloudAccountsPath = "cloudaccounts/" +) + +type AgentlessAwsTerraformOnboardingDataResponse struct { + Stage string `json:"stage"` + Region string `json:"region"` + CloudGuardBackendAccountId string `json:"cloudGuardBackendAccountId"` + AgentlessBucketName string `json:"agentlessBucketName"` + RemoteFunctionsPrefixKey string `json:"remoteFunctionsPrefixKey"` + RemoteSnapshotsUtilsFunctionName string `json:"remoteSnapshotsUtilsFunctionName"` + RemoteSnapshotsUtilsFunctionRunTime string `json:"remoteSnapshotsUtilsFunctionRunTime"` + RemoteSnapshotsUtilsFunctionTimeOut int `json:"remoteSnapshotsUtilsFunctionTimeOut"` + AwpClientSideSecurityGroupName string `json:"awpClientSideSecurityGroupName"` + RemoteSnapshotsUtilsFunctionS3PreSignedUrl string `json:"remoteSnapshotsUtilsFunctionCodePreSigneUrl"` +} + +type CloudAccountResponse struct { + ID string `json:"id"` + Vendor string `json:"vendor"` + Name string `json:"name"` + ExternalAccountNumber string `json:"externalAccountNumber"` + Error interface{} `json:"error"` + IsFetchingSuspended bool `json:"isFetchingSuspended"` + CreationDate string `json:"creationDate"` + Credentials Credentials `json:"credentials"` + IamSafe interface{} `json:"iamSafe"` + NetSec NetSec `json:"netSec"` + Magellan bool `json:"magellan"` + FullProtection bool `json:"fullProtection"` + AllowReadOnly bool `json:"allowReadOnly"` + OrganizationId string `json:"organizationId"` + OrganizationalUnitId interface{} `json:"organizationalUnitId"` + OrganizationalUnitPath string `json:"organizationalUnitPath"` + OrganizationalUnitName string `json:"organizationalUnitName"` + LambdaScanner bool `json:"lambdaScanner"` + Serverless Serverless `json:"serverless"` + OnboardingMode string `json:"onboardingMode"` +} + +type Credentials struct { + Apikey interface{} `json:"apikey"` + Arn string `json:"arn"` + Secret interface{} `json:"secret"` + IamUser interface{} `json:"iamUser"` + Type string `json:"type"` + IsReadOnly bool `json:"isReadOnly"` +} + +type NetSec struct { + Regions []Region `json:"regions"` +} + +type Region struct { + Region string `json:"region"` + Name string `json:"name"` + Hidden bool `json:"hidden"` + NewGroupBehavior string `json:"newGroupBehavior"` +} + +type Serverless struct { + CodeAnalyzerEnabled bool `json:"codeAnalyzerEnabled"` + CodeDependencyAnalyzerEnabled bool `json:"codeDependencyAnalyzerEnabled"` +} + +type AgentlessAccountSettings struct { + DisabledRegions []string `json:"disabledRegions"` + ScanMachineIntervalInHours int `json:"scanMachineIntervalInHours"` + MaxConcurrenceScansPerRegion int `json:"maxConcurrenceScansPerRegion"` + SkipFunctionAppsScan bool `json:"skipFunctionAppsScan"` + CustomTags map[string]string `json:"customTags"` +} + +type CreateAWPOnboardingRequest struct { + CrossAccountRoleName string `json:"crossAccountRoleName"` + CrossAccountRoleExternalId string `json:"crossAccountRoleExternalId"` + ScanMode string `json:"scanMode"` + IsTerraform bool `json:"isTerraform"` + AgentlessAccountSettings *AgentlessAccountSettings `json:"agentlessAccountSettings"` +} + +type AccountIssues struct { + Regions map[string]interface{} `json:"regions"` + Account *map[string]interface{} `json:"account"` +} + +type GetAWPOnboardingResponse struct { + AgentlessAccountSettings *AgentlessAccountSettings `json:"agentlessAccountSettings"` + MissingAwpPrivateNetworkRegions *[]string `json:"missingAwpPrivateNetworkRegions"` + AccountIssues *AccountIssues `json:"accountIssues"` + CloudAccountId string `json:"cloudAccountId"` + AgentlessProtectionEnabled bool `json:"agentlessProtectionEnabled"` + ScanMode string `json:"scanMode"` + Provider string `json:"provider"` + ShouldUpdate bool `json:"shouldUpdate"` + IsOrgOnboarding bool `json:"isOrgOnboarding"` + CentralizedCloudAccountId string `json:"centralizedCloudAccountId"` +} + +type CreateOptions struct { + ShouldCreatePolicy string `url:"shouldCreatePolicy"` +} + +type DeleteOptions struct { + ForceDelete string `url:"forceDelete"` +} + +func (service *Service) CreateAWPOnboarding(id string, req CreateAWPOnboardingRequest, queryParams CreateOptions) (*http.Response, error) { + // Define the maximum number of retries and the interval between retries + maxRetries := 3 + retryInterval := time.Second * 5 + + // Create the base path + basePath := fmt.Sprintf("%s/%s/enable", awsOnboardingResourcePath, id) + + // Initialize the response and error variables outside the loop + var resp *http.Response + var err error + + // Attempt the request up to maxRetries times + for i := 0; i < maxRetries; i++ { + // Make the request + resp, err = service.Client.NewRequestDo("POST", basePath, queryParams, req, nil) + if err == nil { + // If the request was successful, return the response + return resp, nil + } + + // If the request failed with a 404 status code, wait for the retry interval before trying again + if resp != nil && resp.StatusCode == 404 { + time.Sleep(retryInterval) + } else { + // If the status code is not 404, return the response and error immediately + return resp, err + } + } + + // If the function hasn't returned after maxRetries, return an error + return nil, fmt.Errorf("failed to create AWP Onboarding after %d attempts: %w", maxRetries, err) +} + +func (service *Service) GetAWPOnboarding(cloudProvider, id string) (*GetAWPOnboardingResponse, *http.Response, error) { + v := new(GetAWPOnboardingResponse) + path := fmt.Sprintf("workload/agentless/%s/accounts/%s", cloudProvider, id) + resp, err := service.Client.NewRequestDo("GET", path, nil, nil, v) + if err != nil { + return nil, nil, err + } + return v, resp, nil +} + +func (service *Service) DeleteAWPOnboarding(id string, queryParams DeleteOptions) (*http.Response, error) { + path := fmt.Sprintf("%s/%s", awsOnboardingResourcePath, id) + resp, err := service.Client.NewRequestDo("DELETE", path, queryParams, nil, nil) + if err != nil { + return nil, err + } + return resp, nil +} + +func (service *Service) Get() (*AgentlessAwsTerraformOnboardingDataResponse, *http.Response, error) { + v := new(AgentlessAwsTerraformOnboardingDataResponse) + resp, err := service.Client.NewRequestDo("GET", awpAWSGetOnboardingDataPath, nil, nil, v) + if err != nil { + return nil, nil, err + } + + return v, resp, nil +} + +func (service *Service) GetCloudAccountId(externalAccountId string) (string, *http.Response, error) { + path := fmt.Sprintf("%s%s", cloudAccountsPath, externalAccountId) + respData := new(CloudAccountResponse) + log.Printf("[DEBUG] GetCloudAccountId Path: %s", path) + resp, err := service.Client.NewRequestDo("GET", path, nil, nil, respData) + if err != nil { + return "", nil, err + } + return respData.ID, resp, nil +} + +func (service *Service) UpdateAWPSettings(cloudProvider, id string, req AgentlessAccountSettings) (*http.Response, error) { + // Construct the URL path + path := fmt.Sprintf("workload/agentless/%s/accounts/%s/settings", cloudProvider, id) + // Make a PATCH request with the JSON body + resp, err := service.Client.NewRequestDo("PATCH", path, nil, req, nil) + if err != nil { + return nil, err + } + + return resp, nil +} diff --git a/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/service.go b/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/service.go new file mode 100644 index 00000000..f8fa8d95 --- /dev/null +++ b/vendor/github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding/service.go @@ -0,0 +1,14 @@ +package awp_aws_onboarding + +import ( + "github.com/dome9/dome9-sdk-go/dome9" + "github.com/dome9/dome9-sdk-go/dome9/client" +) + +type Service struct { + Client *client.Client +} + +func New(c *dome9.Config) *Service { + return &Service{Client: client.NewClient(c)} +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 99c13ca2..59947aa7 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -56,11 +56,12 @@ github.com/bgentry/go-netrc/netrc github.com/bgentry/speakeasy # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew -# github.com/dome9/dome9-sdk-go v1.18.3 +# github.com/dome9/dome9-sdk-go v1.18.4 github.com/dome9/dome9-sdk-go/dome9 github.com/dome9/dome9-sdk-go/dome9/client github.com/dome9/dome9-sdk-go/services/admissioncontrol/admission_policy github.com/dome9/dome9-sdk-go/services/assessment +github.com/dome9/dome9-sdk-go/services/awp_aws_onboarding github.com/dome9/dome9-sdk-go/services/cloudaccounts github.com/dome9/dome9-sdk-go/services/cloudaccounts/alibaba github.com/dome9/dome9-sdk-go/services/cloudaccounts/aws diff --git a/website/docs/d/awp_aws_onboarding.html.markdown b/website/docs/d/awp_aws_onboarding.html.markdown new file mode 100644 index 00000000..eb99329b --- /dev/null +++ b/website/docs/d/awp_aws_onboarding.html.markdown @@ -0,0 +1,41 @@ +--- +layout: "dome9" +page_title: "Check Point CloudGuard Dome9: dome9_awp_aws_onboarding" +sidebar_current: "docs-datasource-dome9-awp-aws-onboarding" +description: |- + Get information about AWS AWP onboarding in Dome9. +--- + +# Data Source: dome9_awp_aws_onboarding + +Use this data source to get information about AWS AWP onboarding in Dome9. +it gives details information about the awp aws account scanner configurations. + +## Example Usage + +```hcl +data "dome9_awp_aws_onboarding" "test" { + id = "d9-aws-cloudguard-account-id or aws-account-id" +} + +``` + +## Argument Reference + +The following arguments supported: + +* `id` - (Required) The Dome9 id for the onboarded AWS account. + +## Attributes Reference + +In addition to all arguments above, the following attributes exported: + +* `scan_mode` - The scan mode of the onboarding process +* `agentless_account_settings` - The settings for the agentless account that the awp scanner will be configured with. +* `missing_awp_private_network_regions` - The regions missing AWP private network. +* `account_issues` - The issues related to the awp account. +* `cloud_account_id` - The CloudGuard account ID. +* `agentless_protection_enabled` - Whether agentless protection is enabled or not. +* `cloud_provider` - The cloud provider for the onboarding process. +* `should_update` - Whether the onboarding process should be updated. +* `is_org_onboarding` - Whether the onboarding process is for an organization. \ No newline at end of file diff --git a/website/docs/d/awp_aws_onboarding_data.html.markdown b/website/docs/d/awp_aws_onboarding_data.html.markdown new file mode 100644 index 00000000..9da1bb5f --- /dev/null +++ b/website/docs/d/awp_aws_onboarding_data.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "dome9" +page_title: "Check Point CloudGuard Dome9: dome9_awp_aws_onboarding_data" +sidebar_current: "docs-datasource-dome9-awp-aws-get-onboarding-data" +description: |- + Get information about AWS AWP onboarding data in Dome9. +--- + +# Data Source: dome9_awp_aws_onboarding_data + +Use this data source to get information about AWS AWP onboarding data in Dome9. + +## Example Usage + +```hcl +data "dome9_awp_aws_onboarding_data" "test" { + cloud_account_id = "d9-aws-cloud-account-id" +} + +``` + +## Argument Reference + +The following arguments supported: + +* `cloud_account_id` - (Required) The Dome9 id for the onboarded AWS account, + * it can be the dome9 cloudguard account id or the external aws account id. + +## Attributes Reference + +In addition to all arguments above, the following attributes exported: + +* `stage` - The stage of the AWP AWS onboarding process(i.e "prod-us"). +* `region` - The region of the AWP AWS onboarding process. +* `cloud_guard_backend_account_id` - The CloudGuard AWS backend account ID. +* `agentless_bucket_name` - The name of the agentless s3 bucket. +* `remote_functions_prefix_key` - The prefix key for remote functions. +* `remote_snapshots_utils_function_name` - The name of the remote snapshots utility function. +* `remote_snapshots_utils_function_run_time` - The runtime of the remote snapshots utility function. +* `remote_snapshots_utils_function_time_out` - The timeout for the remote snapshots utility function. +* `awp_client_side_security_group_name` - The name of the AWP client-side security group. +* `cross_account_role_external_id` - The external ID for the cross-account role. +* `remote_snapshots_utils_function_s3_pre_signed_url` - The pre-signed URL for the remote snapshots utility function. \ No newline at end of file diff --git a/website/docs/r/awp_aws_onboarding.html.markdown b/website/docs/r/awp_aws_onboarding.html.markdown new file mode 100644 index 00000000..879766be --- /dev/null +++ b/website/docs/r/awp_aws_onboarding.html.markdown @@ -0,0 +1,127 @@ +--- +layout: "dome9" +page_title: "Check Point CloudGuard Dome9: dome9_awp_aws_onboarding" +sidebar_current: "docs-resource-dome9-awp-aws-onboarding" +description: |- + Creates an AWP AWS Onboarding in Dome9 +--- + +# dome9_awp_aws_onboarding + +This resource is used to create and modify AWP AWS Onboarding in CloudGuard Dome9. + +## Example Usage + +Basic usage: + +```hcl +provider "dome9" { + dome9_access_id = "DOME9_ACCESS_ID" + dome9_secret_key = "DOME9_SECRET_KEY" + base_url = "https://api.dome9.com/v2/" +} +provider "aws" { + region = "AWS_REGION" + access_key = "AWS_ACCESS_KEY" + secret_key = "AWS_SECRET_KEY" + token = "AWS_SESSION_TOKEN" +} + + +# There is a need to use this terraform module [terraform-dome9-awp-aws] to create all the prerequisites for the onboarding process (All the needed AWS Resources) +# for further information please refer to the module documentation [terraform-dome9-awp-aws](https://registry.terraform.io/modules/dome9/awp-aws/dome9/latest) +# for more examples (simple and complete), you can visit this github examples [terraform-dome9-awp-aws](https://github.com/dome9/terraform-dome9-awp-aws/blob/master/examples) +# Example for the module use: +module "terraform-dome9-awp-aws" { + source = "github.com/dome9/terraform-dome9-awp-aws" + awp_cloud_account_id = " or " + awp_scan_mode = "" # Valid Values = "inAccount" or "saas" + + # Optional customizations: + # e.g: + # awp_cross_account_role_name = "" + # awp_cross_account_role_external_id = "" + + # Optional account Settings + # e.g: + # awp_account_settings_aws = { + # scan_machine_interval_in_hours = 24 + # disabled_regions = ["ap-northeast-1", "ap-northeast-2", ...] # List of regions to disable + # max_concurrent_scans_per_region = 20 + # custom_tags = { + # tag1 = "value1" + # tag2 = "value2" + # tag3 = "value3" + # ... + # } + # } +} + +# The dome9_awp_aws_onboarding resource defines a Dome9 AWP AWS Onboarding. +# The Dome9 AWP AWS Onboarding resource allows you to onboard an AWS account to Dome9 AWP. +# The cloudguard_account_id attribute is used to specify the CloudGuard account id of the AWS account. +# The cross_account_role_name attribute is used to specify the name of the cross account role that is used to allow AWP to access the AWS account. +# The cross_account_role_external_id attribute is used to specify the external id of the cross account role that is used to allow AWP to access the AWS account. +# The scan_mode attribute is used to specify the scan mode of the Dome9 AWP AWS Onboarding. The valid values are "inAccount" and "saas". +# The agentless_account_settings attribute is used to specify the agentless account settings of the Dome9 AWP AWS Onboarding. +# The disabled_regions attribute is used to specify the disabled regions of the agentless account settings of the Dome9 AWP AWS Onboarding. +# The scan_machine_interval_in_hours attribute is used to specify the scan machine interval in hours of the agentless account settings of the Dome9 AWP AWS Onboarding. +# The max_concurrent_scans_per_region attribute is used to specify the max concurrent scans per region of the agentless account settings of the Dome9 AWP AWS Onboarding. +# The custom_tags attribute is used to specify the custom tags of the agentless account settings of the Dome9 AWP AWS Onboarding. +resource "dome9_awp_aws_onboarding" "awp_aws_onboarding_test" { + cloudguard_account_id = "dome9_cloudaccount_aws.aws_onboarding_account_test.id | | " + cross_account_role_name = "" + cross_account_role_external_id = "" + scan_mode = "" # Valid Values = "inAccount" or "saas" + agentless_account_settings { + disabled_regions = ["us-east-1", "us-west-1", "ap-northeast-1", "ap-southeast-2"] + scan_machine_interval_in_hours = 24 + max_concurrent_scans_per_region = 20 + custom_tags = { + tag1 = "value1" + tag2 = "value2" + tag3 = "value3" + } + } +} + +# The dome9_awp_aws_onboarding data source allows you to get the onboarding data of an AWS account (Optional). +data "dome9_awp_aws_onboarding" "awp_aws_onboarding_test" { + id = dome9_awp_aws_onboarding.awp_aws_onboarding_test.cloudguard_account_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cloudguard_account_id` - (Required) The CloudGuard account id. +* `cross_account_role_name` - (Required) The name of the cross account role. +* `cross_account_role_external_id` - (Required) The external id of the cross account role. +* `scan_mode` - (Required) The scan mode. Valid values are "inAccount", "saas", "inAccountHub", "inAccountSub". +* `agentless_account_settings` - (Optional) The agentless account settings. + * `disabled_regions` - (Optional) The disabled regions. valid values are "af-south-1", "ap-south-1", "eu-north-1", "eu-west-3", "eu-south-1", "eu-west-2", "eu-west-1", "ap-northeast-3", "ap-northeast-2", "me-south-1", "ap-northeast-1", "me-central-1", "ca-central-1", "sa-east-1", "ap-east-1", "ap-southeast-1", "ap-southeast-2", "eu-central-1", "ap-southeast-3", "us-east-1", "us-east-2", "us-west-1", "us-west-2" + * `scan_machine_interval_in_hours` - (Optional) The scan machine interval in hours + * `max_concurrent_scans_per_region` - (Optional) The max concurrent scans per region + * `custom_tags` - (Optional) The custom tags. +* `should_create_policy` - (Optional) Whether to create a policy. Default is true. + +## Attributes Reference + +* `missing_awp_private_network_regions` - The missing AWP private network regions. +* `account_issues` - The account issues. +* `cloud_account_id` - The cloud guard account id. +* `agentless_protection_enabled` - Whether agentless protection is enabled. +* `cloud_provider` - The cloud provider. +* `should_update` - Whether to update. +* `is_org_onboarding` - Whether is org onboarding. + +## Import + +The AWP AWS Onboarding can be imported; use as the import ID. + +For example: + +```shell +terraform import dome9_awp_aws_onboarding.test_awp_aws_onboarding 00000000-0000-0000-0000-000000000000 +```