Skip to content
Open
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
2 changes: 1 addition & 1 deletion src/terraform/structure/terraform_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type TerraformBlock struct {
HclSyntaxBlock *hclsyntax.Block
}

var ProviderToTagAttribute = map[string]string{"aws": "tags", "azurerm": "tags", "google": "labels", "oci": "freeform_tags", "alicloud": "tags"}
var ProviderToTagAttribute = map[string]string{"aws": "tags", "azurerm": "tags", "google": "labels", "oci": "freeform_tags", "alicloud": "tags", "kubernetes": "metadata.annotations"}

const ResourceBlockType = "resource"
const ModuleBlockType = "module"
Expand Down
58 changes: 52 additions & 6 deletions src/terraform/structure/terraform_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var unsupportedTerraformBlocks = []string{
"aws_cloudwatch_log_destination", // This resource does not support tags, although docs state otherwise.
"google_monitoring_notification_channel", // This resource uses labels for other purposes.
"aws_secretsmanager_secret_rotation", // This resource does not support tags, although tfschema states otherwise.
"kubernetes_manifest", // This resource specifically supports tags with a different structure.
}

var taggableResourcesLock sync.RWMutex
Expand Down Expand Up @@ -278,10 +279,54 @@ func (p *TerraformParser) WriteFile(readFilePath string, blocks []structure.IBlo
return nil
}

func GetTags(block *hclwrite.Block, tagsAttributeName string) *hclwrite.Attribute {
block = GetTagsBlock(block, tagsAttributeName)

if strings.Contains(tagsAttributeName, ".") {
parts := strings.Split(tagsAttributeName, ".")

if block == nil {
return nil
}
logger.Debug(fmt.Sprintf("Trying to get attribute %v from %v", parts[len(parts)-1], block))
return block.Body().GetAttribute(parts[len(parts)-1])
} else {
return block.Body().GetAttribute(tagsAttributeName);
}
}

func SetTags(block *hclwrite.Block, tagsAttributeName string, newTags hclwrite.Tokens) {
block = GetTagsBlock(block, tagsAttributeName)

if strings.Contains(tagsAttributeName, ".") {
parts := strings.Split(tagsAttributeName, ".")

logger.Debug(fmt.Sprintf("Trying to set attribute %v on %v with value %v", parts[len(parts)-1], block, newTags))
block.Body().SetAttributeRaw(parts[len(parts)-1], newTags)
} else {
block.Body().SetAttributeRaw(tagsAttributeName, newTags);
}
}

func GetTagsBlock(block *hclwrite.Block, tagsAttributeName string) *hclwrite.Block {
if strings.Contains(tagsAttributeName, ".") {
parts := strings.Split(tagsAttributeName, ".")

for _, part := range parts[0:len(parts)-1] {
logger.Debug(fmt.Sprintf("Trying to get block %v from %v", part, block))
block = block.Body().FirstMatchingBlock(part, nil)
}

return block
} else {
return block
}
}

func (p *TerraformParser) modifyBlockTags(rawBlock *hclwrite.Block, parsedBlock structure.IBlock) {
mergedTags := parsedBlock.MergeTags()
tagsAttributeName := parsedBlock.(*TerraformBlock).TagsAttributeName
tagsAttribute := rawBlock.Body().GetAttribute(tagsAttributeName)
tagsAttribute := GetTags(rawBlock, tagsAttributeName)

// we don't add tags to data sources
if rawBlock.Type() == "data" {
Expand All @@ -291,7 +336,7 @@ func (p *TerraformParser) modifyBlockTags(rawBlock *hclwrite.Block, parsedBlock
if tagsAttribute == nil {
mergedTagsTokens := buildTagsTokens(mergedTags)
if mergedTagsTokens != nil {
rawBlock.Body().SetAttributeRaw(tagsAttributeName, mergedTagsTokens)
SetTags(rawBlock, tagsAttributeName, mergedTagsTokens)
}
} else {
rawTagsTokens := tagsAttribute.Expr().BuildTokens(hclwrite.Tokens{})
Expand Down Expand Up @@ -362,7 +407,7 @@ func (p *TerraformParser) modifyBlockTags(rawBlock *hclwrite.Block, parsedBlock
} else {
rawTagsTokens = InsertTokens(rawTagsTokens, newTagsTokens[2:len(newTagsTokens)-2]) // checkov:skip=CKV_SECRET_80 false positive
}
rawBlock.Body().SetAttributeRaw(tagsAttributeName, rawTagsTokens)
SetTags(rawBlock, tagsAttributeName, rawTagsTokens)
return
}

Expand Down Expand Up @@ -399,7 +444,7 @@ func (p *TerraformParser) modifyBlockTags(rawBlock *hclwrite.Block, parsedBlock
}
}
// Set the body's tags to the new built tokens
rawBlock.Body().SetAttributeRaw(tagsAttributeName, rawTagsTokens)
SetTags(rawBlock, tagsAttributeName, rawTagsTokens)
}
}

Expand Down Expand Up @@ -660,7 +705,8 @@ func (p *TerraformParser) getExistingTags(hclBlock *hclwrite.Block, tagsAttribut
isTaggable := false
existingTags := make([]tags.ITag, 0)

tagsAttribute := hclBlock.Body().GetAttribute(tagsAttributeName)
tagsAttribute := GetTags(hclBlock, tagsAttributeName)

if tagsAttribute != nil {
// if tags exists in resource
isTaggable, _ = p.isBlockTaggable(hclBlock)
Expand Down Expand Up @@ -873,7 +919,7 @@ func (p *TerraformParser) getModuleTags(hclBlock *hclwrite.Block, tagsAttributeN
isTaggable := false
existingTags := make([]tags.ITag, 0)

tagsAttribute := hclBlock.Body().GetAttribute(tagsAttributeName)
tagsAttribute := GetTags(hclBlock, tagsAttributeName)
if tagsAttribute != nil {
// if tags exists in module
isTaggable = true
Expand Down
22 changes: 22 additions & 0 deletions src/terraform/structure/tf_taggable.go
Original file line number Diff line number Diff line change
Expand Up @@ -676,4 +676,26 @@ var TfTaggableResourceTypes = []string{
"google_tpu_node",
"google_vertex_ai_dataset",
"google_workflows_workflow",
"kubernetes_cluster_role",
"kubernetes_cluster_role_binding",
"kubernetes_config_map",
"kubernetes_config_map_v1",
"kubernetes_cron_job_v1",
"kubernetes_deployment",
"kubernetes_deployment_v1",
"kubernetes_horizontal_pod_autoscaler_v2",
"kubernetes_ingress_v1",
"kubernetes_namespace",
"kubernetes_namespace_v1",
"kubernetes_persistent_volume_claim",
"kubernetes_persistent_volume_claim_v1",
"kubernetes_role_binding_v1",
"kubernetes_role_v1",
"kubernetes_secret",
"kubernetes_secret_v1",
"kubernetes_service",
"kubernetes_service_account",
"kubernetes_service_account_v1",
"kubernetes_service_v1",
"kubernetes_stateful_set",
}
Loading