Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
aniket_singh
ServiceNow Employee
ServiceNow Employee

Add new cloud provider in Terraform Connector (AWS) - Cloud/Enterprise

Step 1: Terraform AWS authentication

Step 2: Configure an AWS Datacenter Resource Block

Terraform simplifies the orchestration of cloud deployments, helping operators build small- to large-scale multi-cloud infrastructures. Instead of creating specific CloudFormation templates for AWS, ARM templates for Azure, and Cloud Deployment Manager for GCP, Terraform lets you deploy across multiple providers using 'template’ files. The ServiceNow Cloud Management application (with the Terraform Connector from the ServiceNow Store) provides out of the box support for providers such as VMware, IBM, and MS Azure clouds.

This article takes you through the procedures or steps needed to add a new cloud provider (AWS, in this example) to the Terraform Connector Store app. The main steps are:
1. Map Credentials between Cloud Management and Terraform.
2. Add a Terraform orchestration interface on a resource block.
After you have mapped the credentials and configured the resource block you can proceed to:
3. Create a Terraform config provider and run Discovery (Enterprise)
4. Create catalog items based on Terraform templates.

Step 1: Terraform AWS authentication:
The ServiceNow Cloud Management application supports credentials where we use access_key and secret_key as variable defined in the template. The values of `keys’ are mapped from Discovery credentials.
You can use the (Infrastructure as Code) IaC Provider Settings user interface to perform credential and service account mappings for DataCenter credentials used by the Terraform provider to provision data center resources and Cloud Management for discovery. Mapping credential and service account fields between Cloud Management and Terraform using the IaC Provider Settings enables you to store and manage credentials in an external credential repository rather than directly in a ServiceNow credentials record. See product documentation for detailed steps.

 

 

Step 2: Configure an AWS Datacenter Resource Block:
Add the Terraform Orchestration interface on a resource block, to execute cloud-based operations via terraform templates. The product documentation has detailed instructions on setting up an Azure Datacenter resource block. The procedure is mostly similar except that the response processor scripts in this article are specifically for AWS Create Stack and Delete Stack operations. Similarly, you will need to create custom response processors for different resource types, e.g. if you want to add support for GCP and deploy a GCP cloud db - then a response mapping must be done for the cloud db instance.

- Go to Cloud Admin Portal à Design --> ResourceBlock --> AWS Datacenter
- Add Terraform Orchestration Interface to AWS Datacenter

 

 

- Add a step to CreateStack operation:

Form ParameterValue
Operation TypeInvoke Flow
Content TypeSubflow
SubflowTFEProvision
Condition'${Script:sn_cmp_terraform.GetWorkloadProperties.isEnterpriseTF[arg=${parameter.WorkloadConfigProvider}]}' == 'YES'

 

 - Step Parameter Mapping:

     Parameter                                                                             Value
config_provider_id$(ci.cmdb_ci_workload_config_provider[name=${parameter.WorkloadConfigProvider}].sys_id)
environment_variables${parameter.environment_variables}
flowcorrelationid$(Script:CMPFlowStepHandler.generateCorrelationId)
provider_credential_id$(Script:sn_cmp_terraform.GetWorkloadProperties.getProviderCredentialId[arg=$(context.ServiceAccountID)])
provider_variables$(Script:sn_cmp_terraform.GetWorkloadProperties.getProviderParams[arg=${parameter.ProviderParameters},arg=$(context.ServiceAccountID)])
terraform_variables$(Script:sn_cmp_terraform.TerraformCommandUtils.getRegionForTF[arg=${parameter.templateParameters},arg=$(context.order.sys_id)])
vcs_repository_id$(Script:sn_cmp_terraform.GetWorkloadProperties.getVcsRepoId[arg=${parameter.ConfigurationName},arg=$(ci.cmdb_ci_workload_config_provider[name=${parameter.WorkloadConfigProvider}].sys_id)])
workspace_name $(Script:sn_cmp_terraform.GetWorkloadProperties.generateWorkspaceName[arg=$(context.order.stack)])

 

- Create response processor: AWS_TFE_CreateStack_Response_Processor:

 

Script Content:

function processResponse(response, cloudServiceAccountId, ldc,
correlationId, step, requestorContext, stackId) {
var responseObject = global.JSON.parse(response);

var processor = new sn_cmp_terraform.TerraformResponseProcessor();
var processedResponses = processor.processResponse(responseObject.state, cloudServiceAccountId, ldc,
correlationId, step, requestorContext, stackId);

var configObjectID = '';
//Get workload provider id from API Step
var providerId = new sn_cmp_terraform.GetWorkloadProperties().getOrderStepInputParameterValue(correlationId, 'config_provider_id');

var gr = new GlideRecord("cmdb_ci_workload_config_provider");
if (gr.get(providerId))
configObjectID = gr.object_id + '';

var workspaceResp = responseObject.workspace;
var workspaceRespData = workspaceResp['data'];
var templateInfo = {
"cmdb_ci_tfe_workspace": {
"identification": {
"cmdb_ci_tfe_org": {
"criterion": {
"object_id": configObjectID
}
},
"cmdb_ci_tfe_workspace": {
"criterion": {
"object_id": workspaceRespData.id
}
},
},
"attributes": {
"name": workspaceRespData.attributes['name'],
"object_id": workspaceRespData.id,
"terraform_version": workspaceRespData.attributes['terraform-version'],
"description": workspaceRespData.attributes['description'],
"permissions": global.JSON.stringify(workspaceRespData.attributes['permissions']),
"actions": global.JSON.stringify(workspaceRespData.attributes['actions']),
"auto_apply": workspaceRespData.attributes['auto_apply']
},
"relationships": {}
}
};

processedResponses.push(templateInfo);
return global.JSON.stringify(processedResponses);
}

 

Final CreateStack Configuration:

 

- Add a step to DeleteStack operation:

Form ParameterValue
Operation TypeInvoke Flow
Content TypeSubflow
SubflowTFEDeprovision
Condition'${Script:sn_cmp_terraform.GetWorkloadProperties.isEnterpriseTF[arg=${parameter.WorkloadConfigProvider}]}' == 'YES'

 

 

- Input Parameter Mapping:

     Parameter                                                                             Value
config_provider_id$(ci.cmdb_ci_workload_config_provider[name=${parameter.WorkloadConfigProvider}].sys_id)
flowcorrelationid$(Script:CMPFlowStepHandler.generateCorrelationId)
workspace_id$(Script:sn_cmp_terraform.GetWorkloadProperties.getWorkspaceSysID[arg=$(context.order.stack)])

 

Create response processor: AWS_TFE_DeleteStack_Response_Processor:

 

Script Content :

function processResponse(response, cloudServiceAccountId, ldc, correlationId,
step, requestorContext, stackId) {

var responseObject = global.JSON.parse(response);
var tfStateAfter = responseObject.state.after;
var tfStateBefore = responseObject.state.before;

var processor = new sn_cmp_terraform.DeprovisionTerraformResponseProcessor();

//there is no support for before state currently, hence its handled internally
var retiredStackItems = processor.updateStackItemTermination(stackId, tfStateBefore, tfStateAfter);
if (retiredStackItems)
gs.info("Retired CI's of stack items");
else
gs.warn("Haven't retired CI's of stack items");

return global.JSON.stringify([{}]);
}

 

Final Mapping:

 

Next Steps:
Create a Terraform config provider and run Discovery
Create catalog items based on Terraform templates

Reference material:
Resource Blocks
Configure a Response Processor
Execute response processor for workflow
Create a CI class for virtual cloud resource
Virtual server response processor example (AWS VM CIs)

Setup New terraform provider using Terraform Opensource

Comments
Rob50
Tera Contributor

Hi @aniket.singh@servicenow,

Thanks for putting this together, it is really useful. In the instructions it mentions:

"Settings enables you to store and manage credentials in an external credential repository rather than directly in a ServiceNow credentials record"

Does this mean the credentials are stored in Terraform and the integration references those parameters stored in the Terraform instance? Additionally, what script is leveraged to map the credentials?

Is it possible to get this community article transferred into a KB article, as it is extremely helpful and would be a lot easier to find. It would be great if the cloud management advanced course could include sections on this plugin as it appears to be the direction the platform is heading.

Thanks,

Rob

Version history
Last update:
‎07-31-2020 01:21 AM
Updated by: