Utilizzo delle chiavi SSH all'interno del contenitore finestra mobile


324

Ho un'app che esegue varie cose divertenti con Git (come eseguire git clone e git push) e sto cercando di agganciarlo.

Sto riscontrando un problema in cui è necessario poter aggiungere una chiave SSH al contenitore per l'utilizzo da parte dell'utente "utente".

Ho provato a copiarlo /root/.ssh/, a cambiarlo $HOME, creando un wrapper git ssh, e ancora senza fortuna.

Ecco il Dockerfile per riferimento:

#DOCKER-VERSION 0.3.4                                                           

from  ubuntu:12.04                                                              

RUN  apt-get update                                                             
RUN  apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN  add-apt-repository ppa:chris-lea/node.js                                   
RUN  echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN  apt-get update                                                             
RUN  apt-get install nodejs -y                                                  

ADD . /src                                                                       
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa                             
RUN   cd /src; npm install                                                      

EXPOSE  808:808                                                                 

CMD   [ "node", "/src/app.js"]

app.js esegue i comandi git come git pull


3
Chiunque si avvicini a questa domanda dovrebbe pensare alla fine del gioco in quanto è facile creare una falla di sicurezza e dimenticarsene qui se non stai attento. Leggi tutte le risposte e scegli con saggezza.
Josh Habdas,

Risposte:


144

È un problema più difficile se devi usare SSH in fase di compilazione. Ad esempio se stai usando git clone, o nel mio caso, pipe npmper scaricare da un repository privato.

La soluzione che ho trovato è quella di aggiungere le tue chiavi usando la --build-argbandiera. Quindi puoi usare il nuovo --squashcomando sperimentale (aggiunto 1.13) per unire i livelli in modo che le chiavi non siano più disponibili dopo la rimozione. Ecco la mia soluzione:

Comando Build

$ docker build -t example --build-arg ssh_prv_key="$(cat ~/.ssh/id_rsa)" --build-arg ssh_pub_key="$(cat ~/.ssh/id_rsa.pub)" --squash .

Dockerfile

FROM python:3.6-slim

ARG ssh_prv_key
ARG ssh_pub_key

RUN apt-get update && \
    apt-get install -y \
        git \
        openssh-server \
        libmysqlclient-dev

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan github.com > /root/.ssh/known_hosts

# Add the keys and set permissions
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    echo "$ssh_pub_key" > /root/.ssh/id_rsa.pub && \
    chmod 600 /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa.pub

# Avoid cache purge by adding requirements first
ADD ./requirements.txt /app/requirements.txt

WORKDIR /app/

RUN pip install -r requirements.txt

# Remove SSH keys
RUN rm -rf /root/.ssh/

# Add the rest of the files
ADD . .

CMD python manage.py runserver

Aggiornamento: se stai usando Docker 1.13 e hai funzionalità sperimentali su puoi aggiungere --squashal comando build che unirà i livelli, rimuovendo le chiavi SSH e nascondendole docker history.


13
Questo thread di emissione di GitHub indicherebbe che questo approccio non è ancora sicuro. Vedi questo commento per un'altra soluzione simile.
eczajk,

4
Un'altra soluzione invece di schiacciare è aggiungere e rimuovere la chiave nello stesso comando RUN, e tra l'aggiunta e la rimozione la usi per quello che ti serve.
Benjamin Hammer Nørgaard,

2
Forse puoi rimuovere le linee per la creazione del id_rsa.pubfile in quanto non è richiesto.
LCB

1
Invece di schiacciare, fai uso di build di immagini multi-fase .
Richard Kiefer,

Se la chiave è protetta da password, utilizzare $(openssl rsa -in ~/.ssh/id_rsa)invece
BroiSatse

89

Risulta quando si utilizza Ubuntu, ssh_config non è corretto. Devi aggiungere

RUN  echo "    IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config

al tuo Dockerfile per farlo riconoscere la tua chiave ssh.


2
Probabilmente dovrai anche impostare il nome utente corretto come questoRUN echo " Host example.com" >> /root/.ssh/config RUN echo " User <someusername>" >> /root/.ssh/config
monofone

1
Perché qualcuno dovrebbe copiare la chiave privata da una macchina host in un contenitore. Il comando è OK, ma non vedo il senso nel fare di cui sopra ...
Vladimir Djuricic

12
Questo non è sicuro! Vedi la mia soluzione di seguito per l'ultima versione 1.13 di Docker. @ebensing
Daniel van Flymen,

1
@VladimirDjuricic Tuttavia ci sono cose come le chiavi di distribuzione.
Zelphir Kaltstahl,

in realtà è necessario eseguire ssh-keygen -A per configurare correttamente ssh sul contenitore minimo di Ubuntu. Quindi è possibile aggiungere le chiavi pub / priv e avviare sshd. Ho questa voce nel mio file docker: 'RUN ssh-keygen -A' come uno dei passaggi.
piotrektt,

84

Nota : utilizzare questo approccio solo per le immagini che sono private e lo saranno sempre !

La chiave ssh rimane memorizzata nell'immagine, anche se la chiave viene rimossa in un comando di livello dopo averla aggiunta (vedere i commenti in questo post ).

Nel mio caso va bene, quindi è quello che sto usando:

# Setup for ssh onto github
RUN mkdir -p /root/.ssh
ADD id_rsa /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

91
Ciò manterrà la tua chiave nell'immagine, non farlo.
CppLearner

12
@CppLearner hai ragione, questo memorizza la chiave nell'immagine e potrebbe essere un problema di sicurezza in alcuni casi. Grazie per averlo evidenziato. Tuttavia, ci sono molte situazioni in cui questo è perfettamente salvabile. Ad esempio, per le immagini archiviate in un repository privato o le immagini create direttamente su un server di produzione copiando le chiavi locali sull'immagine.
yellowcap

2
Inoltre, se installi i tuoi fornitori all'interno del Dockerfile, non c'è nulla che ti impedisca di rimuovere la chiave ssh dopo l'installazione dei fornitori.
SebScoFr

2
@SebScoFr, apparentemente le chiavi verranno memorizzate in uno dei livelli, anche se le rimuovi in ​​un comando successivo (vedi link nella risposta aggiornata). Quindi l'immagine esporrà sempre il tasto ssh e la soluzione dovrebbe essere usata solo per immagini private!
yellowcap

1
@yellowcap no se - annulla la build
Anoyz

57

Se stai usando la finestra mobile componi una scelta facile è inoltrare l'agente SSH in questo modo:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent

23
Solo una nota che questo non funziona per gli host Mac, sia che si tratti di docker-machine (tramite VirtualBox) o Docker per Mac (che utilizza xhyve) perché i socket del dominio unix non sono sottoposti a proxy.
Joe Shaw,

SSH_AUTH_SOCKè una variabile, che contiene un percorso per un agente ssh
Aistis,


1
ssh-forwarding è ora supportato anche su host macOS - invece di montare il percorso di $SSH_AUTH_SOCK, devi montare questo percorso - /run/host-services/ssh-auth.sock.
Jakub Kukul il

47

Espandendo la risposta di Peter Grainger Sono stato in grado di utilizzare la build multi-stage disponibile dalla Docker 17.05. La pagina ufficiale afferma:

Con build multi-stage, usi più FROMistruzioni nel tuo Dockerfile. Ogni FROMistruzione può usare una base diversa e ognuna di esse inizia una nuova fase della build. Puoi copiare in modo selettivo artefatti da uno stadio all'altro, lasciando tutto ciò che non vuoi nell'immagine finale.

Tenere presente questo è il mio esempio di Dockerfileincludere tre fasi di costruzione. Ha lo scopo di creare un'immagine di produzione dell'applicazione Web client.

# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
    echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
    printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
    yarn --pure-lockfile --mutex file --network-concurrency 1 && \
    rm -rf /root/.ssh/

# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignoreripete il contenuto del .gitignorefile (impedisce node_modulesche le distdirectory risultanti del progetto vengano copiate):

.idea
dist
node_modules
*.log

Esempio di comando per creare un'immagine:

$ docker build -t ezze/geoport:0.6.0 \
  --build-arg SSH_KEY="$(cat ~/.ssh/id_rsa)" \
  --build-arg SSH_KEY_PASSPHRASE="my_super_secret" \
  ./

Se la tua chiave SSH privata non ha una passphrase, specifica semplicemente un SSH_KEY_PASSPHRASEargomento vuoto .

È così che funziona:

1). Solo nella prima fase package.json, i yarn.lockfile e la chiave SSH privata vengono copiati nella prima immagine intermedia denominata sources. Per evitare ulteriori prompt della passphrase della chiave SSH, viene aggiunto automaticamente ssh-agent. Infine il yarncomando installa tutte le dipendenze richieste da NPM e clona i repository git privati ​​da Bitbucket su SSH.

2). La seconda fase crea e minimizza il codice sorgente dell'applicazione Web e lo posiziona nella distdirectory della successiva immagine intermedia denominata production. Si noti che il codice sorgente di installato node_modulesviene copiato dall'immagine denominata sourcesprodotta nel primo stadio da questa riga:

COPY --from=sources /app/ /app/

Probabilmente potrebbe anche essere la seguente riga:

COPY --from=sources /app/node_modules/ /app/node_modules/

node_modulesQui abbiamo solo directory dalla prima immagine intermedia, no SSH_KEYe SSH_KEY_PASSPHRASEargomenti. Tutto il resto necessario per la compilazione viene copiato dalla nostra directory di progetto.

3). Nella terza fase riduciamo una dimensione dell'immagine finale che verrà taggata ezze/geoport:0.6.0includendo solo la distdirectory della seconda immagine intermedia denominata productione installando Node Express per l'avvio di un web server.

Elencare le immagini fornisce un output come questo:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        3 hours ago         717MB
<none>              <none>              1f6518644324        3 hours ago         1.1GB
<none>              <none>              fa00f1182917        4 hours ago         1.63GB
node                carbon              b87c2ad8344d        4 weeks ago         676MB

dove le immagini senza tag corrispondono alla prima e alla seconda fase di costruzione intermedia.

Se corri

$ docker history ezze/geoport:0.6.0 --no-trunc

non vedrai alcuna menzione di SSH_KEYe SSH_KEY_PASSPHRASEnell'immagine finale.


Vecchio post, ma voglio sottolineare che questo è di gran lunga il modo migliore per farlo prima del 18.09. Lo squash è superfluo e rischioso. Con il multi-stage, sai che stai solo portando gli artefatti che desideri. Pensa a squash come opt-out dei file che non vuoi, e multistage come opt-in. Questa risposta deve essere più alta. Cuocere le tue chiavi ssh nell'immagine è una pratica terribile.
mritalian

@ezze Grazie mille per questo utilissimo post :) L'agente SSH mi sta facendo impazzire, ho fatto qualcosa di simile a quello che hai fatto: vedo correttamente nei log di compilazione della finestra mobile Identity added: /root/.ssh/id_rsa (/root/.ssh/id_rsa)ma quando eseguo il check in un altro RUN o anche nello stesso RUN eseguendo un comando ssh-add -lmi dice che "L'agente non ha identità". Cominciando a togliermi i capelli, qualche pensiero?
Alex

40

Per iniettarti la chiave ssh, all'interno di un contenitore, hai più soluzioni:

  1. Utilizzando un file Docker con l' ADDistruzione, è possibile iniettarlo durante il processo di generazione

  2. Semplicemente facendo qualcosa di simile cat id_rsa | docker run -i <image> sh -c 'cat > /root/.ssh/id_rsa'

  3. Utilizzando il docker cpcomando che consente di iniettare file mentre un contenitore è in esecuzione.


2
Quindi, fin d'ora, ho provato a copiarlo in /root/.ssh/id_rsa ma continuo a ricevere errori di verifica della chiave dell'host non riusciti. Fatale: l'estremità remota ha riattaccato inaspettatamente "errori da Git, che sono abbastanza sicuro che significa non sta usando la chiave per nessun motivo. Quindi sto pensando che c'è qualcos'altro che devo fare per dire al sistema di usarlo come è la chiave ssh? Non sono sicuro di come eseguire il debug di questo. (e so che questa chiave funziona perché funziona senza problemi dall'host)
ebensing

puoi assicurarti che / etc / ssh / ssh_config abbia come target il file chiave corretto?
Creack

1
Esiste un buon modo per ispezionare i file del contenitore della finestra mobile? O dovrei solo provare a copiare in una configurazione valida?
ebensing

3
Ho appena provato con l'immagine 'base', facendo apt-get install openssh-servere mettendo la mia chiave in /root/.ssh/id_rsa e ha funzionato bene. Quale immagine stai usando?
Creack

se è necessario ispezionare il file di un container, il modo migliore sarebbe quello di eseguire il commit e l'esecuzione dell'immagine risultante con 'cat'.
Creack

15

Una soluzione multipiattaforma consiste nell'utilizzare un mount bind per condividere la .sshcartella dell'host sul contenitore:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

Simile all'inoltro dell'agente, questo approccio renderà le chiavi pubbliche accessibili al contenitore. Un ulteriore vantaggio è che funziona anche con un utente non root e ti collegherà a GitHub. Un avvertimento da considerare, tuttavia, è che tutti i contenuti (comprese le chiavi private) della .sshcartella saranno condivisi, quindi questo approccio è desiderabile solo per lo sviluppo e solo per le immagini dei container attendibili.


1
questo potrebbe funzionare, ma non docker buildsolo durantedocker run
Alexander Mills,

3
Questo è esattamente il punto. Non vuoi mettere le tue chiavi ssh in un file docker.
Mohammad Azim,

2
Dato che l'inoltro dell'agente SSH non funziona al di fuori di Linux, questa è un'ottima soluzione per essere operativi in ​​un ambiente di sviluppo senza troppi problemi.
Josh Habdas,

Sto eseguendo la finestra mobile usando docker-compose upnella mia Windows 10. Come dovrei usare la soluzione in quello scenario?
llaaalu,

In sostanza, stai chiedendo come mappare il volume nella composizione docker. Sopra c'è una risposta che risponde a questa domanda. In particolare per Windows questo potrebbe aiutare stackoverflow.com/questions/41334021/…
Mohammad Azim

14

I container Docker dovrebbero essere visti come "servizi" propri. Per separare le preoccupazioni è necessario separare le funzionalità:

1) I dati dovrebbero essere in un contenitore di dati: utilizzare un volume collegato per clonare il repository. Tale contenitore di dati può quindi essere collegato al servizio che lo necessita.

2) Utilizzare un contenitore per eseguire l'attività di clonazione git, (ovvero è solo il lavoro è la clonazione) che collega il contenitore di dati ad esso quando lo si esegue.

3) Lo stesso per il tasto ssh: inseriscilo in un volume (come suggerito sopra) e collegalo al servizio clone git quando ne hai bisogno

In questo modo, sia l'attività di clonazione che la chiave sono effimere e attive solo quando necessario.

Ora, se la tua stessa app è un'interfaccia git, potresti prendere in considerazione le API REST github o bitbucket direttamente per fare il tuo lavoro: è per questo che sono state progettate.


13

Questa riga è un problema:

ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa

Quando si specificano i file che si desidera copiare nell'immagine, è possibile utilizzare solo percorsi relativi, relativi alla directory in cui si trova il file Docker. Quindi dovresti invece usare:

ADD id_rsa /root/.ssh/id_rsa

E metti il ​​file id_rsa nella stessa directory dove si trova il tuo Dockerfile.

Dai un'occhiata a questo per maggiori dettagli: http://docs.docker.io/reference/builder/#add


4
Questo è anche un problema di sicurezza perché inserisce una chiave privata in un'immagine che può essere facilmente dimenticata.
Mike D,

docker cplo mette solo nel contenitore e non nell'immagine, giusto?
Alexander Mills,

13

Abbiamo riscontrato un problema simile durante l'installazione di npm in fase di creazione della finestra mobile.

Ispirato alla soluzione di Daniel van Flymen e combinandola con la riscrittura di git url , abbiamo trovato un metodo un po 'più semplice per autenticare l'installazione di npm dai repository github privati: abbiamo usato i token oauth2 invece delle chiavi.

Nel nostro caso, le dipendenze npm sono state specificate come "git + https://github.com/ ..."

Per l'autenticazione nel contenitore, gli URL devono essere riscritti per essere adatti all'autenticazione ssh (ssh: //git@github.com/) o autenticazione token (https: // $ {GITHUB_TOKEN} @ github.com /)

Comando di costruzione:

docker build -t sometag --build-arg GITHUB_TOKEN=$GITHUB_TOKEN . 

Sfortunatamente, sono sulla finestra mobile 1.9, quindi l'opzione --squash non è ancora presente, alla fine deve essere aggiunta

Dockerfile:

FROM node:5.10.0

ARG GITHUB_TOKEN

#Install dependencies
COPY package.json ./

# add rewrite rule to authenticate github user
RUN git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/"

RUN npm install

# remove the secret token from the git config file, remember to use --squash option for docker build, when it becomes available in docker 1.13
RUN git config --global --unset url."https://${GITHUB_TOKEN}@github.com/".insteadOf

# Expose the ports that the app uses
EXPOSE 8000

#Copy server and client code
COPY server /server 
COPY clients /clients

11

Inoltra il socket di autenticazione ssh al contenitore:

docker run --rm -ti \
        -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock \
        -e SSH_AUTH_SOCK=/tmp/ssh_auth.sock \
        -w /src \
        my_image

Il tuo script sarà in grado di eseguire un git clone.

Extra: se si desidera che i file clonati appartengano a un utente specifico, è necessario utilizzarli chownpoiché l'utilizzo di un utente diverso da root all'interno del contenitore non riuscirà git.

È possibile eseguire questa pubblicazione nell'ambiente del contenitore alcune variabili aggiuntive:

docker run ...
        -e OWNER_USER=$(id -u) \
        -e OWNER_GROUP=$(id -g) \
        ...

Dopo aver clonato, è necessario eseguire chown $OWNER_USER:$OWNER_GROUP -R <source_folder>l'impostazione della proprietà corretta prima di lasciare il contenitore in modo che i file siano accessibili da un utente non root all'esterno del contenitore.


1
Nelle versioni Docker più recenti puoi passare -u root:$(id -u $USER)almeno per avere i file di proprietà dello stesso gruppo primario dell'utente, il che dovrebbe renderli almeno leggibili senza sudoche qualcosa non li crei con le 0600autorizzazioni.
dragon788,

@ dragon788 Penso che tu abbia un refuso: -u root:$(id -u $USER)dovrebbe essere -g.
edupo,

Ottima scelta! Non riesco a risolverlo dal cellulare, proverò presto sul desktop.
dragon788,

Ho /tmp/ssh_auth.sock: No such file or directoryora è /tmp/ssh-vid8Zzi8UILE/agent.46016sulla mia macchina host
vladkras

@vladkras l'errore è piuttosto generico. Potrebbe essere causato a causa delle autorizzazioni /tmpall'interno del contenitore. O un refuso sul comando Esegui finestra mobile. Assicurarsi che l'istruzione bind sia corretta -v $SSH_AUTH_SOCK:/tmp/ssh_auth.sock: l'ordine è importante e anche il punto e virgola è importante. Per ulteriori informazioni, consultare la documentazione della finestra mobile .
edupo,

10

Come già commentato eczajk nella risposta di Daniel van Flymen, non sembra sicuro rimuovere le chiavi e utilizzarle --squash, poiché saranno ancora visibili nella storia ( docker history --no-trunc).

Invece con Docker 18.09, ora puoi usare la funzione "Costruisci segreti". Nel mio caso ho clonato un repository git privato usando la mia chiave SSH hosts con il seguente nel mio Dockerfile:

# syntax=docker/dockerfile:experimental

[...]

RUN --mount=type=ssh git clone [...]

[...]

Per poterlo utilizzare, è necessario abilitare il nuovo backend BuildKit prima di eseguire docker build:

export DOCKER_BUILDKIT=1

E devi aggiungere il --ssh defaultparametro a docker build.

Maggiori informazioni al riguardo qui: https://medium.com/@tonistiigi/build-secrets-and-ssh-forwarding-in-docker-18-09-ae8161d066


1
La migliore soluzione IMHO. Ho dovuto fare altre due cose per farlo funzionare: 1) aggiungere la mia chiave privata a ssh-agent con ssh-add ~/.ssh/id_rsae 2) aggiungere l'host git a known_hosts, cioè per bitbucket:RUN ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts
Moritz Ringler

Non sono stato in grado di farlo funzionare affatto. Sto ancora ricevendo autorizzazioni errori: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access and the repository exists.Questo nonostante passando la --ssh defaultbandiera nella mia finestra mobile di generazione, e l'utilizzo --mount=type=sshnel comando di marcia in cui ho git clone. Sono in grado di clonare lo stesso repository senza problemi sulla macchina di compilazione. Non riesce semplicemente nel contenitore di generazione della finestra mobile. Sospetto che la versione mac di Docker non stia effettivamente passando il client ssh.
PMende,

@PMende sei riuscito a capire questo problema che hai citato perché anch'io sto affrontando lo stesso.
Sadan A.

@SadanArshad Si scopre che questa funzionalità è attualmente supportata solo se si esegue Docker da una macchina Linux. Non funziona se stai eseguendo i comandi Docker da un Mac (e probabilmente anche da Windows, anche se non posso confermare).
PMende,

Peccato che non funziona con docker-compose ... github.com/docker/compose/issues/6440
Alexis Wilke

9

Questo problema è davvero fastidioso. Dato che non puoi aggiungere / copiare alcun file al di fuori del contesto del file docker, il che significa che è impossibile semplicemente collegare ~ / .ssh / id_rsa in /root/.ssh/id_rsa dell'immagine e quando hai sicuramente bisogno di una chiave per fare qualcosa di sshed come il clone di git da un collegamento repository privato ..., durante la creazione dell'immagine della finestra mobile.

Comunque, ho trovato una soluzione per aggirare il problema, non così convincente, ma ha funzionato per me.

  1. nel tuo file docker:

    • aggiungi questo file come /root/.ssh/id_rsa
    • fai quello che vuoi, come git clone, compositore ...
    • rm /root/.ssh/id_rsa alla fine
  2. una sceneggiatura da fare in una sola ripresa:

    • cp la chiave per la cartella contenente il file docker
    • build docker
    • rm la chiave copiata
  3. ogni volta che devi eseguire un container da questa immagine con alcuni requisiti ssh, aggiungi -v per il comando run, come:

    docker run -v ~ / .ssh / id_rsa: /root/.ssh/id_rsa --name container image comando

Questa soluzione non comporta alcuna chiave privata sia nell'origine del progetto che nell'immagine docker integrata, quindi nessun problema di sicurezza di cui preoccuparsi più.


1
"Dato che non puoi aggiungere / copiare alcun file al di fuori del contesto del file docker," Hai visto docker cp? È usato per "Copia file / cartelle tra un contenitore e il tuo host".
Jonathon Reinhart,

@JonathonReinhart, grazie per averlo sottolineato. Sì, docker cppotrebbe fare il trucco. Tuttavia, proprio in questa situazione, avevo bisogno di ssh_key durante la creazione dell'immagine, e non c'è nessun contenitore in quel momento ... aggiornerà la mia espressione poco chiara, grazie comunque.
ImLeo,

9

Ho riscontrato lo stesso problema oggi e versione leggermente modificata con i post precedenti ho trovato questo approccio più utile per me

docker run -it -v ~/.ssh/id_rsa:/root/.my-key:ro image /bin/bash

(Nota che il flag di sola lettura in modo che container non rovini la mia chiave ssh in ogni caso.)

All'interno del contenitore ora posso eseguire:

ssh-agent bash -c "ssh-add ~/.my-key; git clone <gitrepourl> <target>"

Quindi non ricevo Bad owner or permissions on /root/.ssh/..quell'errore che è stato notato da @kross


Grazie! Questa è stata la chiave per farlo funzionare per me: avere l'ssh-agent e ssh-add in un unico comando come: ssh-agent bash -c "ssh-add...". Posso quindi passare questo diritto in modalità docker run. Tutti gli esempi precedenti che ho trovato usati eval ssh-agent, seguiti da ssh-add e non sono riuscito a trovare un modo per farlo passare evalattraverso il comando run docker.
Ryanman,


6

Puoi anche collegare la tua directory .ssh tra l'host e il contenitore, non so se questo metodo abbia implicazioni per la sicurezza, ma potrebbe essere il metodo più semplice. Qualcosa del genere dovrebbe funzionare:

$ sudo docker run -it -v /root/.ssh:/root/.ssh someimage bash

Ricorda che la finestra mobile funziona con sudo (a meno che tu non lo faccia), in questo caso utilizzerai i tasti root ssh.


L'uso di questo metodo funziona con la finestra mobile 0.11 ma se si utilizza fig, si genererà un errore di panico. Non so perché
Luis Elizondo,

3
Questo sarebbe un metodo preferito, il trucco sarebbe usare le chiavi dell'utente privato senza privilegi come root del contenitore. Come accennato, provando a farlo non come cede l'utente root dell'host Bad owner or permissions on /root/.ssh/config.
Kross,

questo può essere usato solo durante docker run, ma non durante docker build.
ccpizza,

3
@ccpizza, lo considero un vantaggio. Molte di queste risposte lasciano le chiavi private memorizzate in un'immagine; la chiave rimane memorizzata anche dopo aver rimosso la chiave in un successivo comando di livello. Introducendo le chiavi private solo durante l'esecuzione (non build), possono esistere solo nel contenitore (non nell'immagine).
cowlinator,

6

A partire da docker API 1.39+(Verifica versione API con docker version) la finestra mobile build consente di--ssh opzione con un socket agente o le chiavi per consentire al motore Docker di inoltrare le connessioni dell'agente SSH.

Build Command

export DOCKER_BUILDKIT=1
docker build --ssh default=~/.ssh/id_rsa .

Dockerfile

# syntax=docker/dockerfile:experimental
FROM python:3.7

# Install ssh client (if required)
RUN apt-get update -qq
RUN apt-get install openssh-client -y

# Download public key for github.com
RUN --mount=type=ssh mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts

# Clone private repository
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject

Ulteriori informazioni:


1
L'espansione della tilde non ha funzionato per me; Ho ottenuto: could not parse ssh: [default=~/.ssh/id_rsa]: stat ~/.ssh/id_rsa: no such file or directory. Utilizzare il percorso completo se non funziona.
slhck,

3

Se non ti interessa la sicurezza delle tue chiavi SSH, ci sono molte buone risposte qui. Se lo fai, la migliore risposta che ho trovato è stata da un link in un commento sopra a questo commento GitHub di diegocsandrim . In modo che altri abbiano maggiori probabilità di vederlo, e nel caso in cui il repository scompaia, ecco una versione modificata di quella risposta:

La maggior parte delle soluzioni qui finisce per lasciare la chiave privata nell'immagine. Questo è negativo, poiché chiunque abbia accesso all'immagine ha accesso alla tua chiave privata. Dal momento che non sappiamo abbastanza sul comportamento di squash, questo potrebbe essere il caso anche se elimini la chiave e schiacci quel livello.

Generiamo un URL di pre-segno per accedere alla chiave con aws s3 cli e limitiamo l'accesso per circa 5 minuti, salviamo questo URL di pre-segno in un file nella directory repo, quindi in dockerfile lo aggiungiamo all'immagine.

In dockerfile abbiamo un comando RUN che esegue tutti questi passaggi: utilizzare l'URL pre-sing per ottenere la chiave ssh, eseguire npm install e rimuovere la chiave ssh.

In questo modo in un singolo comando la chiave ssh non verrebbe memorizzata in alcun livello, ma verrà archiviato l'URL pre-segno e questo non è un problema perché l'URL non sarà valido dopo 5 minuti.

Lo script di build è simile a:

# build.sh
aws s3 presign s3://my_bucket/my_key --expires-in 300 > ./pre_sign_url
docker build -t my-service .

Il file Docker è simile al seguente:

FROM node

COPY . .

RUN eval "$(ssh-agent -s)" && \
    wget -i ./pre_sign_url -q -O - > ./my_key && \
    chmod 700 ./my_key && \
    ssh-add ./my_key && \
    ssh -o StrictHostKeyChecking=no git@github.com || true && \
    npm install --production && \
    rm ./my_key && \
    rm -rf ~/.ssh/*

ENTRYPOINT ["npm", "run"]

CMD ["start"]

1
Il problema con questa soluzione è che, poiché pre_sign_url cambierà ogni volta, l'installazione di npm non può essere memorizzata nella cache anche se non vi sono modifiche al file package.json. È meglio ottenere la chiave in build.sh e impostarla come argomento build in modo che non cambi ogni volta
York Yang,


3

Una breve descrizione delle sfide di SSH all'interno dei container Docker è dettagliata qui . Per connettersi a telecomandi attendibili all'interno di un contenitore senza perdere segreti, ci sono alcuni modi:

Oltre a questi c'è anche la possibilità di utilizzare un keystore in esecuzione in un contenitore docker separato accessibile in fase di esecuzione quando si utilizza Compose. Lo svantaggio è la complessità aggiuntiva dovuta ai macchinari necessari per creare e gestire un keystore come Vault di HashiCorp .

Per l'uso della chiave SSH in un contenitore Docker autonomo, vedere i metodi collegati sopra e considerare gli svantaggi di ciascuno in base alle proprie esigenze specifiche. Se, tuttavia, stai eseguendo Compose e vuoi condividere una chiave con un'app in fase di esecuzione (riflettendo le funzionalità dell'OP) prova questo:

  • Crea un docker-compose.envfile e aggiungilo al tuo.gitignore file.
  • Aggiorna il tuo docker-compose.ymle aggiungienv_file per il servizio che richiede la chiave.
  • Accedere alla chiave pubblica dall'ambiente durante l'esecuzione dell'applicazione, ad esempio process.node.DEPLOYER_RSA_PUBKEYnel caso di un'applicazione Node.js.

L'approccio di cui sopra è ideale per lo sviluppo e il collaudo e, sebbene possa soddisfare i requisiti di produzione, in produzione è meglio utilizzare uno degli altri metodi sopra identificati.

Risorse addizionali:


3

È possibile utilizzare la compilazione in più fasi per creare contenitori Questo è l'approccio che è possibile adottare: -

Fase 1: costruzione di un'immagine con ssh

FROM ubuntu as sshImage
LABEL stage=sshImage
ARG SSH_PRIVATE_KEY
WORKDIR /root/temp

RUN apt-get update && \
    apt-get install -y git npm 

RUN mkdir /root/.ssh/ &&\
    echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa &&\
    chmod 600 /root/.ssh/id_rsa &&\
    touch /root/.ssh/known_hosts &&\
    ssh-keyscan github.com >> /root/.ssh/known_hosts

COPY package*.json ./

RUN npm install

RUN cp -R node_modules prod_node_modules

Fase 2: costruisci il tuo contenitore

FROM node:10-alpine

RUN mkdir -p /usr/app

WORKDIR /usr/app

COPY ./ ./

COPY --from=sshImage /root/temp/prod_node_modules ./node_modules

EXPOSE 3006

CMD ["npm", "run", "dev"] 

aggiungi l'attributo env nel tuo file di composizione:

   environment:
      - SSH_PRIVATE_KEY=${SSH_PRIVATE_KEY}

quindi passa args dallo script build in questo modo:

docker-compose build --build-arg SSH_PRIVATE_KEY="$(cat ~/.ssh/id_rsa)"

E rimuovere il contenitore intermedio per sicurezza. Questo ti aiuterà a fare il tifo.


2

Un modo semplice e sicuro per raggiungere questo obiettivo senza salvare la chiave in un livello di immagine Docker o passare attraverso la ginnastica ssh_agent è:

  1. Come uno dei passaggi nel tuo Dockerfile, crea una .sshdirectory aggiungendo:

    RUN mkdir -p /root/.ssh

  2. Di seguito indica che si desidera montare la directory ssh come volume:

    VOLUME [ "/root/.ssh" ]

  3. Assicurati che il tuo contenitore ssh_configsappia dove trovare le chiavi pubbliche aggiungendo questa riga:

    RUN echo " IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

  4. Esporre la .sshdirectory dell'utente locale al contenitore in fase di esecuzione:

    docker run -v ~/.ssh:/root/.ssh -it image_name

    O nel tuo dockerCompose.ymlaggiungi questo sotto il tasto del volume del servizio:

    - "~/.ssh:/root/.ssh"

Il tuo finale Dockerfiledovrebbe contenere qualcosa come:

FROM node:6.9.1

RUN mkdir -p /root/.ssh
RUN  echo "    IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config

VOLUME [ "/root/.ssh" ]

EXPOSE 3000

CMD [ "launch" ]

1

Sto cercando di risolvere il problema nell'altro modo: aggiungendo la chiave pubblica ssh a un'immagine. Ma nelle mie prove, ho scoperto che "docker cp" è per la copia da un contenitore a un host. L'elemento 3 nella risposta di creak sembra dire che puoi usare la finestra mobile cp per iniettare file in un contenitore. Vedi https://docs.docker.com/engine/reference/commandline/cp/

estratto

Copia file / cartelle dal filesystem di un contenitore nel percorso host. I percorsi sono relativi alla radice del filesystem.

  Usage: docker cp CONTAINER:PATH HOSTPATH

  Copy files/folders from the PATH to the HOSTPATH

Questo URL sembra essere rotto ora.
Slm

Questo è obsoleto o errato. Può copiare entrambe le direzioni, al più tardi al 1.8.2.
Jonathon Reinhart,

1

Puoi passare le chiavi autorizzate al tuo contenitore usando una cartella condivisa e impostare le autorizzazioni usando un file docker come questo:

FROM ubuntu:16.04
RUN apt-get install -y openssh-server
RUN mkdir /var/run/sshd
EXPOSE 22
RUN cp /root/auth/id_rsa.pub /root/.ssh/authorized_keys
RUN rm -f /root/auth
RUN chmod 700 /root/.ssh
RUN chmod 400 /root/.ssh/authorized_keys
RUN chown root. /root/.ssh/authorized_keys
CMD /usr/sbin/sshd -D

E la tua corsa docker contiene qualcosa come il seguente per condividere una directory auth sull'host (tenendo le chiavi_autorizzate) con il contenitore quindi aprire la porta ssh che sarà accessibile attraverso la porta 7001 sull'host.

-d -v /home/thatsme/dockerfiles/auth:/root/auth -–publish=127.0.0.1:7001:22

Potresti voler consultare https://github.com/jpetazzo/nsenter che sembra essere un altro modo per aprire una shell su un contenitore ed eseguire comandi all'interno di un contenitore.


1

Devo ammettere che alla fine della festa ciò che renderà le chiavi del sistema operativo host disponibili per il root all'interno del contenitore, al volo:

docker run -v ~/.ssh:/mnt -it my_image /bin/bash -c "ln -s /mnt /root/.ssh; ssh user@10.20.30.40"

Non sono favorevole all'utilizzo di Dockerfile per installare le chiavi poiché le iterazioni del contenitore potrebbero lasciare indietro le chiavi private.


0

È possibile utilizzare i segreti per gestire tutti i dati sensibili di cui un contenitore ha bisogno in fase di esecuzione ma non si desidera archiviare nell'immagine o nel controllo del codice sorgente, come ad esempio:

  • Nomi utente e password
  • Certificati e chiavi TLS
  • Chiavi SSH
  • Altri dati importanti come il nome di un database o di un server interno
  • Stringhe generiche o contenuto binario (dimensioni fino a 500 kb)

https://docs.docker.com/engine/swarm/secrets/

Stavo cercando di capire come aggiungere le chiavi di firma a un contenitore da utilizzare durante il runtime (non build) e ho riscontrato questa domanda. I segreti di Docker sembrano essere la soluzione per il mio caso d'uso, e poiché nessuno lo ha ancora menzionato, lo aggiungerò.


0

Nel mio caso ho avuto un problema con nodejs e 'npm i' da un repository remoto. Ho risolto il problema aggiungendo l'utente 'node' al container nodejs e da 700 a ~ / .ssh nel container.

Dockerfile:

USER node #added the part
COPY run.sh /usr/local/bin/
CMD ["run.sh"]

run.sh:

#!/bin/bash
chmod 700 -R ~/.ssh/; #added the part

finestra mobile-compose.yml:

nodejs:
      build: ./nodejs/10/
      container_name: nodejs
      restart: always
      ports:
        - "3000:3000"
      volumes:
        - ../www/:/var/www/html/:delegated
        - ./ssh:/home/node/.ssh #added the part
      links:
        - mailhog
      networks:
        - work-network

dopo che ha iniziato a funzionare


-1

Il modo più semplice, ottenere un account launchpad e utilizzare: ssh-import-id


8
La domanda riguardava le chiavi private. ssh-import-idsembra che importa solo le chiavi pubbliche.
cddr

-1

In un contenitore docker in esecuzione, è possibile emettere ssh-keygen con l'opzione docker -i (interattiva). Ciò inoltrerà le richieste del contenitore per creare la chiave all'interno del contenitore della finestra mobile.


1
E poi cosa? Non puoi fare nulla dopo questo, perché non hai il permesso di farlo.
Jonathon Reinhart,

-1

Per debian / root / authorized_keys:

RUN set -x && apt-get install -y openssh-server

RUN mkdir /var/run/sshd
RUN mkdir -p /root/.ssh
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN  echo "ssh-rsa AAAA....yP3w== rsa-key-project01" >> /root/.ssh/authorized_keys
RUN chmod -R go= /root/.ssh
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.