feat: add pre-commit configuration (#9)
- add pre-commit-config - add yamllint config - add ci/validate-* custom scripts - verify no secrets added - verify clusters with kustomize and kubeconform - verify apps with kustomize and kubeconform Reviewed-on: #9
This commit is contained in:
parent
ebb47348fe
commit
72a892eb14
53
.pre-commit-config.yaml
Normal file
53
.pre-commit-config.yaml
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
repos:
|
||||||
|
# General file checks
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.5.0
|
||||||
|
hooks:
|
||||||
|
- id: check-executables-have-shebangs
|
||||||
|
- id: check-json
|
||||||
|
- id: check-added-large-files
|
||||||
|
args: ['--maxkb=500']
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-shebang-scripts-are-executable
|
||||||
|
- id: check-symlinks
|
||||||
|
- id: check-toml
|
||||||
|
- id: check-yaml
|
||||||
|
args: [--allow-multiple-documents]
|
||||||
|
- id: detect-aws-credentials
|
||||||
|
args: [--allow-missing-credentials]
|
||||||
|
- id: detect-private-key
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: forbid-new-submodules
|
||||||
|
- id: no-commit-to-branch
|
||||||
|
- id: pretty-format-json
|
||||||
|
- id: trailing-whitespace
|
||||||
|
|
||||||
|
# YAML linting
|
||||||
|
- repo: https://github.com/adrienverge/yamllint.git
|
||||||
|
rev: v1.37.1
|
||||||
|
hooks:
|
||||||
|
- id: yamllint
|
||||||
|
args:
|
||||||
|
[
|
||||||
|
"-d {extends: relaxed, rules: {line-length: disable}, ignore: chart}",
|
||||||
|
"-s",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Kubernetes manifest validation
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: kubeconform_validate_apps
|
||||||
|
name: kubeconform validate apps
|
||||||
|
entry: ci/validate-apps.sh
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
- id: kubeconform_validate_clusters
|
||||||
|
name: kubeconform validate clusters
|
||||||
|
entry: ci/validate-clusters.sh
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
- id: no_plain_secrets
|
||||||
|
name: prevent plain kubernetes secrets
|
||||||
|
entry: ci/validate-no-secrets.sh
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
29
.yamllint.yaml
Normal file
29
.yamllint.yaml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# .yamllint.yaml
|
||||||
|
extends: default
|
||||||
|
|
||||||
|
rules:
|
||||||
|
# Allow long lines for base64 encoded values and URLs
|
||||||
|
line-length:
|
||||||
|
max: 200
|
||||||
|
allow-non-breakable-words: true
|
||||||
|
allow-non-breakable-inline-mappings: true
|
||||||
|
|
||||||
|
# Kubernetes manifests use 2-space indentation
|
||||||
|
indentation:
|
||||||
|
spaces: 2
|
||||||
|
indent-sequences: consistent
|
||||||
|
|
||||||
|
# Allow multiple documents (---) in a single file
|
||||||
|
document-start: enable
|
||||||
|
|
||||||
|
# Be lenient with comments
|
||||||
|
comments:
|
||||||
|
require-starting-space: true
|
||||||
|
min-spaces-from-content: 1
|
||||||
|
|
||||||
|
# Allow empty values (common in Kustomize patches)
|
||||||
|
empty-values: enable
|
||||||
|
|
||||||
|
truthy:
|
||||||
|
# Allow 'on' and 'yes' values (common in Kubernetes)
|
||||||
|
allowed-values: ['true', 'false', 'yes', 'no', 'on', 'off']
|
||||||
23
ci/validate-apps.sh
Executable file
23
ci/validate-apps.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
KUBE_VERSION="1.33.7"
|
||||||
|
|
||||||
|
schema_args=(
|
||||||
|
-schema-location "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{.NormalizedKubernetesVersion}}-standalone{{.StrictSuffix}}/{{.ResourceKind}}{{.KindSuffix}}.json"
|
||||||
|
-schema-location "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
while IFS= read -r -d "" k; do
|
||||||
|
dir="$(dirname "$k")"
|
||||||
|
echo "==> kubeconform: $dir" >&2
|
||||||
|
|
||||||
|
kustomize build --enable-helm "$dir" \
|
||||||
|
| kubeconform \
|
||||||
|
-kubernetes-version "$KUBE_VERSION" \
|
||||||
|
-summary \
|
||||||
|
-output pretty \
|
||||||
|
-verbose \
|
||||||
|
-skip CustomResourceDefinition \
|
||||||
|
"${schema_args[@]}"
|
||||||
|
done < <(find apps/overlays -name kustomization.yaml -print0)
|
||||||
23
ci/validate-clusters.sh
Executable file
23
ci/validate-clusters.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
KUBE_VERSION="1.33.7"
|
||||||
|
|
||||||
|
schema_args=(
|
||||||
|
-schema-location "https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/{{.NormalizedKubernetesVersion}}-standalone{{.StrictSuffix}}/{{.ResourceKind}}{{.KindSuffix}}.json"
|
||||||
|
-schema-location "https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json"
|
||||||
|
)
|
||||||
|
|
||||||
|
while IFS= read -r -d "" k; do
|
||||||
|
dir="$(dirname "$k")"
|
||||||
|
echo "==> kubeconform: $dir" >&2
|
||||||
|
|
||||||
|
kustomize build --enable-helm "$dir" \
|
||||||
|
| kubeconform \
|
||||||
|
-kubernetes-version "$KUBE_VERSION" \
|
||||||
|
-summary \
|
||||||
|
-output pretty \
|
||||||
|
-verbose \
|
||||||
|
-skip CustomResourceDefinition \
|
||||||
|
"${schema_args[@]}"
|
||||||
|
done < <(find clusters -name kustomization.yaml -print0)
|
||||||
22
ci/validate-no-secrets.sh
Executable file
22
ci/validate-no-secrets.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Check staged files for plain Kubernetes Secrets
|
||||||
|
ERRORS=0
|
||||||
|
|
||||||
|
while IFS= read -r -d '' file; do
|
||||||
|
# Skip if file doesn't exist (e.g., deleted files)
|
||||||
|
[[ -f "$file" ]] || continue
|
||||||
|
|
||||||
|
# Check if the file contains a plain Kubernetes Secret
|
||||||
|
if grep -q "^kind: Secret" "$file"; then
|
||||||
|
# Allow secure secret types
|
||||||
|
if ! grep -q -E "^kind: (SealedSecret|ExternalSecret|VaultStaticSecret|VaultDynamicSecret)" "$file"; then
|
||||||
|
echo "BLOCKED: $file contains a plain Kubernetes Secret" >&2
|
||||||
|
echo " Use VaultStaticSecret or VaultDynamicSecret instead" >&2
|
||||||
|
((ERRORS++))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done < <(git diff --cached --name-only --diff-filter=ACM -z | grep -zE '\.(yaml|yml)$')
|
||||||
|
|
||||||
|
exit $ERRORS
|
||||||
Loading…
Reference in New Issue
Block a user