diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml index 484d093a..525ade39 100644 --- a/.catalog-onboard-pipeline.yaml +++ b/.catalog-onboard-pipeline.yaml @@ -12,3 +12,8 @@ offerings: scc: instance_id: 1c7d5f78-9262-44c3-b779-b28fe4d88c37 region: us-south + - name: agents + mark_ready: true + install_type: extension + pre_validation: "tests/scripts/pre-validation-deploy-slz-roks-and-scc-wp-instances.sh" + post_validation: "tests/scripts/post-validation-destroy-slz-roks-and-scc-wp-instances.sh" diff --git a/ibm_catalog.json b/ibm_catalog.json index 3cfafa95..82347eeb 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -284,7 +284,7 @@ } ], "architecture": { - "descriptions": "This architecture supports creating and configuring an Key Protect instance.", + "descriptions": "This architecture supports creating and configuring a Security and Compliance Center Workload Protection instance.", "features": [ { "title": "Creates a Security and Compliance Center instance.", @@ -310,7 +310,75 @@ } ] } - } + }, + { + "label": "Agents", + "name": "agents", + "install_type": "fullstack", + "working_directory": "solutions/agents", + "compliance": {}, + "configuration": [ + { + "key": "ibmcloud_api_key" + }, + { + "key": "scc_workload_protection_agent_agent_name" + }, + { + "key": "scc_workload_protection_agent_agent_namespace" + }, + { + "key": "scc_workload_protection_agent_cluster_name" + }, + { + "key": "scc_workload_protection_agent_access_key" + }, + { + "key": "scc_workload_protection_instance_region" + }, + { + "key": "scc_workload_protection_agent_endpoint_type", + "options": [ + { + "displayname": "Public", + "value": "public" + }, + { + "displayname": "Private", + "value": "private" + } + ] + } + ], + "iam_permissions": [ + { + "service_name": "compliance", + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Manager", + "crn:v1:bluemix:public:iam::::role:Editor" + ] + } + ], + "architecture": { + "descriptions": "This architecture supports creating and configuring Security and Compliance Center Workload Protection agents.", + "features": [ + { + "title": "Creates a Security and Compliance Center Workload Protection agents.", + "description": "Creates and configures a Security and Compliance Center Workload Protection agents." + } + ], + "diagrams": [ + { + "diagram": { + "caption": "Security and Compliance Center Workload Protection Agent", + "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-scc-da/main/reference-architecture/scc-wp-agent.svg", + "type": "image/svg+xml" + }, + "description": "This architecture supports creating and configuring Security and Compliance Center Workload Protection agent resources." + } + ] + } + } ] } ] diff --git a/reference-architecture/scc-wp-agent.svg b/reference-architecture/scc-wp-agent.svg new file mode 100644 index 00000000..0e024064 --- /dev/null +++ b/reference-architecture/scc-wp-agent.svg @@ -0,0 +1,4 @@ + + + +
IBM Cloud
Region
Resource Group
SCC Workload Protection Instance
OpenShift Cluster
Agent
Node Analyzer
KSPM Collector
\ No newline at end of file diff --git a/solutions/agents/README.md b/solutions/agents/README.md index fbf396ba..56f1a262 100644 --- a/solutions/agents/README.md +++ b/solutions/agents/README.md @@ -1,3 +1,10 @@ # Security and Compliance Center Workload Protection Agent solution -(Coming soon) +This solution supports installing and configuring [IBM Cloud Security and Compliance Center Workload Protection agent](https://cloud.ibm.com/docs/workload-protection?topic=workload-protection-getting-started). It uses [sysdig-deploy charts](https://github.com/sysdiglabs/charts/tree/master/charts/sysdig-deploy) which deploys the following components into your cluster: +- Agent +- Node Analyzer +- KSPM Collector + +This solution will deploy and configure the Workload Protections components in an existing cluster to an existing IBM Cloud Security and Compliance Center Workload Protection instance. + +![scc-wp-agent](../../reference-architecture/scc-wp-agent.svg) diff --git a/solutions/agents/catalogValidationValues.json.template b/solutions/agents/catalogValidationValues.json.template new file mode 100644 index 00000000..f48a7e33 --- /dev/null +++ b/solutions/agents/catalogValidationValues.json.template @@ -0,0 +1,3 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY +} diff --git a/solutions/agents/kubeconfig/.gitignore b/solutions/agents/kubeconfig/.gitignore new file mode 100644 index 00000000..632a28fb --- /dev/null +++ b/solutions/agents/kubeconfig/.gitignore @@ -0,0 +1,6 @@ +# Ignore everything +* + +# But not these files... +!.gitignore +!README.md diff --git a/solutions/agents/kubeconfig/README.md b/solutions/agents/kubeconfig/README.md new file mode 100644 index 00000000..e85afee8 --- /dev/null +++ b/solutions/agents/kubeconfig/README.md @@ -0,0 +1,2 @@ +This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the +config.yml used to connect to a kubernetes cluster. diff --git a/solutions/agents/main.tf b/solutions/agents/main.tf new file mode 100644 index 00000000..230e88df --- /dev/null +++ b/solutions/agents/main.tf @@ -0,0 +1,20 @@ +####################################################################################################################### +# SCC WP Agent +####################################################################################################################### + +module "scc_wp_agent" { + source = "terraform-ibm-modules/scc-workload-protection-agent/ibm" + version = "1.2.3" + access_key = var.access_key + cluster_name = var.cluster_name + region = var.region + endpoint_type = var.endpoint_type + name = var.name + namespace = var.namespace + deployment_tag = var.deployment_tag + kspm_deploy = var.kspm_deploy + node_analyzer_deploy = var.node_analyzer_deploy + host_scanner_deploy = var.host_scanner_deploy + cluster_scanner_deploy = var.cluster_scanner_deploy + +} diff --git a/solutions/agents/outputs.tf b/solutions/agents/outputs.tf new file mode 100644 index 00000000..1af9c4c2 --- /dev/null +++ b/solutions/agents/outputs.tf @@ -0,0 +1,8 @@ +######################################################################################################################## +# Outputs +######################################################################################################################## + +output "name" { + description = "Helm chart release name." + value = module.scc_wp_agent.name +} diff --git a/solutions/agents/provider.tf b/solutions/agents/provider.tf new file mode 100644 index 00000000..3bd1f78b --- /dev/null +++ b/solutions/agents/provider.tf @@ -0,0 +1,26 @@ +######################################################################################################################## +# Provider config +######################################################################################################################## + +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} + +provider "kubernetes" { + host = data.ibm_container_cluster_config.cluster_dconfig.host + token = data.ibm_container_cluster_config.cluster_config.token +} + +provider "helm" { + kubernetes { + host = data.ibm_container_cluster_config.cluster_config.host + token = data.ibm_container_cluster_config.cluster_config.token + } +} + +data "ibm_container_cluster_config" "cluster_config" { + cluster_name_id = var.cluster_name + config_dir = "${path.module}/kubeconfig" + endpoint_type = var.cluster_endpoint_type +} diff --git a/solutions/agents/variables.tf b/solutions/agents/variables.tf new file mode 100644 index 00000000..2f8dfc6e --- /dev/null +++ b/solutions/agents/variables.tf @@ -0,0 +1,92 @@ +######################################################################################################################## +# Common variables +######################################################################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The API Key to use for IBM Cloud." + sensitive = true +} + +######################################################################################################################## +# SCC Workload Protection Agent variables +######################################################################################################################## + +variable "name" { + type = string + description = "Helm release name." + default = "ibm-scc-wp-agent" +} + +variable "namespace" { + type = string + description = "Namespace of the Security and Compliance Workload Protection agent." + default = "ibm-scc-wp" +} + +variable "cluster_name" { + type = string + description = "Cluster name to add Security and Compliance Workload Protection agent to." +} + +variable "access_key" { + type = string + description = "Security and Compliance Workload Protection instance access key." + sensitive = true +} + +variable "region" { + type = string + description = "Region where Security and Compliance Workload Protection agent is created." +} + +variable "endpoint_type" { + type = string + description = "Specify the endpoint (public or private) for the Security and Compliance Center Workload Protection service." + default = "private" + validation { + error_message = "The specified endpoint_type can be private or public only." + condition = contains(["private", "public"], var.endpoint_type) + } +} + +variable "deployment_tag" { + type = string + description = "Sets a global tag that will be included in the components. It represents the mechanism from where the components have been installed (terraform, local...)." + default = "terraform" +} + +variable "kspm_deploy" { + type = bool + description = "Deploy Security and Compliance Workload Protection KSPM component." + default = true +} + +variable "node_analyzer_deploy" { + type = bool + description = "Deploy Security and Compliance Workload Protection node analyzer component." + default = true +} + +variable "host_scanner_deploy" { + type = bool + description = "Deploy Security and Compliance Workload Protection host scanner component. If node_analyzer_deploy false, this component will not be deployed." + default = true +} + +variable "cluster_scanner_deploy" { + type = bool + description = "Deploy Security and Compliance Workload Protection cluster scanner component." + default = true +} + + +variable "cluster_endpoint_type" { + type = string + description = "Specify the endpoint (public or private) for the cluster." + default = "private" + validation { + error_message = "The specified cluster_endpoint_type can be private or public only." + condition = contains(["private", "public"], var.cluster_endpoint_type) + } +} diff --git a/solutions/agents/version.tf b/solutions/agents/version.tf new file mode 100644 index 00000000..5d467206 --- /dev/null +++ b/solutions/agents/version.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.3.0, <1.7.0" + + required_providers { + # Lock DA into an exact provider version - renovate automation will keep it updated + ibm = { + source = "ibm-cloud/ibm" + version = "1.65.0" + } + helm = { + source = "hashicorp/helm" + version = "2.13.2" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.30.0" + } + } +} diff --git a/tests/pr_test.go b/tests/pr_test.go index 9e6bbdc5..204ad92f 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -22,6 +22,8 @@ import ( const resourceGroup = "geretain-test-resources" const instanceFlavorDir = "solutions/instances" +const agentFlavorDir = "solutions/agents" +const agentsKubeconfigDir = "solutions/agents/kubeconfig" // Define a struct with fields that match the structure of the YAML data const yamlLocation = "../common-dev-assets/common-go-assets/common-permanent-resources.yaml" @@ -47,6 +49,85 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } +func TestAgentsInSchematics(t *testing.T) { + t.Parallel() + + var region = validRegions[rand.Intn(len(validRegions))] + + // ------------------------------------------------------------------------------------------------------ + // Deploy SLZ ROKS Cluster and SCC Workload Protection instance since it is needed to deploy SCC Workload Protection Agents + // ------------------------------------------------------------------------------------------------------ + + prefix := fmt.Sprintf("slz-%s", strings.ToLower(random.UniqueId())) + realTerraformDir := "./resources/existing-resources/agents" + tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, fmt.Sprintf(prefix+"-%s", strings.ToLower(random.UniqueId()))) + + // Verify ibmcloud_api_key variable is set + checkVariable := "TF_VAR_ibmcloud_api_key" + val, present := os.LookupEnv(checkVariable) + require.True(t, present, checkVariable+" environment variable not set") + require.NotEqual(t, "", val, checkVariable+" environment variable is empty") + + logger.Log(t, "Tempdir: ", tempTerraformDir) + existingTerraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{ + TerraformDir: tempTerraformDir, + Vars: map[string]interface{}{ + "prefix": prefix, + "region": region, + }, + // Set Upgrade to true to ensure latest version of providers and modules are used by terratest. + // This is the same as setting the -upgrade=true flag with terraform. + Upgrade: true, + }) + + terraform.WorkspaceSelectOrNew(t, existingTerraformOptions, prefix) + _, existErr := terraform.InitAndApplyE(t, existingTerraformOptions) + + if existErr != nil { + assert.True(t, existErr == nil, "Init and Apply of temp resources (SLZ-ROKS and Workload SCC Protection Instances) failed") + } else { + + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + Prefix: "scc-wp-agents", + TarIncludePatterns: []string{ + agentFlavorDir + "/*.*", + agentsKubeconfigDir + "/*.*", + }, + ResourceGroup: resourceGroup, + TemplateFolder: agentFlavorDir, + Tags: []string{"test-schematic"}, + DeleteWorkspaceOnFail: false, + WaitJobCompleteMinutes: 60, + Region: region, + }) + + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "access_key", Value: terraform.Output(t, existingTerraformOptions, "access_key"), DataType: "string"}, + {Name: "cluster_name", Value: terraform.Output(t, existingTerraformOptions, "workload_cluster_name"), DataType: "string"}, + {Name: "region", Value: region, DataType: "string"}, + {Name: "endpoint_type", Value: "private", DataType: "string"}, + {Name: "name", Value: options.Prefix, DataType: "string"}, + } + + err := options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") + } + + // Check if "DO_NOT_DESTROY_ON_FAILURE" is set + envVal, _ := os.LookupEnv("DO_NOT_DESTROY_ON_FAILURE") + // Destroy the temporary existing resources if required + if t.Failed() && strings.ToLower(envVal) == "true" { + fmt.Println("Terratest failed. Debug the test and delete resources manually.") + } else { + logger.Log(t, "START: Destroy (existing resources)") + terraform.Destroy(t, existingTerraformOptions) + terraform.WorkspaceDelete(t, existingTerraformOptions, prefix) + logger.Log(t, "END: Destroy (existing resources)") + } +} + func TestInstancesInSchematics(t *testing.T) { t.Parallel() @@ -118,7 +199,7 @@ func TestRunExistingResourcesInstances(t *testing.T) { // ------------------------------------------------------------------------------------ prefix := fmt.Sprintf("scc-exist-%s", strings.ToLower(random.UniqueId())) - realTerraformDir := "./resources/existing-resources" + realTerraformDir := "./resources/existing-resources/instances" tempTerraformDir, _ := files.CopyTerraformFolderToTemp(realTerraformDir, fmt.Sprintf(prefix+"-%s", strings.ToLower(random.UniqueId()))) tags := common.GetTagsFromTravis() region := "us-south" diff --git a/tests/resources/existing-resources/agents/kubeconfig/.gitignore b/tests/resources/existing-resources/agents/kubeconfig/.gitignore new file mode 100644 index 00000000..632a28fb --- /dev/null +++ b/tests/resources/existing-resources/agents/kubeconfig/.gitignore @@ -0,0 +1,6 @@ +# Ignore everything +* + +# But not these files... +!.gitignore +!README.md diff --git a/tests/resources/existing-resources/agents/kubeconfig/README.md b/tests/resources/existing-resources/agents/kubeconfig/README.md new file mode 100644 index 00000000..e85afee8 --- /dev/null +++ b/tests/resources/existing-resources/agents/kubeconfig/README.md @@ -0,0 +1,2 @@ +This directory must exist in source control so the `ibm_container_cluster_config` data lookup can use it to place the +config.yml used to connect to a kubernetes cluster. diff --git a/tests/resources/existing-resources/agents/main.tf b/tests/resources/existing-resources/agents/main.tf new file mode 100644 index 00000000..b291a60b --- /dev/null +++ b/tests/resources/existing-resources/agents/main.tf @@ -0,0 +1,37 @@ +############################################################################## +# Resource Group +############################################################################## + +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.1.5" + # if an existing resource group is not set (null) create a new one using prefix + resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null + existing_resource_group_name = var.resource_group +} + +############################################################################## +# SLZ ROKS Pattern +############################################################################## + +module "landing_zone" { + source = "git::https://github.com/terraform-ibm-modules/terraform-ibm-landing-zone//patterns//roks//module?ref=v5.22.0" + region = var.region + prefix = var.prefix + tags = var.resource_tags + add_atracker_route = false + enable_transit_gateway = false +} + +############################################################################## +# Observability Instances +############################################################################## + +module "scc_wp_instance" { + source = "terraform-ibm-modules/scc-workload-protection/ibm" + version = "1.3.0" + name = "${var.prefix}-scc-wp-instance" + region = var.region + resource_group_id = module.resource_group.resource_group_id + resource_key_name = "${var.prefix}-key" +} diff --git a/tests/resources/existing-resources/agents/outputs.tf b/tests/resources/existing-resources/agents/outputs.tf new file mode 100644 index 00000000..c5db996d --- /dev/null +++ b/tests/resources/existing-resources/agents/outputs.tf @@ -0,0 +1,25 @@ +output "access_key" { + description = "Workload Protection instance access key." + value = module.scc_wp_instance.access_key + sensitive = true +} + +output "cluster_data" { + value = module.landing_zone.cluster_data + description = "Details of OCP cluster." +} + +output "workload_cluster_id" { + value = lookup([for cluster in module.landing_zone.cluster_data : cluster if strcontains(cluster.resource_group_name, "workload")][0], "id", "") + description = "ID of the workload cluster." +} + +output "workload_cluster_name" { + value = [for cluster_name in module.landing_zone.cluster_names : cluster_name if strcontains(cluster_name, "workload")][0] + description = "Name of the workload cluster." +} + +output "cluster_resource_group_id" { + value = lookup([for cluster in module.landing_zone.cluster_data : cluster if strcontains(cluster.resource_group_name, "workload")][0], "resource_group_id", "") + description = "Resource group ID of the workload cluster." +} diff --git a/tests/resources/existing-resources/provider.tf b/tests/resources/existing-resources/agents/provider.tf similarity index 100% rename from tests/resources/existing-resources/provider.tf rename to tests/resources/existing-resources/agents/provider.tf diff --git a/tests/resources/existing-resources/agents/variables.tf b/tests/resources/existing-resources/agents/variables.tf new file mode 100644 index 00000000..f06b8399 --- /dev/null +++ b/tests/resources/existing-resources/agents/variables.tf @@ -0,0 +1,32 @@ +######################################################################################################################## +# Common variables +######################################################################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The API Key to use for IBM Cloud." + sensitive = true +} + +variable "prefix" { + type = string + description = "Prefix to append to all resources created by this solution." +} + +variable "resource_group" { + type = string + description = "The name of an existing resource group to provision resources in to. If not set a new resource group will be created using the prefix variable" + default = null +} + +variable "region" { + type = string + default = "us-south" + description = "The region in which to provision SCC resources." +} + +variable "resource_tags" { + type = list(string) + description = "Optional list of tags to be added to created resources" + default = [] +} diff --git a/tests/resources/existing-resources/version.tf b/tests/resources/existing-resources/agents/version.tf similarity index 100% rename from tests/resources/existing-resources/version.tf rename to tests/resources/existing-resources/agents/version.tf diff --git a/tests/resources/existing-resources/README.md b/tests/resources/existing-resources/instances/README.md similarity index 100% rename from tests/resources/existing-resources/README.md rename to tests/resources/existing-resources/instances/README.md diff --git a/tests/resources/existing-resources/main.tf b/tests/resources/existing-resources/instances/main.tf similarity index 100% rename from tests/resources/existing-resources/main.tf rename to tests/resources/existing-resources/instances/main.tf diff --git a/tests/resources/existing-resources/outputs.tf b/tests/resources/existing-resources/instances/outputs.tf similarity index 100% rename from tests/resources/existing-resources/outputs.tf rename to tests/resources/existing-resources/instances/outputs.tf diff --git a/tests/resources/existing-resources/instances/provider.tf b/tests/resources/existing-resources/instances/provider.tf new file mode 100644 index 00000000..df45ef50 --- /dev/null +++ b/tests/resources/existing-resources/instances/provider.tf @@ -0,0 +1,4 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region +} diff --git a/tests/resources/existing-resources/variables.tf b/tests/resources/existing-resources/instances/variables.tf similarity index 100% rename from tests/resources/existing-resources/variables.tf rename to tests/resources/existing-resources/instances/variables.tf diff --git a/tests/resources/existing-resources/instances/version.tf b/tests/resources/existing-resources/instances/version.tf new file mode 100644 index 00000000..e128ec26 --- /dev/null +++ b/tests/resources/existing-resources/instances/version.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.3.0" + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = ">= 1.51.0" + } + } +} diff --git a/tests/scripts/post-validation-destroy-slz-roks-and-scc-wp-instances.sh b/tests/scripts/post-validation-destroy-slz-roks-and-scc-wp-instances.sh new file mode 100644 index 00000000..7dd0bb61 --- /dev/null +++ b/tests/scripts/post-validation-destroy-slz-roks-and-scc-wp-instances.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +######################################################################################################################## +## This script is used by the catalog pipeline to destroy the SLZ ROKS Cluster, which was provisioned as a ## +## prerequisite for the WAS extension that is published to the catalog ## +######################################################################################################################## + +set -e + +TERRAFORM_SOURCE_DIR="tests/resources/existing-resources/agents" +TF_VARS_FILE="terraform.tfvars" + +( + cd ${TERRAFORM_SOURCE_DIR} + echo "Destroying prerequisite SLZ ROKS Cluster and SCC workload protection instances .." + terraform destroy -input=false -auto-approve -var-file=${TF_VARS_FILE} || exit 1 + + echo "Post-validation completed successfully" +) diff --git a/tests/scripts/pre-validation-deploy-slz-roks-and-scc-wp-instances.sh b/tests/scripts/pre-validation-deploy-slz-roks-and-scc-wp-instances.sh new file mode 100644 index 00000000..016e3c87 --- /dev/null +++ b/tests/scripts/pre-validation-deploy-slz-roks-and-scc-wp-instances.sh @@ -0,0 +1,51 @@ +#! /bin/bash + +############################################################################################################ +## This script is used by the catalog pipeline to deploy the SLZ ROKS and SCC workload protection instances, +## which are the prerequisites for the SCC workload protection agents extension. +############################################################################################################ + +set -e + +DA_DIR="solutions/agents" +TERRAFORM_SOURCE_DIR="tests/resources/existing-resources/agents" +JSON_FILE="${DA_DIR}/catalogValidationValues.json" +REGION="us-south" +TF_VARS_FILE="terraform.tfvars" + +( + cwd=$(pwd) + cd ${TERRAFORM_SOURCE_DIR} + echo "Provisioning prerequisite SLZ ROKS CLUSTER and SCC workload protection instances .." + terraform init || exit 1 + $VALIDATION_APIKEY is available in the catalog runtime + { + echo "ibmcloud_api_key=\"${VALIDATION_APIKEY}\"" + echo "region=\"${REGION}\"" + echo "prefix=\"slz-$(openssl rand -hex 2)\"" + } >> ${TF_VARS_FILE} + terraform apply -input=false -auto-approve -var-file=${TF_VARS_FILE} || exit 1 + + region_var_name="region" + cluster_name_var_name="cluster_name" + cluster_name_value=$(terraform output -state=terraform.tfstate -raw workload_cluster_name) + cluster_resource_group_id_var_name="cluster_resource_group_id" + cluster_resource_group_id_value=$(terraform output -state=terraform.tfstate -raw workload_cluster_id) + access_key_var_name="access_key" + access_key_value=$(terraform output -state=terraform.tfstate -raw access_key) + + echo "Appending '${cluster_name_var_name}' and '${region_var_name}' input variable values to ${JSON_FILE}.." + + cd "${cwd}" + jq -r --arg region_var_name "${region_var_name}" \ + --arg region_var_value "${REGION}" \ + --arg cluster_name_var_name "${cluster_name_var_name}" \ + --arg cluster_name_value "${cluster_name_value}" \ + --arg cluster_resource_group_id_var_name "${cluster_resource_group_id_var_name}" \ + --arg cluster_resource_group_id_value "${cluster_resource_group_id_value}" \ + --arg access_key_var_name "${access_key_var_name}" \ + --arg access_key_value "${access_key_value}" \ + '. + {($region_var_name): $region_var_value, ($cluster_name_var_name): $cluster_name_value, ($cluster_resource_group_id_var_name): $cluster_resource_group_id_value, ($access_key_var_name): $access_key_value}' "${JSON_FILE}" > tmpfile && mv tmpfile "${JSON_FILE}" || exit 1 + + echo "Pre-validation complete successfully" +)