Disaccoppiamento credenziali container da script docker #18

Closed
opened 2022-11-11 21:30:30 +00:00 by giomba · 3 comments
Owner

Nota: questa issue richiederà un bel po' di immaginazione da parte di chi non può (ancora) vedere i repository (privati) in questione.
Nonostante questo, la apro qui, così che tutti possano vedere e (spero presto) anche partecipare.

Stato attuale:

  • esiste un repository che contiene i docker-compose.yml versionati per i vari servizi del GOLEM
  • alcuni file di configurazione contengono anche chiavi/password e, in generale, "segreti" da non divulgare
  • questa scelta era stata fatta con l'idea che "intanto segniamo qui le credenziali, poi ci si penserà": dunque, è arrivato il momento di pensarci.

Problema:

  • il repository deve essere privato per ovvie ragioni di sicurezza, e questo impedisce una maggiore collaborazione al mantenimento e allo sviluppo dell'infrastruttura di sistema, all'interno del gruppo

Possibili soluzione: disaccoppiare gli script di configurazione dai segreti.

  • @giuliof aveva proposto questo, ma qualche sera fa, in officina, abbiamo convenuto, a voce, che è overkill ed è l'ennesima cosa da mantenere
  • creazione di un repository dedicato con solo le chiavi

Soluzione:

  • scelta di usare il repository con le chiavi

Ho buttato giù una bozza di questa nuova infrastruttura, e ho iniziato a ripulire un po' delle configurazioni in questione, generando nuovi segreti, così non c'è nemmeno bisogno di riscrivere la history del repo, che non piace mai a nessuno).

TODO list (al momento, doable solo da chi appartiene al gruppo argilla):

  • Container con MySQL

  • gestionaledb

  • gitea

  • nextcloud

  • wiki

  • wordpress

  • Container con SSH

  • pubblici

  • build (beta)

  • Container con altri segreti

  • docker registry
    - drone (beta)

Nota: questa issue richiederà un bel po' di immaginazione da parte di chi non può (ancora) vedere i repository (privati) in questione. Nonostante questo, la apro qui, così che tutti possano vedere e (spero presto) anche partecipare. Stato attuale: - esiste un repository che contiene i `docker-compose.yml` versionati per i vari servizi del GOLEM - alcuni file di configurazione contengono anche chiavi/password e, in generale, "segreti" da non divulgare - questa scelta era stata fatta con l'idea che "intanto segniamo qui le credenziali, poi ci si penserà": dunque, è arrivato il momento di pensarci. Problema: - il repository deve essere privato per ovvie ragioni di sicurezza, e questo impedisce una maggiore collaborazione al mantenimento e allo sviluppo dell'infrastruttura di sistema, all'interno del gruppo Possibili soluzione: disaccoppiare gli script di configurazione dai segreti. - @giuliof aveva proposto [questo](https://git.golem.linux.it/giuliof/pyGOLEMsecret), ma qualche sera fa, in officina, abbiamo convenuto, a voce, che è overkill ed è l'ennesima cosa da mantenere - creazione di un repository dedicato con solo le chiavi Soluzione: - scelta di usare il repository con le chiavi Ho buttato giù una bozza di questa nuova infrastruttura, e ho iniziato a ripulire un po' delle configurazioni in questione, generando nuovi segreti, così non c'è nemmeno bisogno di riscrivere la history del repo, che non piace mai a nessuno). TODO list (al momento, doable solo da chi appartiene al gruppo `argilla`): - Container con MySQL - [x] gestionaledb - [x] gitea - [x] nextcloud - [x] wiki - [x] wordpress - Container con SSH - [x] pubblici - [x] build (beta) - Container con altri segreti - [x] docker registry ~~- [ ] drone (beta)~~
giomba self-assigned this 2022-11-11 21:32:02 +00:00
giomba added a new dependency 2022-11-11 21:35:25 +00:00
Member

Possibili soluzione: disaccoppiare gli script di configurazione dai segreti.

@giuliof aveva proposto questo, ma qualche sera fa, in officina, abbiamo convenuto, a voce, che è overkill ed è l'ennesima cosa da mantenere
creazione di un repository dedicato con solo le chiavi

Butto lì altre possibilità che mi vengono in mente, sono solo idee a livello di brainstorming, non penso siano soluzioni migliori del semplice repository, aggiungendo un livello di complessità probabilmente inutile:

  • creare un bash script che crea sul server i files dei segreti (.env o equivalenti), le password sono variabili nello script. Lo script include nel nome il numero di versione e viene tenuto da vari membri dell'associazione nel loro password manager personale
  • idem come sopra, ma lo script non contiene le password ed è tenuto nel repository pubblico, le password vengono chieste al momento dell'esecuzione e inserite manualmente, sono tenute da vari membri dell'associazione nel loro password manager personale
  • dividere il file contenente le password con la tecnica SSSS - pessima idea, servono più persone per ritirare su il server

L'unico difetto dell'approccio con repository è che in teoria non sarebbe una B.P. tenere segreti su git, dal momento che una eventuale compromissione dà accesso ai segreti attuali e a quelli "pregressi", che potrebbe ad esempio servire per avere accesso a dei backup. Ma ovviamente bisogna essere pragmatici e tenere in considerazione qual'è il threat model a cui si è soggetti, le risorse che possono essere compromesse e la gravità delle conseguenze...


Per quanto riguarda i file concreti da usare per contenere i segreti ci sono varie possibilità:

  1. directory /srv/secrets (o /srv/vault o equivalente) con una sottodirectory per ogni servizio, la quale contiene il file .env; nella cartella con il file docker-compose.yaml c'è un symlink a quel file .env
  2. il file .env è presente direttamente nella directory del docker-compose.yaml, ma appartiene ad un bare repository, mentre nel repository dei file docker-compose il .gitignore permette di ignorare i file .env. I repository di "infrastruttura" e quello dei segreti sono "compenetrati" e si ignorano a vicenda
  3. nel file docker-compose si usa l'istruzione env_file per puntare al file /srv/secrets/fooservice/docker-compose.env che contiene la variabile del segreto. NB: a differenza dei file .env le variabili contenute negli env_file vengono passate tal quali al container, non possono essere usate all'interno del docker-compose.yaml
  4. usare la funzionalità dei docker secrets, vedi sotto

A mio avviso i docker secrets sono da preferire dove possibile (non tutti i container lo permettono), con fallback ad una delle soluzioni precedenti.

Esempio di utilizzo di docker secrets e env_file come ripiego dove non possibile:

---
version: '3.9'

networks:
    proxy:
        external: true
    internal:
        external: false

secrets:
    db_password:
        file: /srv/secrets/miniflux/dbpwd
    admin_password:
        file: /srv/secrets/miniflux/adminpwd

services:
    app:
        container_name: miniflux
        image: miniflux/miniflux:latest
        restart: unless-stopped
        networks:
            - proxy
            - internal
        secrets:
            - admin_password
        depends_on:
            - db
        env_file:
            - /srv/secrets/miniflux/docker-compose.env  # for: `DATABASE_URL="postgres://miniflux:db_password@db/miniflux?sslmode=disable"`
            # NB: values are not used in the compose file, https://stackoverflow.com/a/39548957
        environment:
            RUN_MIGRATIONS: 1
            ADMIN_USERNAME: admin
            ADMIN_PASSWORD_FILE: /run/secrets/admin_password
        healthcheck:
            test: [CMD, /usr/bin/miniflux, -healthcheck, auto]
        labels:
            - traefik.enable=true
            - traefik.http.routers.miniflux.rule=Host(`miniflux.golem.linux.it`)
            - traefik.http.routers.miniflux.entrypoints=websecure
            - traefik.http.routers.miniflux.tls.certresolver=letsencrypt
            - traefik.http.services.miniflux.loadbalancer.server.port=8080

    db:
        image: postgres:14
        restart: always
        networks:
            - internal
        volumes:
            - /srv/volumes/miniflux:/var/lib/postgresql/data
        secrets:
            - db_password
        environment:
            POSTGRES_USER: miniflux
            POSTGRES_PASSWORD_FILE: /run/secrets/db_password
        healthcheck:
            test: [CMD, pg_isready, -U, miniflux]
            interval: 10s
            start_period: 30s

> Possibili soluzione: disaccoppiare gli script di configurazione dai segreti. > @giuliof aveva proposto questo, ma qualche sera fa, in officina, abbiamo convenuto, a voce, che è overkill ed è l'ennesima cosa da mantenere > creazione di un repository dedicato con solo le chiavi Butto lì altre possibilità che mi vengono in mente, sono solo idee a livello di brainstorming, non penso siano soluzioni migliori del semplice repository, aggiungendo un livello di complessità probabilmente inutile: - creare un bash script che crea sul server i files dei segreti (.env o equivalenti), le password sono variabili nello script. Lo script include nel nome il numero di versione e viene tenuto da vari membri dell'associazione nel loro password manager personale - idem come sopra, ma lo script non contiene le password ed è tenuto nel repository pubblico, le password vengono chieste al momento dell'esecuzione e inserite manualmente, sono tenute da vari membri dell'associazione nel loro password manager personale - dividere il file contenente le password con la tecnica [SSSS](http://point-at-infinity.org/ssss/) - pessima idea, servono più persone per ritirare su il server L'unico difetto dell'approccio con repository è che in teoria non sarebbe una B.P. tenere segreti su git, dal momento che una eventuale compromissione dà accesso ai segreti attuali e a quelli "pregressi", che potrebbe ad esempio servire per avere accesso a dei backup. Ma ovviamente bisogna essere pragmatici e tenere in considerazione qual'è il threat model a cui si è soggetti, le risorse che possono essere compromesse e la gravità delle conseguenze... --- Per quanto riguarda i file concreti da usare per contenere i segreti ci sono varie possibilità: 1. directory /srv/secrets (o /srv/vault o equivalente) con una sottodirectory per ogni servizio, la quale contiene il file .env; nella cartella con il file docker-compose.yaml c'è un **symlink** a quel file .env 1. il file .env è presente direttamente nella directory del docker-compose.yaml, ma appartiene ad un **bare repository**, mentre nel repository dei file docker-compose il .gitignore permette di ignorare i file .env. I repository di "infrastruttura" e quello dei segreti sono "compenetrati" e si ignorano a vicenda 1. nel file docker-compose si usa l'istruzione `env_file` per puntare al file `/srv/secrets/fooservice/docker-compose.env` che contiene la variabile del segreto. NB: a differenza dei file .env le variabili contenute negli env_file vengono passate tal quali al container, non possono essere usate all'interno del docker-compose.yaml 1. usare la funzionalità dei *docker secrets*, vedi sotto A mio avviso i docker secrets sono da preferire dove possibile (non tutti i container lo permettono), con fallback ad una delle soluzioni precedenti. Esempio di utilizzo di docker secrets e env_file come ripiego dove non possibile: ```yaml --- version: '3.9' networks: proxy: external: true internal: external: false secrets: db_password: file: /srv/secrets/miniflux/dbpwd admin_password: file: /srv/secrets/miniflux/adminpwd services: app: container_name: miniflux image: miniflux/miniflux:latest restart: unless-stopped networks: - proxy - internal secrets: - admin_password depends_on: - db env_file: - /srv/secrets/miniflux/docker-compose.env # for: `DATABASE_URL="postgres://miniflux:db_password@db/miniflux?sslmode=disable"` # NB: values are not used in the compose file, https://stackoverflow.com/a/39548957 environment: RUN_MIGRATIONS: 1 ADMIN_USERNAME: admin ADMIN_PASSWORD_FILE: /run/secrets/admin_password healthcheck: test: [CMD, /usr/bin/miniflux, -healthcheck, auto] labels: - traefik.enable=true - traefik.http.routers.miniflux.rule=Host(`miniflux.golem.linux.it`) - traefik.http.routers.miniflux.entrypoints=websecure - traefik.http.routers.miniflux.tls.certresolver=letsencrypt - traefik.http.services.miniflux.loadbalancer.server.port=8080 db: image: postgres:14 restart: always networks: - internal volumes: - /srv/volumes/miniflux:/var/lib/postgresql/data secrets: - db_password environment: POSTGRES_USER: miniflux POSTGRES_PASSWORD_FILE: /run/secrets/db_password healthcheck: test: [CMD, pg_isready, -U, miniflux] interval: 10s start_period: 30s ```
Author
Owner

Finito.
Ho cambiato tutte le credenziali esistenti.

Quando ci vediamo in officina, lo riguardiamo insieme, chiudiamo quest issue, e poi direi che il repository può essere pubblicato e esteso.

Finito. Ho cambiato tutte le credenziali esistenti. Quando ci vediamo in officina, lo riguardiamo insieme, chiudiamo quest issue, e poi direi che il repository può essere pubblicato e esteso.
Owner

Messo in scheduling per il prossimo GOLEM internals (18 aprile) una ripassata su quanto fatto sui servizi di rete GOLEM, fra cui questo. Chiudo.

Messo in scheduling per il prossimo GOLEM internals (18 aprile) una ripassata su quanto fatto sui servizi di rete GOLEM, fra cui questo. Chiudo.
Sign in to join this conversation.
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Reference: golem/morgan#18
No description provided.