| from __future__ import annotations |
|
|
| from .schemas import EnrichedFinding, EnrichedFindings, ScanBundle |
|
|
|
|
| POLICY_DESCRIPTIONS: dict[str, str] = { |
| "CKV_AWS_18": "S3 buckets should have access logging enabled.", |
| "CKV_AWS_20": "S3 buckets should not allow public ACLs.", |
| "CKV_AWS_21": "S3 buckets should have versioning enabled.", |
| "CKV_AWS_23": "Security group ingress rules should not allow unrestricted access.", |
| "CKV_AWS_24": "Security group ingress rules should not allow unrestricted SSH.", |
| "CKV_AWS_79": "EC2 instances should require IMDSv2.", |
| "CKV_AWS_144": "S3 buckets should have cross-region replication enabled when required.", |
| "CKV_AWS_145": "S3 buckets should use KMS encryption.", |
| "CKV2_AWS_6": "S3 public access block should block public ACLs and policies.", |
| "CKV2_AWS_61": "S3 buckets should have lifecycle configuration.", |
| "CKV2_AWS_62": "S3 buckets should have event notifications configured when required.", |
| "CKV2_AWS_64": "KMS keys should have key rotation enabled.", |
| "CKV_K8S_8": "Kubernetes containers should not run as root.", |
| "CKV_K8S_9": "Kubernetes containers should not run with privileged escalation.", |
| "CKV_K8S_10": "Kubernetes containers should set CPU requests.", |
| "CKV_K8S_11": "Kubernetes containers should set CPU limits.", |
| "CKV_K8S_12": "Kubernetes containers should set memory requests.", |
| "CKV_K8S_13": "Kubernetes containers should set memory limits.", |
| "CKV_K8S_14": "Kubernetes images should use immutable tags.", |
| "CKV_K8S_20": "Kubernetes containers should not run privileged.", |
| "CKV_K8S_21": "Kubernetes default namespace should not be used.", |
| "CKV_K8S_22": "Kubernetes containers should use read-only root filesystems where possible.", |
| "CKV_K8S_23": "Kubernetes containers should drop dangerous capabilities.", |
| "CKV_K8S_28": "Kubernetes containers should minimize Linux capabilities.", |
| "CKV_K8S_29": "Kubernetes containers should not allow privilege escalation.", |
| "CKV_K8S_31": "Kubernetes seccomp profile should be configured.", |
| "CKV_K8S_37": "Kubernetes containers should minimize capabilities.", |
| "CKV_K8S_38": "Kubernetes containers should run as non-root.", |
| "CKV_K8S_40": "Kubernetes containers should not run as UID 0.", |
| "CKV_K8S_43": "Kubernetes images should use digest or immutable tags.", |
| "CKV_TF_1": "Terraform should pin module sources to immutable versions.", |
| "CKV_TF_2": "Terraform providers should be version constrained.", |
| } |
|
|
|
|
| REMEDIATION_HINTS: dict[str, str] = { |
| "CKV_AWS_20": "For aws_s3_bucket_acl, avoid public-read/public-read-write. Prefer private ACLs and ownership controls.", |
| "CKV_AWS_21": "Add aws_s3_bucket_versioning with versioning_configuration { status = \"Enabled\" } for the target bucket.", |
| "CKV_AWS_23": "Restrict ingress CIDR blocks from 0.0.0.0/0 to a known trusted CIDR. If unknown, require human approval.", |
| "CKV_AWS_24": "Do not expose port 22 to 0.0.0.0/0. Narrow CIDR or remove the SSH ingress rule if not required.", |
| "CKV_AWS_79": "Add metadata_options { http_tokens = \"required\" } to aws_instance resources.", |
| "CKV_AWS_145": "Configure aws_s3_bucket_server_side_encryption_configuration with aws:kms only when a real KMS key exists; otherwise require approval.", |
| "CKV2_AWS_6": "Add aws_s3_bucket_public_access_block with all four block/restrict flags set to true.", |
| "CKV2_AWS_61": "Add aws_s3_bucket_lifecycle_configuration only when a retention policy is known; otherwise require approval.", |
| "CKV2_AWS_64": "Set enable_key_rotation = true on aws_kms_key resources.", |
| "CKV_K8S_8": "Add securityContext.runAsNonRoot: true and avoid UID 0.", |
| "CKV_K8S_9": "Set securityContext.allowPrivilegeEscalation: false on every container.", |
| "CKV_K8S_10": "Add resources.requests.cpu to each container.", |
| "CKV_K8S_11": "Add resources.limits.cpu to each container.", |
| "CKV_K8S_12": "Add resources.requests.memory to each container.", |
| "CKV_K8S_13": "Add resources.limits.memory to each container.", |
| "CKV_K8S_14": "Replace latest or mutable image tags with immutable versions if a real version is known.", |
| "CKV_K8S_20": "Set privileged: false in each container securityContext.", |
| "CKV_K8S_22": "Set readOnlyRootFilesystem: true only when the workload does not require writes, otherwise require approval.", |
| "CKV_K8S_29": "Set allowPrivilegeEscalation: false on each container securityContext.", |
| "CKV_K8S_31": "Set seccompProfile.type: RuntimeDefault at pod or container securityContext.", |
| "CKV_K8S_38": "Set runAsNonRoot: true at pod or container securityContext.", |
| "CKV_K8S_40": "Set runAsUser to a non-zero UID only when compatible with the image; otherwise require approval.", |
| "CKV_TF_1": "Pin module source references to tags or commits. Do not invent a version if none is known.", |
| "CKV_TF_2": "Add required_providers version constraints compatible with the configuration.", |
| } |
|
|
|
|
| def enrich_findings(bundle: ScanBundle) -> EnrichedFindings: |
| findings = [] |
| for finding in bundle.findings: |
| findings.append( |
| EnrichedFinding( |
| **finding.model_dump(), |
| policy_description=POLICY_DESCRIPTIONS.get(finding.rule_id, finding.message), |
| remediation_hint=REMEDIATION_HINTS.get(finding.rule_id), |
| cis_controls=[], |
| doc_snippets=[], |
| ) |
| ) |
| return EnrichedFindings(file=bundle.file, findings=findings) |
|
|
|
|
| def build_rule_hints_md(rule_ids: list[str]) -> str: |
| lines: list[str] = [] |
| for rule_id in sorted(set(rule_ids)): |
| description = POLICY_DESCRIPTIONS.get(rule_id, "Scanner policy finding.") |
| hint = REMEDIATION_HINTS.get(rule_id, "Use the scanner message and make the smallest safe in-file remediation.") |
| lines.append(f"- {rule_id}: {description} Fix: {hint}") |
| return "\n".join(lines) |
|
|