7.3 SSH Key Management 🔑

Γιατί SSH Keys και όχι Passwords;

┌─────────────────────────────────────────────────────────┐
│  Password Authentication                                │
│  ❌ Αποθηκεύεται σε plaintext (κίνδυνος)                │
│  ❌ Πρέπει να το πληκτρολογείς συνεχώς                  │
│  ❌ Δεν δουλεύει σε automation                          │
│  ❌ Brute force attacks                                 │
├─────────────────────────────────────────────────────────┤
│  SSH Key Authentication                                 │
│  ✅ Κρυπτογραφικά ασφαλές                               │
│  ✅ Πλήρως αυτόματο (χωρίς password)                    │
│  ✅ Ιδανικό για automation                              │
│  ✅ Αδύνατο brute force                                 │
└─────────────────────────────────────────────────────────┘

Τύποι SSH Keys

┌────────────────────────────────────────────────────────┐
│  Αλγόριθμος  │ Μέγεθος  │ Ασφάλεια   │ Σύσταση         │
├──────────────┼──────────┼────────────┼─────────────────┤
│  RSA         │ 4096 bit │ ⭐⭐⭐     │ ⚠️ Παλιό        │
│  DSA         │ 1024 bit │ ⭐         │ ❌ Αποφύγετε    │
│  ECDSA       │ 256 bit  │ ⭐⭐⭐⭐   │ ✅ Καλό         │
│  Ed25519     │ 256 bit  │ ⭐⭐⭐⭐⭐ │ ✅ Συνιστάται   │
└──────────────┴──────────┴────────────┴─────────────────┘

💡 Γιατί Ed25519:

✅ Μικρότερο μέγεθος → γρηγορότερο
✅ Ισχυρότερη κρυπτογραφία από RSA 4096
✅ Σύγχρονος αλγόριθμος (2011)
✅ Υποστηρίζεται παντού (OpenSSH 6.5+)

Δημιουργία SSH Key Pair

# Βασική δημιουργία Ed25519 key
ssh-keygen -t ed25519 -C "ansible@ansible-controller"

# Με custom filename
ssh-keygen -t ed25519 \
    -C "ansible@ansible-controller" \
    -f ~/.ssh/ansible_ed25519

# Παράμετροι:
# -t ed25519  → αλγόριθμος
# -C          → comment (περιγραφή)
# -f          → filename (default: ~/.ssh/id_ed25519)
# -N ""       → κενό passphrase (για automation)

# Για automation (χωρίς ερωτήσεις)
ssh-keygen -t ed25519 \
    -C "ansible@ansible-controller" \
    -f ~/.ssh/id_ed25519 \
    -N ""                          # ← κενό passphrase

Ανατομία του Key Pair

# Δες τα αρχεία
ls -la ~/.ssh/

# -rw------- 1 ansible ansible  419 ... id_ed25519      ← PRIVATE
# -rw-r--r-- 1 ansible ansible  108 ... id_ed25519.pub  ← PUBLIC
# Δες το public key
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBx... ansible@ansible-controller
#      │              │                              │
#      │              │                              └── comment
#      │              └─────────────────────────────── key data
#      └────────────────────────────────────────────── algorithm

# Δες το private key (ΠΟΤΕ μην το μοιραστείς!)
cat ~/.ssh/id_ed25519
# -----BEGIN OPENSSH PRIVATE KEY-----
# b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
# ...
# -----END OPENSSH PRIVATE KEY-----

Αποστολή Public Key στους Servers

Μέθοδος 1: ssh-copy-id (Αυτόματη) ✅

# Αποστολή σε server με password
ssh-copy-id -i ~/.ssh/id_ed25519.pub \
    -p 2022 \
    ansible@192.212.104.27

# Τι κάνει:
# 1. Συνδέεται με password
# 2. Δημιουργεί ~/.ssh/authorized_keys (αν δεν υπάρχει)
# 3. Προσθέτει το public key
# 4. Ορίζει σωστά permissions

# Επαλήθευση
ssh -i ~/.ssh/id_ed25519 -p 2022 ansible@192.212.104.27
# Πρέπει να μπεις ΧΩΡΙΣ password! ✅

Μέθοδος 2: Χειροκίνητα

# Βήμα 1: Αντιγραφή public key
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAA... ansible@ansible-controller

# Βήμα 2: Σύνδεση στον server
ssh ansible@192.212.104.27 -p 2022

# Βήμα 3: Στον server
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "ssh-ed25519 AAAA..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Μέθοδος 3: Με Ansible (βέλτιστη πρακτική) ✅

---
# deploy-ssh-key.yml
# Χρήση: ansible-playbook deploy-ssh-key.yml
#        -i "SERVER_IP," -u debian --ask-pass

- name: Αποστολή SSH Key σε νέο server
  hosts: all
  gather_facts: false

  tasks:
    - name: Δημιουργία .ssh directory
      ansible.builtin.file:
        path: /home/ansible/.ssh
        state: directory
        mode: '0700'
        owner: ansible
        group: ansible

    - name: Προσθήκη public key
      ansible.posix.authorized_key:
        user: ansible
        state: present
        key: "{{ lookup('file', '/home/ansible/.ssh/id_ed25519.pub') }}"

    - name: Επαλήθευση
      ansible.builtin.debug:
        msg: "SSH key deployed successfully!"
# Εκτέλεση
ansible-playbook playbooks/deploy-ssh-key.yml \
    -i "192.212.104.27," \
    -u debian \
    --ask-pass \
    -e "ansible_port=22"

Πολλαπλά SSH Keys

Σε real-world περιβάλλοντα έχεις διαφορετικά keys για διαφορετικούς σκοπούς:

# Δομή ~/.ssh/
ls ~/.ssh/
# id_ed25519              ← default Ansible key
# id_ed25519.pub
# github_ed25519          ← GitHub key
# github_ed25519.pub
# backup_ed25519          ← Backup server key
# backup_ed25519.pub
# config                  ← SSH config file

SSH Config File — Ο σωστός τρόπος διαχείρισης:

cat ~/.ssh/config
# ~/.ssh/config

# Default για Ansible
Host ansible-*
    User ansible
    IdentityFile ~/.ssh/id_ed25519
    Port 2022

# Συγκεκριμένος server
Host nextcloud
    HostName 192.212.104.27
    User ansible
    Port 2022
    IdentityFile ~/.ssh/id_ed25519

# GitHub
Host github.com
    User git
    IdentityFile ~/.ssh/github_ed25519

# Backup server
Host backup
    HostName 192.168.1.100
    User backup
    Port 22
    IdentityFile ~/.ssh/backup_ed25519
# Με το config file μπορείς να γράφεις:
ssh nextcloud              # αντί για:
                           # ssh -i ~/.ssh/id_ed25519 -p 2022 ansible@192.212.104.27

SSH Agent — Για Keys με Passphrase

Αν έχεις passphrase στο key σου (για personal use):

# Εκκίνηση ssh-agent
eval $(ssh-agent -s)
# Agent pid 12345

# Προσθήκη key στον agent
ssh-add ~/.ssh/id_ed25519
# Enter passphrase: ← μία φορά!
# Identity added: /home/ansible/.ssh/id_ed25519

# Δες τα keys στον agent
ssh-add -l
# 256 SHA256:... ansible@ansible-controller (ED25519)

# Τώρα η Ansible χρησιμοποιεί τον agent
# χωρίς να ζητάει passphrase για κάθε σύνδεση!

# Αφαίρεση key από agent
ssh-add -d ~/.ssh/id_ed25519

# Καθαρισμός όλων
ssh-add -D

📝 Για Automation: Αν η Ansible τρέχει αυτόματα (cron, CI/CD), χρησιμοποίησε key χωρίς passphrase. Αν το τρέχεις εσύ χειροκίνητα, μπορείς να έχεις passphrase + ssh-agent.


Rotation SSH Keys — Αλλαγή Keys

---
# rotate-ssh-keys.yml
# Αλλαγή SSH key σε όλους τους servers

- name: Rotate SSH Keys
  hosts: all_managed
  tasks:

    - name: Προσθήκη νέου key
      ansible.posix.authorized_key:
        user: ansible
        state: present
        key: "{{ lookup('file', '/home/ansible/.ssh/new_id_ed25519.pub') }}"

    - name: Αφαίρεση παλιού key
      ansible.posix.authorized_key:
        user: ansible
        state: absent
        key: "{{ lookup('file', '/home/ansible/.ssh/old_id_ed25519.pub') }}"

    - name: Επαλήθευση νέου key
      ansible.builtin.debug:
        msg: "SSH key rotated on {{ inventory_hostname }}"
# Εκτέλεση με το παλιό key (για τελευταία φορά)
ansible-playbook playbooks/rotate-ssh-keys.yml \
    --private-key ~/.ssh/old_id_ed25519

Known Hosts Management

# Δες το known_hosts
cat ~/.ssh/known_hosts
# [192.212.104.27]:2022 ssh-ed25519 AAAA...

# Πρόσθεσε server στο known_hosts (χειροκίνητα)
ssh-keyscan -p 2022 192.212.104.27 >> ~/.ssh/known_hosts

# Αφαίρεση server (π.χ. μετά από reinstall)
ssh-keygen -R "[192.212.104.27]:2022"

# Με Ansible (για όλους τους servers)
- name: Add hosts to known_hosts
  ansible.builtin.known_hosts:
    name: "{{ ansible_host }}"
    key: "{{ lookup('pipe', 'ssh-keyscan -p ' + ansible_port|string + ' ' + ansible_host) }}"
    state: present

Σύνοψη 7.3

SSH Key Management
├── Αλγόριθμος: Ed25519 (συνιστάται) ✅
├── Δημιουργία: ssh-keygen -t ed25519
├── Αποστολή:
│   ├── ssh-copy-id (εύκολο)
│   ├── Χειροκίνητα (authorized_keys)
│   └── Ansible playbook (βέλτιστο) ✅
├── Πολλαπλά keys: ~/.ssh/config
├── Passphrase: ssh-agent για interactive use
├── Rotation: ansible.posix.authorized_key
└── Known hosts: ssh-keyscan, known_hosts module