Yorbox
`yorbox` is a command-line interface (CLI) tool that helps manage tags consistently across infrastructure as code (IaC) frameworks. It is specifically designed to work with [BridgeCrew Yor](https://github.com/bridgecrewio/yor), an open-source tool that enables auto-tagging in IaC, making it possible to trace any resource from code to cloud.
Install / Use
/learn @lonegunmanb/YorboxREADME
Yor Box
yorbox is a command-line interface (CLI) tool that helps manage tags consistently across infrastructure as code (IaC) frameworks. It is specifically designed to work with BridgeCrew Yor, an open-source tool that enables auto-tagging in IaC, making it possible to trace any resource from code to cloud.
However, when writing a reusable Terraform module, Yor's tags are hard-coded and cannot be turned off by a variable.
resource azurerm_kubernetes_cluster "k8s_cluster" {
dns_prefix = "terragoat-${var.environment}"
location = var.location
name = "terragoat-aks-${var.environment}"
resource_group_name = azurerm_resource_group.example.name
identity {
type = "SystemAssigned"
}
default_node_pool {
name = "default"
vm_size = "Standard_D2_v2"
node_count = 2
}
addon_profile {
oms_agent {
enabled = false
}
kube_dashboard {
enabled = true
}
}
role_based_access_control {
enabled = false
}
tags = {
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}
}
This is where YorBox comes in. It scans the tags created by Yor and puts them into a "box" with a variable toggle that allows users to turn it on and off as needed. This makes it easier to manage tags and ensures consistency across your infrastructure. With YorBox, you can take control of your tags and streamline your IaC workflow.
It reads all Terraform files in a directory, adds toggle blocks to all tags of resources and modules that generated by yor, and writes the updated files back to disk.
resource azurerm_kubernetes_cluster "k8s_cluster" {
dns_prefix = "terragoat-${var.environment}"
location = var.location
name = "terragoat-aks-${var.environment}"
resource_group_name = azurerm_resource_group.example.name
identity {
type = "SystemAssigned"
}
default_node_pool {
name = "default"
vm_size = "Standard_D2_v2"
node_count = 2
}
addon_profile {
oms_agent {
enabled = false
}
kube_dashboard {
enabled = true
}
}
role_based_access_control {
enabled = false
}
tags = (/*<box>*/(var.yor_toggle ? /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}/*<box>*/ : {})/*</box>*/)
}
Box Denotation and How it works
Assume we've boxed the tags as follows:
tags = (var.yor_toggle ? {
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
} : {})
What if we'd like to use a different box template, e.g:
tags = (var.yor_toggle ? { for k,v in {
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
} : "my_prefix_${k}"=> v }: {})
How can we remove the previous box and add a new one? Here comes the box denotation. The box denotation is a special comment that tells YorBox where the box starts and ends. It's a special comment that starts with /*<box>*/ and ends with /*</box>*/. YorBox will remove the box denotation and the box itself, and then add a new box with the new template:
tags = (/*<box>*/(var.yor_toggle ? /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}/*<box>*/ : {})/*</box>*/)
The tokens between box denotation would be removed:
tags = ({
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
})
Then YorBox will add a new box with the new template:
tags = (/*<box>*/(var.yor_toggle ? { for k,v in /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}/*<box>*/:"my_prefix_${k}"=>v } : {})/*</box>*/)
A pair of paren would be added to tags attribute if it doesn't have one:
tags = {
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}
Would be boxed as:
tags = (/*<box>*/(var.yor_toggle ? /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}/*<box>*/ : {})/*</box>*/)
That's because of hclwrite's limitation. If we call the following go code:
tags := block.Body().GetAttribute("tags")
if tags == nil {
return
}
tokens := tags.Expr().BuildTokens(hclwrite.Tokens{})
If tags's expression is:
tags = /*<box>*/ (var.yor_toggle ? /*</box>*/{ yor_trace = 123 } /*<box>*/ : {})</box>
Then tokens wouldn't contain the first /*<box>*/ comment token as it would be interpreted as a lead comment token for the whole expression. To make YorBox work we have to ensure that the expression is wrapped with a pair of paren. That's why we add a pair of paren to the expression if it doesn't have one.
Installation
You can install Yor Box using go install command:
go install github.com/lonegunmanb/yorbox@latest
Usage
$ yor tag -d ./
...
$ yorbox -dir <directory path> [-toggleName <toggle name>] [-help]
Flags
-boxTemplate string
Box template to use when adding boxes (default "/*<box>*/(var.{{ .toggleName }} ? /*</box>*/ { yor_trace = 123 } /*<box>*/ : {})/*</box>*/")
-dir string
path to the directory containing .tf files
-help
Print help information
-tagsPrefix string
Prefix for tags applied to resources
-toggleName string
Name of the toggle to add (default "yor_toggle")
# Add "my_toggle" block to all tags in the "terraform" directory
yorbox -dir terraform -toggleName my_toggle
BoxTemplate
The box template is a go template that is used to generate the box. e.g.:
$ yorbox -dir <directory path> -boxTemplate '/*<box>*/(var.{{ .toggleName }} ? { for k,v in /*</box>*/ { yor_trace = 123 } /*<box>*/ : "my_prefix_${k}"=> v} : {})/*</box>*/'
The left side of the box would be /*<box>*/(var.{{ .toggleName }} ? { for k,v in /*</box>*/, the right side of the box would be /*<box>*/ : "my_prefix_${k}"=> v} : {})/*</box>*/, so the boxed tags could be:
tags = (/*<box>*/(var.yor_toggle ? { for k,v in /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.tf"
git_last_modified_at = "2020-06-17 12:59:55"
git_last_modified_by = "nimrodkor@gmail.com"
git_modifiers = "nimrodkor"
git_org = "bridgecrewio"
git_repo = "terragoat"
yor_trace = "6103d111-864e-42e5-899c-1864de281fd1"
}/*<box>*/:"my_prefix_${k}"=>v } : {})/*</box>*/)
Variable in BoxTemplate
The BoxTemplate would be rendered with user-provided variables. e.g., the default box template /*<box>*/(var.{{ .toggleName }} ? /*</box>*/ { yor_trace = 123 } /*<box>*/ : {})/*</box>*/ with the following command:
$ yorbox -dir <directory> -toggleName "my_toggle"
The generated code could be:
tags = (/*<box>*/(var.my_toggle ? /*</box>*/{
git_commit = "898d5beaec7ffdef6df0d7abecff407362e2a74e"
git_file = "terraform/azure/aks.t
