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