Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,37 @@ venv.bak/
dmypy.json

# Pyre type checker
.pyre/
.pyre/

# Local .terraform directories
**/.terraform/*

# Terraform lockfile
.terraform.lock.hcl

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore CLI configuration files
.terraformrc
terraform.rc

out/*
.DS_Store
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,38 @@ Migrate workloads from other platforms to [StackGuardian Platform](https://app.s
- Terraform
- terraform login to ensure that Terraform can interact with your Terraform Cloud/Enterprise account.
- [sg-cli](https://github.com/StackGuardian/sg-cli/tree/main/shell)

### Perform terraform login
`terraform login`

### Export the resource definitions and Terraform state

- Choose the transformer and locate the example of `terraform.tfvars`.
- Edit that file ( terraform.tfvars) to match your context.
- Run the following commands:

```shell
cd transformer/tfc
terraform init
terraform apply -auto-approve -var-file=terraform.tfvars
```

A new `out` folder should have been created. The `sg-payload.json` file contains the definition for each workflow that will be created for each Terraform Workspace, and the `state-files` folder contains the files for the Terraform state for each of your workspaces, if the state export was enabled.

After completing the export , edit the `sg-payload.json` file to provide tune each workflow configuration with the following:
- `DeploymentPlatformConfig` - (Used to authenticate against a cloud provider using a StackGuardian Integration), Create the relevant integration in StackGuardian platform and update `DeploymentPlatformConfig.kind` from the following "AZURE_STATIC", "AWS_STATIC","GCP_STATIC", "AWS_RBAC". Update `DeploymentPlatformConfig.config.integrationId` with "/integrations/INTEGRRATION_NAME" and `DeploymentPlatformConfig.config.profileName` with the name of the integration used upon creation.
- `VCSConfig` - Provide full path to the `repo` like as well the relevant `sourceConfigDestKind` from the following "GITHUB_COM", "BITBUCKET_ORG", "GITLAB_COM", "AZURE_DEVOPS".

### Bulk import workflows to StackGuardian Platform

- Fetch sg-cli (https://github.com/StackGuardian/sg-cli.git) and set up sg-cli locally (documentation present in repo)
- Run the following commands and pass the `sg-payload.json` as payload (represented below)

```shell
cd ../../out

Get your SG API Key here: https://app.stackguardian.io/orchestrator/orgs/<org-id>/settings?tab=api_key

export SG_API_TOKEN=<YOUR_SG_API_TOKEN>
wget -q "$(wget -qO- "https://api.github.com/repos/stackguardian/sg-cli/releases/latest" | jq -r '.tarball_url')" -O sg-cli.tar.gz && tar -xf sg-cli.tar.gz && rm -f sg-cli.tar.gz && /bin/cp -rf StackGuardian-sg-cli*/shell/sg-cli . && rm -rfd StackGuardian-sg-cli* && ./sg-cli workflow create --bulk --org "stackguardian" -- sg-payload.json
```
29 changes: 29 additions & 0 deletions transformer/tfc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Local .terraform directories
**/.terraform/*

# Terraform lockfile
.terraform.lock.hcl

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Ignore CLI configuration files
.terraformrc
terraform.rc
70 changes: 0 additions & 70 deletions transformer/tfc/main.py

This file was deleted.

98 changes: 52 additions & 46 deletions transformer/tfc/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,75 +23,81 @@ locals {
workflow_ids = [for i, v in data.tfe_workspace_ids.all.ids : v]
workflow_names = [for i, v in data.tfe_workspace_ids.all.ids : i]
workflows = [for i, v in data.tfe_workspace_ids.all.ids : {
ResourceName = data.tfe_workspace.all[i].name
wfgrpName = ""
Description = ""
Tags = data.tfe_workspace.all[i].tag_names
EnvironmentVariables = [for i, v in data.tfe_variables.all[v].variables : {
hcl = v.hcl
name = v.category == "terraform" ? "TF_VAR_${v.name}" : v.name
sensitive = v.sensitive
value = v.value
}]
CLIConfiguration = {
"WorkflowGroup":{
"name": data.tfe_workspace.all[i].project_id
},
"TfStateFilePath" : "${abspath(path.root)}/../../out/state-files/${data.tfe_workspace.all[i].name}.tfstate"
}
ResourceName = data.tfe_workspace.all[i].name
wfgrpName = ""
Description = ""
Tags = data.tfe_workspace.all[i].tag_names
EnvironmentVariables = [for i, v in data.tfe_variables.all[v].variables :
{ "config" : {
"textValue" : v.value,
"varName" : v.name
},
"kind" : "PLAIN_TEXT" } if v.category == "env" && v.sensitive == false]

DeploymentPlatformConfig = []
RunnerConstraints = {"type": "shared"}
RunnerConstraints = { "type" : "shared" }
VCSConfig = {
"iacVCSConfig": {
"useMarketplaceTemplate": false,
"customSource": {
"sourceConfigDestKind": "",
"config": {
"includeSubModule": false,
"ref": length(data.tfe_workspace.all[i].vcs_repo) > 0 ? data.tfe_workspace.all[i].vcs_repo[0].branch != "" ? data.tfe_workspace.all[i].vcs_repo[0].branch : var.vcs_default_branch : var.vcs_default_branch,
"isPrivate": true,
"auth": "/integrations/<integration-name>",
"workingDir": "",
"repo": length(data.tfe_workspace.all[i].vcs_repo) > 0 ? split("/", data.tfe_workspace.all[i].vcs_repo[0].identifier)[1] : ""
"iacVCSConfig" : {
"useMarketplaceTemplate" : false,
"customSource" : {
"sourceConfigDestKind" : "PLEASE PROVIDE A VALUE",
"config" : {
"includeSubModule" : false,
"ref" : length(data.tfe_workspace.all[i].vcs_repo) > 0 ? data.tfe_workspace.all[i].vcs_repo[0].branch != "" ? data.tfe_workspace.all[i].vcs_repo[0].branch : "" : "",
"isPrivate" : true,
"auth" : "PLEASE PROVIDE A VALUE",
"workingDir" : "",
"repo" : length(data.tfe_workspace.all[i].vcs_repo) > 0 ? split("/", data.tfe_workspace.all[i].vcs_repo[0].identifier)[1] : ""
}
}
},
"iacInputData": {
"schemaType": "RAW_JSON",
"data": {}
"iacInputData" : {
"schemaType" : "RAW_JSON",
"data" : { for i, v in data.tfe_variables.all[v].variables : v.name => v.value if v.category == "terraform" }
}
}

MiniSteps = {
"wfChaining": {
"ERRORED": [],
"COMPLETED": []
"wfChaining" : {
"ERRORED" : [],
"COMPLETED" : []
},
"notifications": {
"email": {
"ERRORED": [],
"COMPLETED": [],
"APPROVAL_REQUIRED": [],
"CANCELLED": []
"notifications" : {
"email" : {
"ERRORED" : [],
"COMPLETED" : [],
"APPROVAL_REQUIRED" : [],
"CANCELLED" : []
}
}
}

Approvers = []

TerraformConfig = {
"managedTerraformState": var.export_state,
"terraformVersion": data.tfe_workspace.all[i].terraform_version
"managedTerraformState" : var.export_state,
"terraformVersion" : data.tfe_workspace.all[i].terraform_version
}

WfType = ""
UserSchedules = []
WfType = "TERRAFORM"
UserSchedules = []
}]
data = jsonencode({
"workflows" : local.workflows
})
data = jsonencode(
local.workflows
)
}

data "tfe_workspace_ids" "all" {
exclude_tags = var.tfc_workspace_exclude_tags
names = var.tfc_workspace_names
organization = var.tfc_organization
tag_names = var.tfc_workspace_include_tags
exclude_tags = var.tfc_workspace_exclude_tags
}

data "tfe_workspace" "all" {
Expand All @@ -109,7 +115,7 @@ data "tfe_variables" "all" {

resource "local_file" "data" {
content = local.data
filename = "${path.module}/../../out/data.json"
filename = "${path.module}/../../out/sg-payload.json"
}

resource "local_file" "generate_temp_tf_files" {
Expand Down
18 changes: 0 additions & 18 deletions transformer/tfc/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,3 @@ variable "tfc_workspace_include_tags" {
description = "List of TFC/TFE workspace tags to include when exporting. Excluded tags take precedence over included ones. Wildcards are not supported."
type = list(string)
}

variable "vcs_default_branch" {
default = "main"
description = "Name of the repositories' default branch"
type = string
}

variable "vcs_namespace" {
default = ""
description = "The name of the entity containing the repository. The value should be empty for GitHub.com, the user/organization for GitHub (custom application), the project for Bitbucket, and the namespace for Gitlab."
type = string
}

variable "vcs_provider" {
default = "github"
description = "Name of the Version Control System (VCS) provider to use"
type = string
}