Używanie pliku klucza SSH z Fabric

100

Jak skonfigurować sieć szkieletową do łączenia się ze zdalnymi hostami przy użyciu plików kluczy SSH (na przykład instancji Amazon EC2)?

Yuval Adam
źródło

Odpowiedzi:

69

Warto tutaj również wspomnieć, że możesz użyć do tego argumentów wiersza poleceń:

fab command -i /path/to/key.pem [-H [user@]host[:port]]
Tomasz
źródło
151

Znalezienie prostego pliku fabfile z działającym przykładem użycia pliku klucza SSH nie jest łatwe z jakiegoś powodu. Napisałem o tym post na blogu ( z pasującą treścią ).

Zasadniczo użycie wygląda mniej więcej tak:

from fabric.api import *

env.hosts = ['host.name.com']
env.user = 'user'
env.key_filename = '/path/to/keyfile.pem'

def local_uname():
    local('uname -a')

def remote_uname():
    run('uname -a')

Ważną częścią jest ustawienie env.key_filenamezmiennej środowiskowej, aby konfiguracja Paramiko mogła jej szukać podczas łączenia.

Yuval Adam
źródło
4
w praktyce jest to lepsza odpowiedź.
panchicore
3
env.key_filename może zawierać listę łańcuchów do wypróbowania wielu plików kluczy dla połączenia.
Carl G
Ustawiałem klucz programowo w jednym z moich zadań za pomocą settingsmenedżera kontekstu i nie mogłem go rozpoznać key_filename, dopóki nie zmieniłem go key_filename='/path/to/key'na, key_filename=['/path/to/key']więc jeśli ktoś ma problem, utworzenie key_filename na liście kluczy może to naprawić. To jest z fab 1.10.1 i Paramiko 1.15.2
Jaymon
2
@AseemHegshetye, Został usunięty w najnowszej wersji Fabric 2. Ta odpowiedź dotyczy tkaniny 1.
Iulian Onofrei
1
Wolałbym jawne importowanie zamiast importu *
mit
64

Kolejna fajna funkcja dostępna od Fabric 1.4 - Fabric obsługuje teraz konfiguracje SSH .

Jeśli masz już wszystkie parametry połączenia SSH w swoim ~/.ssh/configpliku, Fabric będzie je obsługiwał natywnie, wystarczy, że dodasz:

env.use_ssh_config = True

na początku twojego pliku fabfile.

Yuval Adam
źródło
2
Bardzo przydatne! Jeśli napotkasz błędy, takie jak IOError: [Errno 2] No such file or directory: ' /path/to/.ssh/key'lub Login password for ' root':po prostu upewnij się, że nie masz białych znaków w pliku .ssh/config. Na przykład User=rootzamiast User = root...
dennis
@dennis To wciąż wydaje się być problemem w 2016 roku ..! Dzięki!
gabn88
17

W przypadku tkaniny 2 w pliku fabfile użyj następującego:

from fabric import task, Connection

@task
def staging(ctx):
    ctx.name = 'staging'
    ctx.user = 'ubuntu'
    ctx.host = '192.1.1.1'
    ctx.connect_kwargs.key_filename = os.environ['ENV_VAR_POINTS_TO_PRIVATE_KEY_PATH']

@task
def do_something_remote(ctx):
    with Connection(ctx.host, ctx.user, connect_kwargs=ctx.connect_kwargs) as conn:
        conn.sudo('supervisorctl status')

i uruchom go z:

fab staging do_something_remote

AKTUALIZACJA:
W przypadku wielu hostów (jeden host też to zrobi) możesz użyć tego:

from fabric2 import task, SerialGroup

@task
def staging(ctx):
    conns = SerialGroup(
        '[email protected]',
        '[email protected]',
        connect_kwargs=
        {
            'key_filename': os.environ['PRIVATE_KEY_TO_HOST']
        })
    ctx.CONNS = conns
    ctx.APP_SERVICE_NAME = 'google'

@task
def stop(ctx):
    for conn in ctx.CONNS:
        conn.sudo('supervisorctl stop ' + ctx.APP_SERVICE_NAME)

i uruchom go z fab lub fab2:

fab staging stop
MikeL
źródło
1
Jest to właściwy sposób postępowania w przypadku tkaniny 2.x, ponieważ wszystkie inne odpowiedzi nie będą działać.
Vivek Aditya
Jak obsługiwać wiele hostów w tym stagingzadaniu?
Black_Rider
1
@Black_Rider, dodał to do mojej odpowiedzi
MikeL
15

U mnie nie zadziałało:

env.user=["ubuntu"]
env.key_filename=['keyfile.pem']
env.hosts=["xxx-xx-xxx-xxx.ap-southeast-1.compute.amazonaws.com"]

lub

fab command -i /path/to/key.pem [-H [user@]host[:port]]

Jednak zrobiły to:

env.key_filename=['keyfile.pem']
env.hosts=["[email protected]"]

lub

env.key_filename=['keyfileq.pem']
env.host_string="[email protected]"
Gaurav Toshniwal
źródło
3
Twój pierwszy przykład działa dla mnie, jeśli używasz env.user="ubuntu"zamiast env.user=["ubuntu"].
Taylor Edmiston
7

Musiałem to zrobić dzisiaj, mój plik .py był tak prosty, jak to tylko możliwe, jak ten opublikowany w odpowiedzi @YuvalAdam, ale wciąż otrzymywałem monit o hasło ...

Patrząc na paramikodziennik (bibliotekę używaną przez Fabric dla ssh), znalazłem wiersz:

Niezgodny element równorzędny ssh (brak akceptowalnego algorytmu Kex)

Zaktualizowałem paramiko:

sudo pip install paramiko --upgrade

A teraz to działa.

flagg19
źródło
1

Jak wspomniano powyżej, Fabric będzie obsługiwał ustawienia pliku .ssh / config po pewnym czasie, ale użycie pliku pem dla ec2 wydaje się być problematyczne. IOW poprawnie skonfigurowany plik .ssh / config będzie działał z wiersza poleceń poprzez „ssh servername” i nie będzie działał z „fab somethingask”, gdy env.host = [„servername”].

Zostało to przezwyciężone przez określenie env.key_filename = 'keyfile' w moim fabfile.py i powielenie wpisu IdentityFile już w moim .ssh / config.

Może to być Fabric lub Paramiko, czyli w moim przypadku Fabric 1.5.3 i Paramiko 1.9.0.

Jeff Doran
źródło
1

Żadna z tych odpowiedzi nie działała dla mnie na py3.7, fabric2.5.0 i paramiko 2.7.1.

Jednak użycie atrybutu PKey w dokumentacji działa: http://docs.fabfile.org/en/2.5/concepts/authentication.html#private-key-objects

from paramiko import RSAKey
ctx.connect_kwargs.pkey = RSAKey.from_private_key_file('path_to_your_aws_key')
with Connection(ctx.host, user, connect_kwargs=ctx.connect_kwargs) as conn:
    //etc.... 
Keith Entzeroth
źródło