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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "cec6e005-9309-46eb-b34b-456f6eae818b",
"queryName": "Beta - Key Vault Purge Protection Is Enabled",
"severity": "HIGH",
"category": "Backup",
"descriptionText": "Deleting an Azure Key Vault without purge protection enabled can cause permanent loss of keys, secrets, and certificates, leading to unrecoverable data loss and disruption of dependent services.",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault",
"platform": "Terraform",
"descriptionID": "cec6e005",
"cloudProvider": "azure",
"cwe": "530",
"riskScore": "8.5",
"experimental": "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package Cx

import data.generic.terraform as tf_lib
import data.generic.common as common_lib

CxPolicy[result] {
key_vault := input.document[i].resource.azurerm_key_vault[name]

res := get_res(key_vault, name)

result := {
"documentId": input.document[i].id,
"resourceType": "azurerm_key_vault",
"resourceName": tf_lib.get_resource_name(key_vault, name),
"searchKey": res["sk"],
"searchLine": res["sl"],
"issueType": res["it"],
"keyExpectedValue": res["kev"],
"keyActualValue": res["kav"],
"remediation": res["rem"],
"remediationType": res["rtype"],
}
}

get_res(resource, name) = res {
not common_lib.valid_key(resource, "purge_protection_enabled")

res := {
"it": "MissingAttribute",
"sk": sprintf("azurerm_key_vault[%s]", [name]),
"sl": common_lib.build_search_line(["resource", "azurerm_key_vault", name], []),
"kev": "'purge_protection_enabled' should be defined and set to true",
"kav": "'purge_protection_enabled' is not defined",
"rem": "purge_protection_enabled = true",
"rtype": "addition"
}
} else = res {
not resource.purge_protection_enabled == true

res := {
"it": "IncorrectValue",
"sk": sprintf("azurerm_key_vault[%s].purge_protection_enabled", [name]),
"sl": common_lib.build_search_line(["resource", "azurerm_key_vault", name, "purge_protection_enabled"], []),
"kev": "'purge_protection_enabled' field should be set to true",
"kav": "'purge_protection_enabled' is not set to true",
"rem": json.marshal({
"before": "false",
"after": "true"
}),
"rtype": "replacement"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "azurerm_key_vault" "negative1" {
name = "examplekeyvault"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
purge_protection_enabled = true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "azurerm_key_vault" "positive1" {
name = "examplekeyvault"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
purge_protection_enabled = false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "azurerm_key_vault" "positive2" {
name = "examplekeyvault"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"queryName": "Beta - Key Vault Purge Protection Is Enabled",
"severity": "HIGH",
"line": 8,
"fileName": "positive1.tf"
},
{
"queryName": "Beta - Key Vault Purge Protection Is Enabled",
"severity": "HIGH",
"line": 1,
"fileName": "positive2.tf"
}
]
6 changes: 4 additions & 2 deletions pkg/remediation/remediation.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ type Report struct {

// Query includes all the files that presents a result related to the queryID
type Query struct {
Files []File `json:"files"`
QueryID string `json:"query_id"`
Files []File `json:"files"`
QueryID string `json:"query_id"`
Experimental bool `json:"experimental"`
}

// File presents the result information related to the file
Expand All @@ -42,6 +43,7 @@ type Remediation struct {
SearchKey string
ExpectedValue string
ActualValue string
Experimental bool
}

// Set includes all the replacements and additions related to a file
Expand Down
12 changes: 7 additions & 5 deletions pkg/remediation/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func scanTmpFile(
tmpFile, queryID string,
remediated []byte,
openAPIResolveReferences bool,
maxResolverDepth int) ([]model.Vulnerability, error) {
maxResolverDepth int,
experimental bool) ([]model.Vulnerability, error) {
// get payload
files, err := getPayload(tmpFile, remediated, openAPIResolveReferences, maxResolverDepth)

Expand All @@ -60,7 +61,7 @@ func scanTmpFile(
payload := files.Combine(false)

// init scan
inspector, err := initScan(queryID)
inspector, err := initScan(queryID, experimental)

if err != nil {
log.Err(err)
Expand Down Expand Up @@ -194,7 +195,7 @@ func runQuery(r *runQueryInfo) []model.Vulnerability {
return decoded
}

func initScan(queryID string) (*engine.Inspector, error) {
func initScan(queryID string, experimental bool) (*engine.Inspector, error) {
scanParams := &scan.Parameters{
QueriesPath: flags.GetMultiStrFlag(flags.QueriesPath),
Platform: flags.GetMultiStrFlag(flags.TypeFlag),
Expand Down Expand Up @@ -227,7 +228,8 @@ func initScan(queryID string) (*engine.Inspector, error) {
}

queryFilter := source.QueryInspectorParameters{
IncludeQueries: includeQueries,
IncludeQueries: includeQueries,
ExperimentalQueries: experimental,
}

t, err := tracker.NewTracker(c.ScanParams.PreviewLines)
Expand Down Expand Up @@ -271,5 +273,5 @@ func loadQuery(inspector *engine.Inspector, queryID string) (*engine.PreparedQue
return query, nil
}

return &engine.PreparedQuery{}, errors.New("unable to load query" + queryID)
return &engine.PreparedQuery{}, errors.New("unable to load query " + queryID)
}
5 changes: 3 additions & 2 deletions pkg/remediation/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func willRemediate(
}

// scan the temporary file to verify if the remediation removed the result
results, err := scanTmpFile(tmpFile, remediation.QueryID, content, openAPIResolveReferences, maxResolverDepth)
results, err := scanTmpFile(tmpFile, remediation.QueryID, content, openAPIResolveReferences, maxResolverDepth, remediation.Experimental)

if err != nil {
log.Error().Msgf("failed to get results of query %s: %s", remediation.QueryID, err)
Expand Down Expand Up @@ -159,7 +159,6 @@ func (s *Summary) GetRemediationSetsFromVulns(vulnerabilities []model.Vulnerabil
}

var remediationSet Set

if shouldRemediate(&file, include) {
s.SelectedRemediationNumber++
r := &Remediation{
Expand All @@ -170,6 +169,7 @@ func (s *Summary) GetRemediationSetsFromVulns(vulnerabilities []model.Vulnerabil
SearchKey: vuln.SearchKey,
ExpectedValue: vuln.KeyExpectedValue,
ActualValue: vuln.KeyActualValue,
Experimental: vuln.Experimental,
}

if file.RemediationType == "replacement" {
Expand Down Expand Up @@ -213,6 +213,7 @@ func getVulns(results Report) []model.Vulnerability {
SearchKey: file.SearchKey,
KeyExpectedValue: file.ExpectedValue,
KeyActualValue: file.ActualValue,
Experimental: query.Experimental,
}

vulns = append(vulns, *vuln)
Expand Down
Loading