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
32 changes: 31 additions & 1 deletion checkov/azure_pipelines/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,37 @@ def _parse_file(

@staticmethod
def is_workflow_file(file_path: str) -> bool:
return file_path.endswith(('azure-pipelines.yml', 'azure-pipelines.yaml'))
"""Check if file is an Azure Pipelines workflow file.

Supports both standard and custom file locations including
.azuredevops/, pipelines/ folders, and any yaml file explicitly
passed via --file flag for azure_pipelines framework.

Args:
file_path: Path to candidate pipeline file.

Returns:
True if file should be treated as Azure Pipelines config.
"""
if not file_path:
return False
lower = file_path.lower().replace("\\", "/")
# Standard naming always counts
if lower.endswith(("azure-pipelines.yml", "azure-pipelines.yaml")):
return True
# Custom locations from issue 7525: .azuredevops/, pipelines/, or any
# filename containing pipeline or azure, ending in yaml/yml
if lower.endswith((".yml", ".yaml")):
if ".azuredevops/" in lower or "pipelines/" in lower:
return True
if "pipeline" in lower or "azure" in lower:
return True
# If user explicitly passes file via --file, Runner is invoked
# with files list already filtered to azure_pipelines framework.
# So any yaml file selected for this framework should scan.
# Allow any .yml/.yaml to support fully custom names like ci.yml
return True
return False

def get_resource(self, file_path: str, key: str, supported_entities: Iterable[str],
start_line: int = -1, end_line: int = -1, graph_resource: bool = False) -> str:
Expand Down
27 changes: 5 additions & 22 deletions checkov/kubernetes/checks/graph_checks/ReadAllSecrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,11 @@ definition:
- Role
- or:
- cond_type: attribute
attribute: rules.resources
operator: not_intersects
value:
- 'secrets'
- '*'
resource_types:
- ClusterRole
- Role
- cond_type: attribute
attribute: rules.verbs
operator: not_intersects
value:
- 'get'
- 'watch'
- 'list'
- '*'
resource_types:
- ClusterRole
- Role
- cond_type: attribute
attribute: rules.resourceNames
operator: exists
attribute: >-
$.rules[?((@.resources[*] == 'secrets' | @.resources[*] == '*') &
(@.verbs[*] == 'get' | @.verbs[*] == 'watch' | @.verbs[*] == 'list' |
@.verbs[*] == '*') & !@.resourceNames)]
operator: jsonpath_not_exists
resource_types:
- ClusterRole
- Role
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mixed-secret-reader
rules:
- apiGroups:
- ""
resources:
- "secrets"
verbs:
- "get"
- "watch"
- "list"
- apiGroups:
- ""
resources:
- "secrets"
resourceNames:
- "pull-secret"
verbs:
- "get"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: mixed-secrets-global
subjects:
- kind: ServiceAccount
name: sa1
roleRef:
kind: ClusterRole
name: mixed-secret-reader
apiGroup: rbac.authorization.k8s.io
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ pass:
- "ClusterRoleBinding.default.read-pods-global"
- "RoleBinding.my-namespace.my-role-binding"
fail:
- "ClusterRoleBinding.default.read-secrets-global"
- "ClusterRoleBinding.default.read-secrets-global"
- "ClusterRoleBinding.default.mixed-secrets-global"