fix(security): restrict Neptune cookbook SG, add VPC flow logs, harden IaC scan suppressions (#806)

* fix(security): restrict Neptune cookbook SG, add VPC flow logs, harden IaC scan suppressions

Addresses open GHAS code scanning alerts:
- Neptune cookbook stack (neptune-setup.yaml) no longer opens the Bolt/OpenCypher
  port to 0.0.0.0/0; a required ClientCidr parameter must be supplied instead.
  Updated 21_Amazon_Neptune_Store.ipynb deploy instructions to match.
- Added VPC Flow Logs (CloudWatch Logs + IAM role) to the same stack.
- Documented why an account-wide IAM password policy resource does not belong
  in a disposable per-learner CFN stack, with a justified ts:skip.
- Added inline `checkov:skip` / `ts:skip` comments to the knowledge-explorer
  Helm templates (deployment/service/configmap) as a second suppression path
  for the CKV_K8S_21/AC_K8S_0086/AC_K8S_0080 false positives, since the prior
  annotation-only suppression was not being honored by the scanner.

* docs(changelog): document the Neptune and Helm chart security scan fixes

* fix(security): correct flow-log IAM scope and ClientCidr regex from review

- FlowLogRole granted logs:CreateLogStream/PutLogEvents on the bare log
  group ARN, but those actions apply to log streams, not the group itself;
  scoped them to "${FlowLogGroup.Arn}:log-stream:*" instead and moved the
  Describe* actions (which don't support group/stream-level resource
  restriction) to Resource: "*", matching AWS's documented flow-log IAM
  policy shape. Without this, flow log delivery could silently fail.
- ClientCidr's AllowedPattern only checked digit count (1-3 digits per
  octet), so malformed values like 999.999.999.999/32 passed parameter
  validation and would only fail later when CloudFormation tried to
  create the security group rule. Tightened the regex to enforce valid
  IPv4 octet ranges (0-255) and prefix lengths (0-32).

* fix(security): harden IAM policy in neptune-setup and standardize Helm chart scan suppressions

- neptune-setup.yaml: split FlowLogRole policy into account-level statement (CreateLogGroup, DescribeLogGroups, DescribeLogStreams with Resource: '*') and log-group-scoped statement (CreateLogStream, PutLogEvents with !GetAtt FlowLogGroup.Arn) per AWS VPC Flow Logs least-privilege documentation.
- deployment.yaml: remove unreliable file-header skip comments (# checkov:skip / # ts:skip) and replace with resource-level metadata.annotations (checkov.io/skip and runterrascan.io/skip). Update seccomp rule ID from CKV_K8S_28 to checkov's actual seccomp rule CKV_K8S_31 on both Deployment and pod-template metadata.
- configmap.yaml / service.yaml: remove stale # ts:skip=AC_K8S_0086 file-header comments and add runterrascan.io/skip resource-level metadata annotations for consistency across all chart templates.
- .checkov.yaml: update documentation to explain resource-level metadata.annotations and reference CKV_K8S_31.

---------

Co-authored-by: Sameer6305 <sskadam6305@gmail.com>
This commit is contained in:
Mohd Kaif
2026-07-27 17:54:38 +05:30
committed by GitHub
co-authored by Sameer6305
parent 4a3cf37679
commit 9eea49a070
7 changed files with 105 additions and 87 deletions
@@ -1,4 +1,4 @@
# checkov:skip=CKV_K8S_21:Namespace is bound via .Release.Namespace at helm install/template time; this chart is namespace-portable by design.
apiVersion: v1
kind: ConfigMap
metadata:
@@ -7,7 +7,8 @@ metadata:
labels:
{{- include "knowledge-explorer.labels" . | nindent 4 }}
annotations:
checkov.io/skip1: CKV_K8S_21=namespace is set via .Release.Namespace, bound only at helm install/template time
runterrascan.io/skip: '[{"rule": "AC_K8S_0086", "comment": "Namespace is bound via .Release.Namespace at helm install time"}]'
checkov.io/skip1: CKV_K8S_21=Namespace bound via .Release.Namespace at helm install/template time
data:
{{- range $key, $value := .Values.env }}
{{ $key }}: {{ $value | quote }}
@@ -1,4 +1,3 @@
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -7,7 +6,9 @@ metadata:
labels:
{{- include "knowledge-explorer.labels" . | nindent 4 }}
annotations:
checkov.io/skip1: CKV_K8S_21=namespace is set via .Release.Namespace, bound only at helm install/template time
runterrascan.io/skip: '[{"rule": "AC_K8S_0086", "comment": "Namespace is bound via .Release.Namespace at helm install time"}, {"rule": "AC_K8S_0080", "comment": "seccompProfile RuntimeDefault is set in values.yaml (podSecurityContext)"}]'
checkov.io/skip1: CKV_K8S_21=Namespace bound via .Release.Namespace at helm install/template time
checkov.io/skip2: CKV_K8S_31=seccompProfile RuntimeDefault set in values.yaml
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
@@ -22,8 +23,10 @@ spec:
{{- include "knowledge-explorer.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
runterrascan.io/skip: '[{"rule": "AC_K8S_0080", "comment": "seccompProfile RuntimeDefault is set in values.yaml (podSecurityContext)"}]'
checkov.io/skip1: CKV_K8S_31=seccompProfile RuntimeDefault set in values.yaml
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
@@ -1,4 +1,4 @@
# checkov:skip=CKV_K8S_21:Namespace is bound via .Release.Namespace at helm install/template time; this chart is namespace-portable by design.
apiVersion: v1
kind: Service
metadata:
@@ -7,7 +7,8 @@ metadata:
labels:
{{- include "knowledge-explorer.labels" . | nindent 4 }}
annotations:
checkov.io/skip1: CKV_K8S_21=namespace is set via .Release.Namespace, bound only at helm install/template time
runterrascan.io/skip: '[{"rule": "AC_K8S_0086", "comment": "Namespace is bound via .Release.Namespace at helm install time"}]'
checkov.io/skip1: CKV_K8S_21=Namespace bound via .Release.Namespace at helm install/template time
spec:
type: {{ .Values.service.type }}
ports: