D8.4 Image Security 🖼️
Minimal Base Images
Image size = Attack surface:
│
├── ubuntu:latest → ~77MB, ~400 packages ← πολλές CVEs!
├── debian:slim → ~75MB, fewer packages
├── alpine:latest → ~7MB, minimal packages ✅
├── distroless → ~2-3MB, NO shell! ✅✅
└── scratch → 0MB, ΜΟΝΟ binary! ✅✅✅
tasks:
# ── Χρήση minimal images ──────────────────
- name: Pull minimal nginx image
community.docker.docker_image:
name: nginx
tag: 1.25-alpine # ← alpine αντί debian!
source: pull
- name: Pull minimal postgres
community.docker.docker_image:
name: postgres
tag: 15-alpine
source: pull
# ── Απόρριψη :latest ──────────────────────
# ❌ Ποτέ: nginx:latest (unknown version!)
# ✅ Πάντα: nginx:1.25.3-alpine (pinned version)
Image Scanning με Trivy
tasks:
# ── Εγκατάσταση Trivy (controller) ───────
- name: Install Trivy
ansible.builtin.get_url:
url: "https://github.com/aquasecurity/trivy/releases/download/v0.50.0/trivy_0.50.0_Linux-64bit.deb"
dest: /tmp/trivy.deb
delegate_to: localhost
run_once: true
- name: Install Trivy package
ansible.builtin.apt:
deb: /tmp/trivy.deb
delegate_to: localhost
run_once: true
become: true
# ── Scan image πριν deployment ────────────
- name: Scan image για CVEs
ansible.builtin.command:
cmd: >
trivy image
--exit-code 1
--severity HIGH,CRITICAL
--no-progress
"{{ app_image }}:{{ app_version }}"
delegate_to: localhost
run_once: true
register: trivy_scan
changed_when: false
ignore_errors: true
- name: Αποτέλεσμα scan
ansible.builtin.debug:
msg: "{{ trivy_scan.stdout_lines[-10:] }}"
run_once: true
- name: Σταμάτα αν HIGH/CRITICAL CVEs
ansible.builtin.fail:
msg: |
❌ Image scan απέτυχε!
Βρέθηκαν HIGH/CRITICAL vulnerabilities.
Αντικατάστησε το image ή αντιμετώπισε τα CVEs.
when:
- trivy_scan.rc != 0
- not allow_vulnerabilities | default(false)
run_once: true
# ── Scan με report ────────────────────────
- name: Full scan report
ansible.builtin.command:
cmd: >
trivy image
--format json
--output /tmp/trivy-report.json
"{{ app_image }}:{{ app_version }}"
delegate_to: localhost
run_once: true
changed_when: false
Image versioning — Pinned tags
vars:
images:
nginx: "nginx:1.25.3-alpine" # ← pinned!
postgres: "postgres:15.4-alpine" # ← pinned!
redis: "redis:7.2.3-alpine" # ← pinned!
# ΌΧΙ: "nginx:latest", "postgres:15", "redis:7"
tasks:
- name: Pull pinned images
community.docker.docker_image:
name: "{{ item.value | split(':') | first }}"
tag: "{{ item.value | split(':') | last }}"
source: pull
force_source: true # ← πάντα νέο pull
loop: "{{ images | dict2items }}"
loop_control:
label: "{{ item.value }}"
Σύνοψη D8.4
Image Security
│
├── Minimal base images:
│ ├── alpine → ~7MB, minimal attack surface
│ ├── distroless → no shell, ultra-minimal
│ └── ΌΧΙ ubuntu:latest → πολλές CVEs
│
├── Pinned versions:
│ ├── nginx:1.25.3-alpine ✅
│ └── nginx:latest ❌
│
└── Trivy scanning:
├── trivy image --severity HIGH,CRITICAL
├── --exit-code 1 → αποτυχία αν CVEs
└── CI/CD gate πριν deployment