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
36 changes: 15 additions & 21 deletions .github/workflows/validate-cfn-samples.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: validate-cfn-samples

on:
workflow_dispatch:
pull_request:
paths:
- "assets/queries/cloudFormation/**/test/*.yaml"
Expand All @@ -18,46 +17,41 @@ jobs:
validate-cfn-syntax:
name: Validate Cloudformation Syntax
runs-on: cx-public-ubuntu-x64
permissions:
contents: read # for actions/checkout to fetch code
pull-requests: read # for lots0logs/gh-action-get-changed-files to read the PR's changed file list
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
- name: Detect changed cloudformation samples
uses: step-security/paths-filter@5c5241b8233e77b55b9046daf88f1cb7560281de # v4.0.1
id: filter
with:
list-files: json
filters: |
samples:
- "assets/queries/cloudFormation/**/test/*.yaml"
- "assets/queries/cloudFormation/**/test/*.json"
- name: Setup python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.x'
- name: Get commit changed files
if: github.event_name != 'workflow_dispatch'
uses: lots0logs/gh-action-get-changed-files@6cb5164a823dbf3318b7c8032a333b4b7ed425b2 # 2.2.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get cfn-python-lint
env:
ECHO_LIBRARIES_ACCESS_KEY: ${{ secrets.ECHO_LIBRARIES_ACCESS_KEY }}
run: |
pip config set global.index-url "https://:${ECHO_LIBRARIES_ACCESS_KEY}@pypi.echohq.com/simple"
pip3 install -U cfn-lint --user
- name: Validate ALL cloudformation template samples
if: github.event_name == 'workflow_dispatch'
- name: Validate changed cloudformation template samples
env:
CHANGED_SAMPLES: ${{ steps.filter.outputs.samples_files }}
run: |
echo "${CHANGED_SAMPLES}" > "${RUNNER_TEMP}/changed-cfn-samples.json"
python3 -u .github/scripts/samples-linters/validate-syntax.py \
"assets/queries/cloudFormation/**/test/*.yaml" \
"assets/queries/cloudFormation/**/test/*.json" \
--diff "${RUNNER_TEMP}/changed-cfn-samples.json" \
--linter /home/runner/.local/bin/cfn-lint \
--extra " --info --config-file .github/scripts/samples-linters/.cfnlintrc.yml" \
--skip ".github/scripts/samples-linters/ignore-list/cloudformation" \
--verbose
- name: Validate CHANGED cloudformation template samples
if: github.event_name != 'workflow_dispatch'
run: |
python3 -u .github/scripts/samples-linters/validate-syntax.py \
"assets/queries/cloudFormation/**/test/*.yaml" \
"assets/queries/cloudFormation/**/test/*.json" \
--diff ${HOME}/files.json \
--linter /home/runner/.local/bin/cfn-lint \
--extra " --info --config-file .github/scripts/samples-linters/.cfnlintrc.yml" \
--skip ".github/scripts/samples-linters/ignore-list/cloudformation" -vv
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ CxPolicy[result] {
"searchKey": sprintf("name={{%s}}.{{%s}}", [task.name, modules[m]]),
"issueType": "MissingAttribute",
"keyExpectedValue": sprintf("%s.deployment_configuration should be defined", [modules[m]]),
"keyActualValue": sprintf("%&s.deployment_configuration is undefined", [modules[m]]),
"keyActualValue": sprintf("%s.deployment_configuration is undefined", [modules[m]]),
}
}

Expand All @@ -36,8 +36,8 @@ CxPolicy[result] {
"resourceName": task.name,
"searchKey": sprintf("name={{%s}}.{{%s}}.deployment_configuration", [task.name, modules[m]]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("%s.deployment_configuration should have at least 1 task running", [modules[m]]),
"keyActualValue": sprintf("%&s.deployment_configuration must have at least 1 task running", [modules[m]]),
"keyExpectedValue": sprintf("%s.deployment_configuration should have maximum_percent or minimum_healthy_percent defined", [modules[m]]),
"keyActualValue": sprintf("%s.deployment_configuration doesn't have maximum_percent or minimum_healthy_percent defined", [modules[m]]),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ CxPolicy[result] {
"resourceName": task.name,
"searchKey": sprintf("name={{%s}}.{{%s}}.end_ip_address", [task.name, modules[m]]),
"issueType": "IncorrectValue",
"keyExpectedValue": "azure_rm_sqlfirewallrule should allow all IPs",
"keyActualValue": "azure_rm_sqlfirewallrule should not allow all IPs (range from start_ip_address to end_ip_address)",
"keyExpectedValue": "azure_rm_sqlfirewallrule should not allow all IPs",
"keyActualValue": "azure_rm_sqlfirewallrule allows all IPs (range from start_ip_address to end_ip_address)",
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,16 @@ prepare_issue(val1, val2) = issue {
} else = issue {
val2 == "not defined"
issue := {
"kav": sprintf("resource with type 'Microsoft.Storage/storageAccounts' publicNetworkAccess is set to '%s')", [val1]),
"kav": sprintf("resource with type 'Microsoft.Storage/storageAccounts' publicNetworkAccess is set to '%s'", [val1]),
"sk": ".properties.publicNetworkAccess",
"sl": ["properties", "publicNetworkAccess"],
"issueType": "IncorrectValue"
}
} else = issue {
issue := {
"kav": sprintf("resource with type 'Microsoft.Storage/storageAccounts' networkAcls.defaultAction is set to '%s')", [val2]),
"kav": sprintf("resource with type 'Microsoft.Storage/storageAccounts' networkAcls.defaultAction is set to '%s'", [val2]),
"sk": ".properties.networkAcls",
"sl": ["properties", "networkAcls"],
"issueType": "IncorrectValue"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ CxPolicy[result] {
"searchKey": sprintf("%s.name={{%s}}.properties.%s.state", [common_lib.concat_path(path), value.name, emailType[x]]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("resource with type 'Microsoft.Security/securityContacts' %s should have '%s.state' property set to 'On'", [type ,emailType[x]]),
"keyActualValue": sprintf("resource with type 'Microsoft.Security/securityContacts' should have '%s.state' property set to 'Off'", [emailType[x]]),
"keyActualValue": sprintf("resource with type 'Microsoft.Security/securityContacts' has '%s.state' property set to 'Off'", [emailType[x]]),
"searchLine": common_lib.build_search_line(path, ["properties", emailType[x], "state"]),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ CxPolicy[result] {
"resourceName": "n/a",
"searchKey": sprintf("Parameters.%s.Default", [paramName]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Parameters.%s.Default should be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default shouldn't be defined", [paramName]),
"keyExpectedValue": sprintf("Parameters.%s.Default should not be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default is defined", [paramName]),
}
}

Expand All @@ -49,8 +49,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.AccessToken", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.AccessToken must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.AccessToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.AccessToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.AccessToken is defined as a plaintext value", [key]),
}
}

Expand All @@ -74,7 +74,7 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.AccessToken", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.AccessToken must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.AccessToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.AccessToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.AccessToken is defined as a plaintext value", [key]),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ CxPolicy[result] {
"resourceName": "n/a",
"searchKey": sprintf("Parameters.%s.Default", [paramName]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Parameters.%s.Default should be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default shouldn't be defined", [paramName]),
"keyExpectedValue": sprintf("Parameters.%s.Default should not be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default is defined", [paramName]),
}
}

Expand All @@ -50,8 +50,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password is defined as a plaintext value", [key]),
}
}

Expand All @@ -76,8 +76,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password is defined as a plaintext value", [key]),
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ CxPolicy[result] {
"resourceName": "n/a",
"searchKey": sprintf("Parameters.%s.Default", [paramName]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Parameters.%s.Default should be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default shouldn't be defined", [paramName]),
"keyExpectedValue": sprintf("Parameters.%s.Default should not be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default is defined", [paramName]),
}
}

Expand All @@ -46,10 +46,10 @@ CxPolicy[result] {
"documentId": input.document[i].id,
"resourceType": resource.Type,
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"searchKey": sprintf("Resources.%s.Properties.OauthToken", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.OauthToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.OauthToken is defined as a plaintext value", [key]),
}
}

Expand All @@ -71,9 +71,9 @@ CxPolicy[result] {
"documentId": input.document[i].id,
"resourceType": resource.Type,
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"searchKey": sprintf("Resources.%s.Properties.OauthToken", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.OauthToken must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.OauthToken is defined as a plaintext value", [key]),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
"fileName": "positive2.yaml"
},
{
"line": 4,
"line": 12,
"fileName": "positive1.yaml",
"queryName": "Amplify App OAuth Token Exposed",
"severity": "HIGH"
},
{
"queryName": "Amplify App OAuth Token Exposed",
"severity": "HIGH",
"line": 5,
"line": 8,
"fileName": "positive3.json"
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ CxPolicy[result] {
"resourceName": "n/a",
"searchKey": sprintf("Parameters.%s.Default", [paramName]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Parameters.%s.Default should be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default shouldn't be defined", [paramName]),
"keyExpectedValue": sprintf("Parameters.%s.Default should not be defined", [paramName]),
"keyActualValue": sprintf("Parameters.%s.Default is defined", [paramName]),
}
}

Expand All @@ -50,8 +50,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password is defined as a plaintext value", [key]),
}
}

Expand All @@ -75,8 +75,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, key),
"searchKey": sprintf("Resources.%s.Properties.BasicAuthConfig.Password", [key]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must not be in plain text string", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyExpectedValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password must be defined as a parameter or have a secret manager referenced", [key]),
"keyActualValue": sprintf("Resources.%s.Properties.BasicAuthConfig.Password is defined as a plaintext value", [key]),
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ CxPolicy[result] {
"searchKey": sprintf("Resources.%s", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s should have AWS::ApiGateway::Stage associated, DeploymentId.Ref should be the same as the ApiGateway::Stage resource", [name]),
"keyActualValue": sprintf("Resources.%s should have AWS::ApiGateway::Stage associated, DeploymentId.Ref should be the same in the ApiGateway::Stage resource", [name]),
"keyActualValue": sprintf("Resources.%s doesn't have a AWS::ApiGateway::Stage whose DeploymentId.Ref matches this resource", [name]),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ CxPolicy[result] {
"searchKey": sprintf("Resources.%s", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s should have AWS::ApiGateway::UsagePlan associated, RestApiId and StageName should be the same as the %s resource", [name, name]),
"keyActualValue": sprintf("Resources.%s should have AWS::ApiGateway::UsagePlan associated, RestApiId and StageName should be the same in the %s resource", [name, name]),
"keyActualValue": sprintf("Resources.%s doesn't have a AWS::ApiGateway::UsagePlan whose RestApiId and StageName match the %s resource", [name, name]),
"searchLine": common_lib.build_search_line(["Resources", name], []),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ CxPolicy[result] {
"searchKey": sprintf("Resources.%s", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s should have AWS::ApiGateway::UsagePlan associated, RestApiId and StageName should be the same as the %s resource", [name, name]),
"keyActualValue": sprintf("Resources.%s should have AWS::ApiGateway::UsagePlan associated, RestApiId and StageName should be the same in the %s resource", [name, name]),
"keyActualValue": sprintf("Resources.%s doesn't have a AWS::ApiGateway::UsagePlan whose RestApiId and StageName match the %s resource", [name, name]),
"searchLine": common_lib.build_search_line(["Resources", name], []),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ CxPolicy[result] {
"resourceName": cf_lib.get_resource_name(resource, name),
"searchKey": sprintf("Resources.%s.Properties.SecurityPolicy", [name]),
"issueType": "MissingAttribute",
"keyExpectedValue": sprintf("Resources.%s.Properties.SecurityPolicy should not be defined", [name]),
"keyActualValue": sprintf("Resources.%s.Properties.SecurityPolicy is defined", [name]),
"keyExpectedValue": sprintf("Resources.%s.Properties.SecurityPolicy should be defined as TLS_1_2", [name]),
"keyActualValue": sprintf("Resources.%s.Properties.SecurityPolicy is not defined", [name]),
}
}

Expand All @@ -37,6 +37,6 @@ CxPolicy[result] {
"searchKey": sprintf("Resources.%s.Properties.SecurityPolicy", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("Resources.%s.Properties.SecurityPolicy should be %s", [name, tls]),
"keyActualValue": sprintf("Resources.%s.Properties.SecurityPolicy should be %s", [name, tls]),
"keyActualValue": sprintf("Resources.%s.Properties.SecurityPolicy is %s", [name, resource.Properties.SecurityPolicy]),
}
}
Loading
Loading