hashicorp vault в режиме HA с integrated storage(raft)

Thank you for reading this post, don't forget to subscribe!

1.Общее по hashicorp vault
2.Установка keepalived
3.Установка hashicorp vault
3.1Создание клю­чей
3.2.Конфигурация vault
3.3.Добавление сер­ти­фи­ка­тов в доверенные
4.Создание мето­да аутен­ти­фи­ка­ции user/password
4.1Создание admin policy для user
4.2.Добавление group с admin правами
4.3.Добавление допол­ни­тель­но­го поль­зо­ва­те­ля в группу
4.4 Настро­им все те же досту­пы но с помо­щью команд
5.Аутентификация через gitlab
6. Auto unseal hashicorp vault
6.1 уста­нов­ка minikub
6.2 под­го­тов­ка хра­ни­ли­ща для PV (nfs)
6.3 уста­нов­ка vault в minikub
6.4 auto unseal vault с помо­щью дру­го­го vault
7.Бэкап данных(backup raft)
8. Настрой­ка LDAP — freeipa
9. Добав­ля­ем сек­ре­ты из vault в POD (vault уста­нов­лен в k8s)
9.1 secrets-store-csi-driver
9.2 Vault Secrets Operator (наи­бо­лее опти­маль­ный вари­ант для использования)
9.2.1 При­мер с под­ки­ды­ва­ни­ем сек­ре­та в deployment
9.2.2 Вклю­че­ние Vault Secrets Operator reloader

10.SSH аутен­ти­фи­ка­ция через vault
10.1 SSH аутен­ти­фи­ка­ция через vault OTP (вре­мен­ный пароль)
10.2 SSH аутен­ти­фи­ка­ция через vault SSH (certificate authority)

 

Vault поз­во­ля­ет хра­нить сек­ре­ты, токе­ны, паро­ли, сер­ти­фи­ка­ты и т.п., предо­став­ляя к ним огра­ни­чен­ный и без­опас­ный доступ. Есте­ствен­но, внут­ри Vault все хра­нит­ся в зашиф­ро­ван­ном виде.
Под катом про­це­ду­ра инстал­ля­ция и запуск Vault на трех узлах в отка­зо­устой­чи­вом режиме.

В про­стом вари­ан­те Vault состо­ит из неко­то­ро­го коли­че­ства вза­и­мо­свя­зан­ных меж­ду собой сер­ве­ров, один из кото­рых рабо­та­ет в режи­ме active, а осталь­ные в режи­ме standby.

HA, либо High Availability поз­во­ля­ет выдер­жать поте­рю одно­го или несколь­ких узлов (в зави­си­мо­сти от кофи­гу­ра­ции), сохра­нив при этом доступ к дан­ным. Не со все­ми бэк­эн­да­ми, исполь­зу­е­мы­ми для хра­не­ния, воз­мож­но исполь­зо­вать HA механизм.

Для хра­не­ния дан­ных Vault может исполь­зо­вать боль­шое коли­че­ство бэк­эн­дов.

Пол­но­стью под­дер­жи­ва­е­мые HC бэк­эн­ды (не все, но основные):
Filesystem – назва­ние гово­рит само за себя. Хра­ним дан­ные на локаль­ной фай­ло­вой систе­ме, там же, где и уста­нов­лен Vault. Не под­хо­дит для HA конфигурации;

Consul – Так же явля­ет­ся раз­ра­бот­кой HashiCorp. Исполь­зо­ва­ние в каче­стве бэк­эн­да поз­во­ля­ет реа­ли­зо­вать Vault HA. Одна­ко, дан­ный вари­ант потре­бу­ет раз­вер­ты­ва­ния допол­ни­тель­ных машин и орга­ни­за­ции отдель­но­го кла­сте­ра Consul (ну либо все в одном, но я не люби­тель такого);

Integrated Storage (Raft) – дан­ные Vault так же хра­нят­ся на фай­ло­вой систе­ме, но при этом реп­ли­ци­ру­ют­ся на дру­гие узлы кла­сте­ра, поз­во­ляя им оста­вать­ся доступ­ны­ми даже в слу­чае выхо­да из строя одно­го из узлов. Дан­ный вари­ант под­дер­жи­ва­ет функ­ци­о­нал HA.

Мой выбор в дан­ном слу­чае – Integrated Storage.

Итак, нач­нем с под­го­тов­ки машин. В моем слу­чае это три маши­ны (мини­маль­ное коли­че­ство для кворума) 

добав­ля­ем в hosts на все тачки

cat /etc/hosts

192.168.1.171 vault1 vault1.test.local
192.168.1.172 vault2 vault2.test.local
192.168.1.173 vault3 vault3.test.local
192.168.1.174 vault.test.local

айпиш­ник 192.168.1.174 - виртуальный

ста­вим на все тачки:

yum install -y yum-utils wget curl
yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

и отклю­ча­ем SELINUX на ВСЕХ тачках

cat /etc/selinux/config

sed -i 's|SELINUX=enforcing|SELINUX=disabled|g' /etc/selinux/config

ребу­та­ем­ся.

теперь поставим keepalived ОБЯЗАТЕЛЬНО 2 версии

на каж­дую ноду ставим:

wget http://www.nosuchhost.net/~cheese/fedora/packages/epel-7/x86_64/cheese-release-7-1.noarch.rpm
rpm -Uvh cheese-release*rpm
yum install keepalived -y

systemctl enable keepalived

если есть firewall то добав­ля­ем в раз­ре­шён­ные про­то­кол vrrp

firewall-cmd --permanent --add-rich-rule='rule protocol value="vrrp" accept'
firewall-cmd --reload

mkdir /usr/libexec/keepalived/

chmod +x /usr/libexec/keepalived/vault-health

mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.old

cat /etc/keepalived/keepalived.conf

groupadd -r keepalived_script
useradd -r -s /sbin/nologin -g keepalived_script -M keepalived_script
systemctl enable --now keepalived.service

Далее ставим vault

yum -y install vault

про­ве­ря­ем:

Откры­ва­ем необ­хо­ди­мые для рабо­ты Vault порты:

Далее необ­хо­ди­мо обза­ве­стись сер­ти­фи­ка­та­ми. Если тако­вые отсут­ству­ют – выпу­стить свои, само­под­пи­сан­ные. Все опе­ра­ции я выпол­няю с пер­вой ноды.

Спер­ва выпу­стим свой CA сер­ти­фи­кат, а затем с его помо­щью под­пи­шем сер­ти­фи­ка­ты для всех узлов кластера:

Теперь под­го­то­вим кон­фи­гу­ра­ци­он­ные фай­лы, содер­жа­щие Subject Alternate Name (SAN) для каж­до­го из узлов. Важ­но, что­бы в SAN был кор­рект­ней хост­нейм и IP каж­до­го узла:

Теперь для каж­до­го из узлов сфор­ми­ру­ем CSR файл:

И выпу­стим сер­ти­фи­ка­ты на осно­ва­нии запросов:


вывод следующий:

Ско­пи­ру­ем сер­ти­фи­ка­ты и клю­чи на узлы B и C:

На каж­дом из узлов уста­но­вим соот­вет­ству­ю­щие пра­ва для досту­па к фай­лам сер­ти­фи­ка­тов и ключам:

Теперь, когда для каж­дой из нод гото­вы сертификаты.

 

Перей­дем к кон­фи­гу­ра­ции Vault.
Отре­дак­ти­ру­ем кон­фи­гу­ра­ци­он­ный файл vault для пер­вой ноды:

вто­рая нода:

cp /etc/vault.d/vault.hcl /etc/vault.d/vault.hcl.backup

[root@vault2 ~]# cat /etc/vault.d/vault.hcl

тре­тья нода:

cp /etc/vault.d/vault.hcl /etc/vault.d/vault.hcl.backup

[root@vault3 ~]# cat /etc/vault.d/vault.hcl

Обра­ти­те вни­ма­ние как меня­ют­ся поля с адре­са­ми, сер­ти­фи­ка­та­ми, а так­же node_id.

api_addr – адрес и порт, на кото­ром будет досту­пен API сервер;
cluster_addr – адрес и порт по кото­ро­му будут вза­и­мо­дей­ство­вать кла­стер­ные сервисы;
disable_mlock – реко­мен­ду­е­мый пара­метр при исполь­зо­ва­нии Integrated Storage;
ui – вклю­че­ние досту­па к веб-интер­фей­су Vault;
в сек­ции listener ука­зы­ва­ют­ся сер­ти­фи­ка­ты, кото­рые будут исполь­зо­ва­ны при сете­вом вза­и­мо­дей­ствии. У каж­дой ноды они свои, за исклю­че­ни­ем CA, дан­ный сер­ти­фи­кат оди­на­ко­вый для всех.

Сек­цию storage сто­ит так же рассмотреть:
path = “/opt/vault/data” – дирек­то­рия, где будут хра­нить­ся дан­ные Vault;
node_id = “vault-a.vmik.lab” – id, с кото­рым нода будет участ­во­вать в кла­сте­ре. У каж­дой ноды он дол­жен отличаться;
Далее идут несколь­ко сек­ций retry_join, с пере­чис­ле­ни­ем всех узлов кла­сте­ра. Посколь­ку допод­лин­но неиз­вест­но, какой из узлов будет актив­ным при запус­ке служб Vault, будет про­из­ве­де­на попыт­ка под­клю­че­ния к каж­до­му из узлов.
Здесь же ука­зы­ва­ют­ся адре­са узлов – leader_api_addrleader_tls_servername – хост­нейм сер­ве­ра, кото­рый дол­жен сов­па­дать с тем, что про­пи­са­но в сер­ти­фи­ка­те дан­но­го сер­ве­ра. Так же ука­зы­ва­ют­ся сер­ти­фи­ка­ты, кото­ры­ми кли­ент будет под­клю­чать­ся к лиде­ру (у каж­дой из нод свои сер­ти­фи­ка­ты, кото­рые мы созда­ва­ли ранее).

Теперь, когда кон­фи­гу­ра­ци­он­ные фай­лы гото­вы, воз­вра­ща­ем­ся на пер­вый узел. Добав­ля­ем Vault в авто­за­груз­ку и авто­ма­ти­че­ски его запускаем:

Про­ве­рим ста­тус Vault, пред­ва­ри­тель­но отме­нив про­вер­ку сер­ти­фи­ка­тов, выста­вив зна­че­ние спе­ци­аль­ной переменной:

Как мож­но заме­тить на теку­щий момент Vault не ини­ци­а­ли­зи­ро­ван (Initialized false), а так­же запе­ча­тан (Sealed true).

При­ме­ча­ние: доба­вив наш CA файл, сге­не­ри­ро­ван­ный ранее, в спи­сок дове­рен­ных сер­ти­фи­ка­тов, при­бе­гать к отмене про­вер­ки сер­ти­фи­ка­тов будет необязательно.

Ини­ци­а­ли­зи­ру­ем Vault:

vault operator init

Vault выдаст 5 клю­чей, кото­рые необ­хо­ди­мо исполь­зо­вать при «рас­пе­чат­ке». Как ска­за­но выше, после каж­дой оста­нов­ки либо пере­за­пус­ка, Vault будет вновь нахо­дить­ся в запе­ча­тан­ном состо­я­нии и для откры­тия нуж­но будет исполь­зо­вать любые три из пяти предо­став­лен­ных клю­чей. Терять эти клю­чи не стоит!
Так же нам предо­став­ля­ет­ся Root Token для досту­па к Vault с мак­си­маль­ны­ми правами.

Рас­пе­ча­та­ем Vault. Опе­ра­цию vault operator unseal нуж­но будет про­ве­сти 3 раза. Каж­дый раз с раз­ным ключом:

На дан­ном эта­пе мы настро­и­ли одну ноду Vault, а так­же ини­ци­а­ли­зи­ро­ва­ли и рас­пе­ча­та­ли ее. Теперь под­клю­чим в кла­стер две дру­гих ноды.
Ранее мы уже под­го­то­ви­ли и раз­ме­сти­ли кон­фи­гу­ра­ци­он­ные фай­лы на нодах B и C.
Под­клю­ча­ем­ся к ноде B, запус­ка­ем Vault:

systemctl enable --now vault
systemctl status vault

Теперь, в отли­чии от пер­вой ноды, ини­ци­а­ли­зи­ро­вать Vault боль­ше не нуж­но, но новая нода все еще в запе­ча­тан­ном состо­я­нии. Рас­пе­ча­та­ем ноду B:

После рас­пе­чат­ки нода будет под­клю­че­на к кла­сте­ру. Мож­но обра­тить вни­ма­ние, что новая нода нахо­дит­ся в режи­ме standby, так же мож­но опре­де­лить теку­щий адрес актив­ной ноды. Это нода A.

Под­клю­чим­ся к ноде C и выпол­ним ана­ло­гич­ные действия:

 

Теперь мы успеш­но сфор­ми­ро­ва­ли кла­стер из трех нод. Вер­нем­ся на первую и про­ве­рим состо­я­ние кластера.

Для нача­ла авто­ри­зу­ем­ся с токе­ном, кото­рый был полу­чен ранее:

И про­ве­рим ста­тус хранилища:

По ста­ту­су вид­но 3 сер­ве­ра, один из кото­рых в ста­ту­се лиде­ра, а два дру­гих – ведомые.

Попро­бу­ем доба­вить новый сек­рет в хра­ни­ли­ще. Для это­го исполь­зу­ем меха­низм kv (key-value):

И поме­стим сек­рет под име­нем db:

Посмот­рим спи­сок всех сек­ре­тов в нашем KV хра­ни­ли­ще test-secrets:

А так­же зна­че­ние сек­ре­та db:

Про­ве­рим рабо­то­спо­соб­ность меха­низ­ма HA. Отклю­чим ноду A:

[root@vault1 tls]# poweroff

Под­клю­чим­ся к ноде B и про­ве­рим статус:

HA Mode изме­не­но со standby на active. Запро­сим спи­сок узлов raft:

но сна­ча­ла пере­да­дим в пере­мен­ные окру­же­ния наш токен руто­вый, мы его полу­чи­ли когда ини­ци­и­ро­ва­ли кластер:

Лидер так же был пере­не­сен на ноду B. В завер­ше­нии запро­сим ранее создан­ный секрет:

Vault про­дол­жа­ет функ­ци­о­ни­ро­вать при поте­ре одной актив­ной ноды. Отклю­чим ноду B. Теперь из трех узлов досту­пен толь­ко один. Про­ве­рим работоспособность:

[root@vault2 ~]# poweroff

Ста­тус Vault с ноды C:

Актив­ная нода не изме­ни­лась. Нода C все так же в режи­ме standby. Ана­ло­гич­но, не удаст­ся запро­сить и сек­рет, посколь­ку запрос пере­на­прав­ля­ет­ся на ранее актив­ную ноду (B):

Запу­стим обрат­но ноду A. После запус­ка, как и ожи­да­ет­ся, нода A нахо­дит­ся в ста­ту­се sealed:

Рас­пе­ча­та­ем:

про­ве­рим:

Рабо­та кла­сте­ра вос­ста­нов­ле­на. Нода С теперь актив­ная. Доступ к сек­ре­там так же восстановлен:

Запу­стим обрат­но выклю­чен­ную ноду B и рас­пе­ча­та­ем. На этом рабо­та по настрой­ке кла­сте­ра Vault закончена.

Нерас­смот­рен­ным остал­ся один вопрос – как под­клю­чать­ся внеш­ним кли­ен­там? Под­клю­че­ние к любой из standby нод пере­на­пра­вит запрос на active ноду, поэто­му знать теку­щий адрес актив­ной ноды не обязательно.
Одна­ко, кли­ент может не знать все адре­са Vault и в слу­чае отклю­че­ния извест­ной ноды, доступ кли­ен­та к Vault может прекратиться.

Наи­бо­лее при­ем­ле­мые на мой взгляд решения:
1. Внеш­ний балан­си­ров­щик нагруз­ки меж­ду узла­ми Vault с зара­нее извест­ным и посто­ян­ным адре­сом. HAProxy, либо nginx;
2. Общий IP-адрес меж­ду узла­ми кла­сте­ра Vault, напри­мер, на осно­ве keepalived.

 

Доба­вим сер­ти­фи­ка­ты в дове­рен­ные, что­бы каж­дый раз не заки­ды­вать в пере­мен­ные окружения 

export VAULT_SKIP_VERIFY="true"

для это­го на каж­дой из нод выполним:

 

Подключимся к кластеру:

https://vault.test.local:8200/

аутен­ти­фи­ци­ру­ем­ся с помо­щью root token

Initial Root Token: hvs.yInppPkxqfAcVcODMVlvLjN3

видим создан­ный нами ранее секрет

теперь созда­дим метод аутен­ти­фи­ка­ции по user/password

созда­дим теперь пользователя

зай­дём под этим поль­зо­ва­те­лем и про­ве­рим что нам доступно:

как видим недо­ста­точ­но доступов.

 

теперь создадим admin policy пример возьмём отсюда:

https://learn.hashicorp.com/tutorials/vault/policies

 

policy созда­ли, теперь нуж­но создать Entities (сущ­но­сти)

логи­ним­ся под нашим поль­зо­ва­те­лем и про­ве­рям какие теперь есть доступы:

как видим теперь мы видим все наши сек­ре­ты воз­мож­ность созда­вать новые policy тоже появи­лась, попро­бу­ем создать новый секрет:

как видим сек­рет создался.

====================================================

Создание группы с админскими правами

созда­ём сущ­ность Entities и alias для неё. alias дол­жен сов­па­дать с име­нем наше­го пользователя

"entity" - это абстракт­ное пред­став­ле­ние чело­ве­ка или сер­ви­са, кото­рый вза­и­мо­дей­ству­ет с сер­ве­ром Vault. Entity может быть свя­зан с одним или несколь­ки­ми мето­да­ми аутен­ти­фи­ка­ции, таки­ми как userpass, ldap или github, и к нему мож­но при­кре­пить поли­ти­ки для управ­ле­ния досту­пом к ресур­сам в Vault.

При исполь­зо­ва­нии мето­да аутен­ти­фи­ка­ции userpass в Vault для каж­до­го поль­зо­ва­те­ля, заре­ги­стри­ро­ван­но­го с этим мето­дом, созда­ет­ся entity. Entity хра­нит инфор­ма­цию о поль­зо­ва­те­ле, такую как имя поль­зо­ва­те­ля, пароль и любые поли­ти­ки, свя­зан­ные с ним. При вхо­де поль­зо­ва­те­ля с помо­щью userpass Vault исполь­зу­ет инфор­ма­цию, хра­ня­щу­ю­ся в entity, что­бы аутен­ти­фи­ци­ро­вать поль­зо­ва­те­ля и опре­де­лить, к каким ресур­сам у него есть доступ.

 

отме­тим что в дан­ном слу­чае мы НЕ ПРИВЯЗЫВАЕМ policy

теперь созда­ём alias

теперь созда­ём группу(в теку­щем при­ме­ре internal):

и уже тут цеп­ля­ем нашу policy

про­ве­ря­ем нашу группу:

id в members группы:

это id Entities

захо­дим под нашим поль­зо­ва­те­лем mid и про­ве­ря­ем что всё ок и досту­пов на добав­ле­ние сек­ре­тов хватает:

создадим ещё пользователя и добавим в ту же группу:

теперь доба­вим его в нашу груп­пу, для это­го созда­ём Entities

добав­ля­ем теперь в группу:

отме­чу что все эти дей­ствия я выпол­нял уже под поль­зо­ва­те­лем MID а не root

всё, мож­но теперь логи­нить­ся под этим пользователем(mid2).

 

Повторим те же действия, но с помощью команд:

  1. Созда­дим userpass - доступ по логи­ну и паролю:

  2. Созда­ём policy с досту­па admin

  3. Созда­ём поль­зо­ва­те­ля mid с авто­ри­за­ци­ей по логи­ну и паролю:

  4. созда­ём entity для поль­зо­ва­те­ля mid

    результат:

    если забы­ли id его мож­но посмот­реть вот так:

    результат:

    ещё нам нуж­на будет пере­мен­ная mount_accessor
    что­бы уви­деть mount_accessor выпол­ним команду:

    всё, мы полу­чи­ли зна­че­ние для mount_accessor и canonical_id теперь мож­но выпол­нять коман­ду на созда­ние alias для entity:

    результат:

    если забы­ли id то его мож­но посмот­реть вот так(тут будут все ключи):

    полу­чить инфор­ма­цию по нему мож­но так:

     
  5. Созда­дим теперь group к кото­рой будет при­со­еди­не­на policy и Member Entity IDs, коман­да выгля­дит вот так:

    вот результат:

     
  6. Доба­вим ново­го поль­зо­ва­те­ля в эту же груп­пу admins:

    обра­ти­те вни­ма­ние что при добав­ле­нии к груп­пе id entity ново­го поль­зо­ва­те­ля нуж­но пере­чис­лять их все.

    что­бы гля­нуть какие уже id есть в груп­пе admins можем исполь­зо­вать команду:

    vault read identity/group/name/admins | grep member_entity_ids

Аутентификация через gitlab

офф инструк­ция:

https://docs.gitlab.com/ee/integration/vault.html

идём в наш гитлаб:

добав­ля­ем:
http://localhost:8250/oidc/callback
http://127.0.0.1:8200/ui/vault/auth/oidc/oidc/callback

Application ID a4b9c2ce0b1a62d4e448450bdb4e458a123a6806549bb660e8179bf70ac13259

Secret 69fa2b783fc889b77cdfdfe20de999585d68183bcdd8341692b421e0dbacc598

пере­хо­дим в кон­соль, логи­ним­ся в vault

[root@vault3 ~]# vault login
Token (will be hidden):

токен копи­ру­ем отсюда:

vault auth enable oidc

теперь нуж­но пере­дать application ID и secret сге­не­ри­ро­ван­ный в GitLab

при­мер:

а вот то что я вставляю:

теперь надо запи­сать роль

а вот что я буду вставлять:

резуль­тат такой:

всё мож­но захо­дить через гитлаб

6. Auto unseal hashicorp vault

идея в сле­ду­ю­щем, у нас есть 2 кла­сте­ра hashicorp vault кото­рые будут делать auto unseal друг дру­га. один кла­стер у нас на отдель­ных тач­ках а вто­рой будет внут­ри k8s. Для про­сто­ты при­ме­ра поста­вим minikub

6.1 установка minikub

отклю­ча­ем selinux

[root@minikub ~]# cat /etc/selinux/config | grep -v ^#
SELINUX=disabled

ребу­та­ем сервер.

ста­вим докер:

vi /etc/yum.repos.d/docker.repo

yum -y install docker-ce

systemctl start docker

systemctl enable docker

ста­вим Conntrack - он явля­ет­ся частью плат­фор­мы Netlifier. тре­бу­ет­ся для рабо­ты слож­ной сети Kubernetes, посколь­ку узлы долж­ны отсле­жи­вать соеди­не­ния меж­ду тыся­ча­ми моду­лей и сервисов.

yum -y install conntrack

chmod +x kubectl

mv kubectl /usr/local/bin/

chmod +x minikube-linux-amd64

mv minikube-linux-amd64 /usr/local/bin/minikube

minikube start

если при запус­ке мы полу­ча­ем сле­ду­ю­щую ошибку:

мож­но запу­стить с фла­гом --force - если рабо­та­е­те из под root
minikube start --force

если хоти­те рабо­тать из под поль­зо­ва­те­ля то нуж­но доба­вить прав:

[root@minikub ~]# adduser mid
[root@minikub ~]# usermod -aG docker mid
[root@minikub ~]# su - mid
[mid@minikub ~]$ minikube start

вклю­ча­ем ingress для minikube

[root@minikub ~]# minikube addons enable ingress

и вклю­чим авто­до­пол­не­ние для kubectl

[root@minikub ~]# yum install bash-completion -y

[root@minikub ~]# echo 'source <(kubectl completion bash)' >>~/.bashrc

 

6.2 подготовка хранилища для PV (nfs)

в каче­стве хра­ни­ли­ща pv будем исполь­зо­вать nfs сервер.

192.168.1.176

настра­и­ва­ем его:

yum install nfs-utils -y

systemctl enable rpcbind
systemctl enable nfs-server
systemctl enable nfs-lock
systemctl enable nfs-idmap
systemctl start rpcbind
systemctl start nfs-server
systemctl start nfs-lock
systemctl start nfs-idmap

созда­дим раз­дел (мож­но и не созда­вать а выбрать удоб­ную для вас дирек­то­рию, я захо­тел сде­лать отдель­ный раздел)

lvcreate -L 5G -n nfs centos
mkfs.ext4 -L nfs /dev/centos/nfs
mkdir /nfs
mount /dev/centos/nfs /nfs/
vi /etc/fstab

добав­ля­ем пра­ва на запись:

[root@nfs ~]# chmod 777 /nfs

на кли­ент (minikub) тоже ста­вим nfs-client

yum install nfs-utils -y

systemctl enable rpcbind
systemctl enable nfs-server
systemctl enable nfs-lock
systemctl enable nfs-idmap
systemctl start rpcbind
systemctl start nfs-server
systemctl start nfs-lock
systemctl start nfs-idmap

теперь настра­и­ва­ем про­ви­жи­нер (provisioner)

cat rbac.yaml

cat nfs_class.yaml

cat nfs_provision.yaml

при­ме­ня­ем:

kubectl apply -f rbac.yaml
kubectl apply -f nfs_class.yaml
kubectl apply -f nfs_provision.yaml

теперь можем про­ве­рить созда­ёт­ся ли PV

cat test-claim.yaml

kubectl apply -f test-claim.yaml

про­ве­ря­ем:

как видим всё ок.
про­ве­ря­ем на nfs шаре:

всё ок.

 

6.3 установка vault в minikub

ста­вить будем в namespace vault

[root@minikub ~]# kubectl create ns vault

будем исполь­зо­вать уже гото­вые helm чар­ты для vault

для нача­ла уста­но­вим helm:

https://github.com/helm/helm/releases/tag/v3.10.3

[root@minikub ~]# wget https://get.helm.sh/helm-v3.10.3-linux-amd64.tar.gz

[root@minikub ~]# tar -zxvf helm-v3.10.3-linux-amd64.tar.gz

[root@minikub ~]# mv linux-amd64/helm /usr/local/bin/helm

Возь­мём офф чарт:

https://github.com/hashicorp/vault-helm

[root@minikub ~]# git clone https://github.com/hashicorp/vault-helm.git

попра­вим values вклю­чим raft (мож­но оста­вить по умол­ча­нию consul мож­но вооб­ще в базу дан­ных postgres всё отправить)

[root@minikub ~]# vim vault-helm/values-my.yaml

что­бы запу­стить на minikub нуж­но выклю­чить affinity

 

а вот такой вид будет при обыч­ном запус­ке в кластере:

как видим раз­ни­ца толь­ко в
affinity: {}

ста­вим сам vault:
[root@minikub ~]# helm upgrade --install vault -n vault ./vault-helm/ -f ./vault-helm/values-my.yaml

теперь нам нуж­но поста­вить Secrets store CSI driver

он потре­бу­ет­ся для под­клю­че­ния сикре­тов из vault в init контейнеры.

теперь нуж­но ини­ци­а­ли­зи­ро­вать vault

Полу­чи­ли ключ для unseal.

далее нам пона­до­бит­ся ути­ли­та jq поста­вим её:

yum install epel-release -y
yum install jq -y

cat cluster-keys.json | jq -r ".unseal_keys_b64[]"

далее рас­пе­ча­ты­ва­ем наше хра­ни­ли­ще командой:

kubectl -n vault exec vault-0 -- vault operator unseal

клю­чи выше.
Если лень вво­дить рука­ми то мож­но исполь­зо­вать цикл:

резуль­тат будет такой:

далее нуж­но собрать raft в кластер:

и рас­пе­ча­ты­ва­ем vault-1 vault-2

 

6.4 auto unseal vault с помощью другого vault

и так мы выпол­ни­ли все пред­ва­ри­тель­ные шаги:
сей­час у нас на 3х отдель­ных тач­ках рас­по­ло­жен vault и в minikub рас­по­ло­жен дру­гой vault, теперь настро­ем их auto unseal.

будет исполь­зо­вать метод Transit Auto Unseal

[root@vault1 ~]# vault login

тут я вби­вал рут токен полу­чен­ный при ини­ци­а­ли­за­ции хранилища

[root@vault1 ~]# vault secrets enable transit
Success! Enabled the transit secrets engine at: transit/

После вклю­че­ния тран­зи­та я запи­шу ключ по это­му пути:

[root@vault1 ~]# vault write -f transit/keys/vault-unseal-key
Success! Data written to: transit/keys/vault-unseal-key

[root@vault1 ~]# vault list transit/keys

Теперь я создам policy и токен с при­креп­лен­ной к нему  поли­ти­кой. Я буду исполь­зо­вать этот токен в кон­фи­гу­ра­ции вто­ро­го сер­ве­ра для Auto Unseal.

[root@vault1 ~]# cat transit-policy.yaml

[root@vault1 ~]# vault policy write unseal-policy transit-policy.yaml
Success! Uploaded policy: unseal-policy

[root@vault1 ~]# vault token create -policy=unseal-policy

Теперь на вто­ром Vault(в minikube) я добав­лю раз­дел с кон­фи­гу­ра­ци­ей для авто­ма­ти­че­ско­го вскры­тия Transit.

Для это­го пра­вим кон­фиг (values) vault-helm/values-my.yaml  и добав­ля­ем вот такой код:

весь values будет вот в таком виде:

cat vault-helm/values-my.yaml

при­ме­ня­ем новую конфигурацию:

[root@minikub ~]# helm upgrade --install vault -n vault ./vault-helm/ -f ./vault-helm/values-my.yaml

теперь нуж­но грох­нуть ста­рые поды и рас­пе­ча­тать vault с фла­гом -migrate

сле­ду­ю­щий:

и послед­ний:

про­ве­ря­ем:

как видим кон­тей­нер с vault под­ни­ма­ет­ся и ста­но­вит­ся ready пото­му что про­шёл auto unseal  посмот­рим его логи:

 

Это мы настроили auto unseal для vault в kubernetes.Теперь настроим auto unseal для нашего основного Vault который на виртуалках.

 

что­бы был доступ из вне вклю­ча­ем ingress

 

(ЭТОТ КЕЙС ТОЛЬКО В СЛУЧАЕ С MINIKUBE, необ­хо­ди­мо про­ки­нуть нару­жу айпиш­ник по кото­ро­му будем ходить в кла­стер) и из-за того что запус­кал в minikube и его айпишник:

[root@minikube ~]# minikube ip
192.168.49.2

надо про­ки­нуть порт на хосто­вую ноду:

для это­го поста­вим haproxy:

yum install haproxy -y

и доба­вим в его кон­фиг проксирование:

[root@minikube ~]# cat /etc/haproxy/haproxy.cfg

systemctl enable haproxy
systemctl start haproxy

Теперь на наших Vault я добав­лю раз­дел с кон­фи­гу­ра­ци­ей для авто­ма­ти­че­ско­го вскры­тия Transit.

не забы­ва­ем доба­вить в hosts адрес наше­го minikube:

(vault1/vault2/vault3)

 

Теперь при­сту­па­ем к настрой­ке auto unseal в k8s

выпол­ня­ем те же действия:

[root@minikub ~]# kubectl -n vault exec -ti vault-0 sh

vault login

vault secrets enable transit

vault write -f transit/keys/vault-unseal-key

/ $ cd /tmp/
/tmp $ cat > transit-policy.yaml

/tmp $ vault policy write unseal-policy transit-policy.yaml

/tmp $ vault token create -policy=unseal-policy

полу­чи­ли токен теперь идём в кон­фи­гу­ра­цИИ наших vault на вир­ту­ал­ках и добав­ля­ем сле­ду­ю­щую конфигурацию:

ниже при­ве­дён пол­ный конфиг:

теперь рестар­ту­ем vault на всех тачках:

[root@vault1 ~]# systemctl restart vault
[root@vault2 ~]# systemctl restart vault
[root@vault3 ~]# systemctl restart vault

про­ве­ря­ем что хра­ни­ли­ще дей­стви­тель­но запечатано:

теперь нуж­но рас­пе­ча­тать наше хра­ни­ли­ще с пара­мет­ром '-migrate'

[root@vault1 ~]# vault operator unseal -migrate
[root@vault1 ~]# vault operator unseal -migrate
[root@vault1 ~]# vault operator unseal -migrate

[root@vault2 ~]# vault operator unseal -migrate
[root@vault2 ~]# vault operator unseal -migrate
[root@vault2 ~]# vault operator unseal -migrate

[root@vault3 ~]# vault operator unseal -migrate
[root@vault3 ~]# vault operator unseal -migrate
[root@vault3 ~]# vault operator unseal -migrate

если лень руч­ка­ми ходить и вби­вать то мож­но исполь­зо­вать цикл:

for i in `cat unseal`; do vault operator unseal -migrate $i; done

всё можем про­ве­рять что наш кла­стер авто­ма­ти­че­ски распечатывается:

на осталь­ных тач­ках так же:

 

7.Бэкап данных(backup raft)

Бла­го­да­ря тому, что Raft пол­но­стью дуб­ли­ру­ет все дан­ные на каж­дый из узлов, выпол­нять снап­шот мож­но на любом сер­ве­ре, где запу­щен Vault.

Для созда­ния сним­ка необходимо:

Зай­ти на сервер/pod, где запу­щен Vault, и выпол­нить команду:

файлbackup.snapshot мож­но заар­хи­ви­ро­вать и пере­не­сти в место для хра­не­ния бэкапов

Для вос­ста­нов­ле­ния коман­ду на сер­ве­ре с Vault надо заме­нить на:

если что вот офи­ци­аль­ная дока

про­ве­рим:

на вир­ту­ал­ке:

в POD:

как видим всё ок.

8. Настройка LDAP — freeipa (лично не тестил)

Раз­дел Access-Auth methods  выби­ра­ем создать ldap

пер­вый раз про­сто нажи­ма­ем создать пара­мет­ры все по дефол­ту,  потом вобьем правильные

  • зада­ем UR: в при­ме­ре ниже это  ldapS и на 636 пор­ту, что­бы это кор­рект­но рабо­та­ла сра­зу, сер­вер дол­жен быть под­клю­чен freeipa-clinet  к сер­ве­ру фриип­ты, либо настра­вай­те ldap обыч­ный по 389 или со с startTLS
  • в раз­де­ле LDAP options:  рас­кры­ва­ем и меня­ем User atrribut на uid
  • Сле­ду­ю­щий раз­дел customize user search — тут мы как раз и настра­и­ва­ем адрес УЗ кем бин­дим­ся, а так где искать поль­зо­ва­те­лей, для фрии­па это будут такие параметры 
    • uid=our-system-user,cn=sysaccounts,cn=etc,dc=example,dc=com
    • cn=users,cn=accounts,dc=example,dc=com

Так же настро­им поиск по группам

Типовое использование

Все шаги ниже, под­ра­зу­ме­ва­ют, что вы под­клю­чи­лись к  vault исполь­зуя кли­ент vault, как под­клю­чить­ся ниже

Ска­чать кли­ент мож­но тут https://developer.hashicorp.com/vault/downloads

Подключение

Ука­жем адрес под­клю­че­ния наше­го vault и убе­дим­ся, что кор­рект­но подключились

Авторизация в VAULT — token

Авторизация в  VAULT — парольная

Авторизация в  VAULT — LDAP

https://www.vaultproject.io/docs/auth/ldap.html


ВАЖНО
: если мы хотим назна­чить сра­зу несколь­ко поли­тик, надо их все пере­чис­лить через запя­тую, ина­че  my-policy пере­за­трет все осталь­ные политики

мно­го политик

Подключение политики к LDAP группе

Узнать какие политики назначены на пользователя

напри­мер  поль­зо­ва­те­лю vasy, кото­рый вхо­дит по логи­ну и паролю

Узнать какие политики назначены на LDAP группу

 Узнать какие политики назначены на пользователя при входе

Вид­но в выво­де при входе

 

9. Добавляем секреты из vault в POD (vault установлен в k8s) можно подкидывать определённые key

это я поды­мал не в мини­ку­бе а в кла­сте­ре быст­рой прой­дём­ся по установке:

чарт берём оффициальный
https://github.com/hashicorp/vault-helm.git
я под­го­то­вил my-values.yaml

cat my-values.yaml

теперь ста­вим vault

если лень 3 раза запус­кать рас­пе­ча­ты­ва­ние то мож­но использовать:

 

 

9.1 secrets-store-csi-driver

 

ста­вим  secrets-store-csi-driver
Secrets Store CSI (Container Storage Interface) Driver - это драй­вер для Kubernetes, кото­рый поз­во­ля­ет мон­ти­ро­вать кон­фи­ден­ци­аль­ные дан­ные из внеш­не­го хра­ни­ли­ща, в виде томов CSI.

логи­ним­ся в vault

kubectl exec -it vault-0 -n vault -- /bin/sh
vault login s.O9SD65yMtAZDpLu2uh0Otkyv

пароль берём из фай­ла cluster-keys.json

созда­ём сек­рет кото­рый будем подкидывать:

вклю­ча­ем аутен­ти­фи­ка­цию в k8s

созда­ём policy

созда­ём роль

Роль свя­зы­ва­ет учет­ную запись служ­бы Kubernetes, webapp-saв про­стран­стве имен default,с поли­ти­кой Vault, internal-app. Токе­ны, воз­вра­щен­ные после аутен­ти­фи­ка­ции, дей­стви­тель­ны в тече­ние 10 минут

 

всё выхо­дим из кон­тей­не­ра vault

 

созда­ём SecretProviderClass

Этот ресурс опи­сы­ва­ет пара­мет­ры, кото­рые предо­став­ля­ют­ся Vault CSI. Для его настрой­ки тре­бу­ет­ся адрес сер­ве­ра Vault, имя роли аутен­ти­фи­ка­ции Vault Kubernetes и секреты.

  • objectName— это сим­во­ли­че­ское имя для это­го сек­ре­та и имя фай­ла для записи.
  • secretPath— это путь к сек­ре­ту, опре­де­лен­но­му в Vault.
  • secretKeyявля­ет­ся клю­чом этом секрете.

при­ме­ня­ем

kubectl apply --filename spc-vault-database.yaml

созда­ём serviceaccaunt

kubectl create serviceaccount webapp-sa

теперь подкидываем секрет как файл

при­ме­ня­ем

kubectl apply --filename webapp-pod.yaml

про­ве­ря­ем:

теперь подкидываем секрет как файл и переменную окружения

kubectl apply --filename spc-vault-database.yaml

и теперь сам POD

уда­ля­ем ста­рый запус­ка­ем новый:

kubectl delete pod webapp && kubectl apply --filename webapp-pod.yaml

про­ве­ря­ем:

если нуж­но под­ки­нуть несколь­ко key к сек­рет  то можем вос­поль­зо­вать­ся вот этим примером:

https://github.com/kubernetes-sigs/secrets-store-csi-driver/blob/release-1.3/test/bats/tests/vault/vault_v1_multiple_secretproviderclass.yaml

в чём неудобство, вам каждый раз нужно ходить и править руками SecretProviderClass когда нужно добавить новую переменную

есть issue
https://github.com/kubernetes-sigs/secrets-store-csi-driver/issues/529
висит давно.

 

9.2 Vault Secrets Operator

вот оффи­ци­аль­ная репка:

https://github.com/hashicorp/vault-secrets-operator

ста­вим

helm repo add hashicorp https://helm.releases.hashicorp.com

добав­ля­ем адресс наше­го vault в values чтоб установить
cat vault-secrets-operator.yaml

напо­ми­наю что vault у меня уста­нов­лен в namespace vault

ста­вим:
helm upgrade --install --namespace vault vault-secrets-operator hashicorp/vault-secrets-operator --version 0.1.0-beta -f vault-secrets-operator.yaml

дан­ная вер­сия --version 0.1.0-beta это вер­сия чар­та https://github.com/hashicorp/vault-secrets-operator/blob/main/chart/Chart.yaml

для про­вер­ки рабо­ты созда­дим отдель­ный неймспейс:

kubectl create ns test

логи­ним­ся в vault

kubectl exec -it vault-0 -n vault -- /bin/sh
vault login s.PAx0C3X0nx9vVBMwgtM9nLH6

пароль берём из фай­ла cluster-keys.json

созда­ём сек­рет кото­рый будем подкидывать:

добав­ля­ем туда ключ значение:

про­ве­ря­ем:

 

вклю­ча­ем аутен­ти­фи­ка­цию в k8s (если один раз вклю­чи­ли после­ду­ю­щие разы ещё раз вклю­чать аутен­ти­фи­ка­цию НЕ нужно)

vault auth enable kubernetes

 

 

созда­ём policy  "test-policy" на чте­ние ТОЛЬКО наше­го секрета

 

 

созда­ём роль "test-role"

Роль свя­зы­ва­ет учет­ную запись служ­бы Kubernetes(serviceaccaunt), кото­рую назо­вём test-serviceaccaunt (но луч­ше исполь­зо­вать уже суще­ству­ю­щий сер­вис акка­унт наше­го при­ло­же­ния ) в про­стран­стве имен test с поли­ти­кой Vault, test-policy Токе­ны, воз­вра­щен­ные после аутен­ти­фи­ка­ции, дей­стви­тель­ны в тече­ние 10 минут

 

созда­ём serviceaccaunt

kubectl create serviceaccount test-serviceaccaunt -n test

созда­ём объ­ект vaultauth

cat vault-auth.yaml

тут зада­ём имя это­го ресур­са  name: vaultauth-app1
нейм­с­пейс в кото­ром от будет создан namespace: test
роль кото­рую мы ранее созда­ли в vault ука­зав там наш нейм­с­пейс и сер­вис акка­унт role: test-role
и так же наш сер­вис акка­унт serviceAccount: test-serviceaccaunt

kubectl apply -f vault-auth.yaml -n test

про­ве­ря­ем:

если в выво­де describe

kubectl describe vaultauths.secrets.hashicorp.com -n test vaultauth-app1

в эвен­тах видим
Successfully handled VaultAuth resource request
зна­чит всё ок

теперь созда­ём объ­ект VaultStaticSecret кото­рый будет созда­вать нам k8s секрет

cat vault-secret.yaml

в дан­ном ресур­се мы зада­ём его имя name: vault-secret-app1
нейм­с­пейс в кото­ром он будет создан namespace: test
в спе­ке зада­ём имя ресур­са vaultauth vaultAuthRef: vaultauth-app1 кото­рый мы созда­ли ранее
имя сек­ре­та mount: test/secret и путь до него name: namespace-test/first-app  напом­ню что сек­рет мы созда­ва­ли командой
vault secrets enable -path=test/secret/ kv  поэто­му mount мы зада­ём test/secret а инфор­ма­цию в сек­рет мы ложи­ли коман­дой vault kv put test/secret/namespace-test/first-app password="db-secret-password"  поэто­му name мы зада­ём по адре­су namespace-test/first-app
вре­мя обнов­ле­ния дан­ных мы зада­ём пере­мен­ной refreshAfter
в destination мы зада­ём нуж­но ли созда­вать сек­рет create: true 
и его имя name: test-secret-k8s 
тип ука­зы­вать не обя­за­тель­но но я ука­зал для нагляд­но­сти  type: Opaque

kubectl apply -f vault-secret.yaml -n test

про­ве­ря­ем:

если в describe видим в event сле­ду­ю­щее сообщение:

Secret synced  или Secret sync not required  то всё ок

ну и про­ве­ря­ем наш секрет:

посмот­рим что внут­ри секрета:

kubectl get secret -n test test-secret-k8s -o yaml

есть 2 записи:
password и _raw  посмот­рим что в них:

и вто­рая запись

доба­вим ещё одно зна­че­ние к это­му секрету:

дёр­нем сек­рет ещё раз и гля­нем что там:

как видим появил­ся допол­ни­тель­ный key:  new-key-for-test со значением:

как видим теперь у нас созда­ют­ся сек­ре­ты и их мож­но дина­ми­че­ски менять, т.е. добавляем/меняем/удаляем зна­че­ние и сек­рет в k8s обновляется

 

9.2.1 Пример с подкидыванием секрета в deployment

Про­ве­рим на тесто­вом деп­лое, созда­дим чарт:
helm create test-chart

вклю­ча­ем ingress для наше­го metallb

vim test-chart/values.yaml

он будет под­тя­ги­вать­ся через  className: "nginx"

так же добав­ля­ем в deployment envfrom

общий вид будет такой:

cat test-chart/templates/deployment.yaml

ста­вим:

helm install test-work -n test --values test-chart/values.yaml ./test-chart/

про­ве­ря­ем:

как видим внут­ри наше­го кон­тей­не­ра наш сек­рет с 2мя пере­мен­ны­ми new-key-for-test password и допол­ни­тель­но _raw

добав­ля­ем ещё одну пере­мен­ную test про­ве­ря­ем что сек­рет обновился:

как видим всё ок.
но внут­ри кон­тей­не­ра этой пере­мен­ной нет:

мож­но поста­вить reloader НО мож­но про­сто настро­ить vault operator а имен­но rolloutRestartTargets

9.2.2 Включение Vault Secrets Operator reloader

 

смот­рим его описание:

kubectl explain VaultStaticSecret.spec.rolloutRestartTargets

как видим на момент 23,03,2023 под­дер­жи­ва­ют­ся деп­лой­мент демон­сет и стейтфулсет

что­бы это исполь­зо­вать доба­вим в VaultStaticSecret допол­ни­тель­ное поле rolloutRestartTargets

но пред­ва­ри­тель­но гля­нем как назы­ва­ет­ся наш деплоймент:

cat vault-secret.yaml

при­ме­ня­ем:

kubectl apply -f vault-secret.yaml -n test

про­ве­ря­ем:

как видим наша новая пере­мен­ная так и не появи­лась, это пото­му что после аплая VaultStaticSecret мы не меня­ли сек­рет в vault

идём в vault и добав­ля­ем новую переменную

в этот же момент смот­рим что про­ис­хо­дит в нашем неймспейсе:

как видим ста­рый кон­тей­нер успеш­но уда­лён а новый стар­та­нул, про­ве­рим его env

как видим всё работает.

 

10.SSH аутентификация через vault

Если поль­зо­ва­тель хочет под­клю­чить­ся по SSH к уда­лен­но­му ком­пью­те­ру, ему необ­хо­ди­мо аутен­ти­фи­ци­ро­вать хранилище.

далее он дела­ет запрос к vault полу­ча­ет ключ и с ним уже может под­клю­чить­ся к нуж­но­му сер­ве­ру: Общая схе­ма такая:

10.1 SSH аутентификация через vault OTP (временный пароль)

Наша кон­фи­гу­ра­ция
1- Vault server (IP= 192.168.1.191) vault.test.ru
2- Our server (IP= 192.168.1.180) сер­вер на кото­рый мы смо­жем под­клю­чать­ся исполь­зуя вре­мен­ный пароль

логи­ним­ся в vault
kubectl exec -ti -n vault vault-0 sh
vault secrets enable ssh

созда­ём роль otp_key_role

"cidr_list": "0.0.0.0/0"  - ука­зы­ва­ет диа­па­зон IP-адре­сов, из кото­рых раз­ре­шен доступ.
"key_type": "otp" - ука­зы­ва­ет, что SSH-клю­чи долж­ны быть под­пи­са­ны вре­мен­ным паро­лем OTP.
"default_user": "ubuntu" - ука­зы­ва­ет, что при исполь­зо­ва­нии этой роли, поль­зо­ва­те­ли будут вхо­дить в систе­му с име­нем "ubuntu"

пере­хо­дим в дирек­то­рию /tmp так как там раз­ре­ше­на запись

cd /tmp/

созда­ём policy

при­ме­ня­ем policy

vault policy write our-policy ./our-policy.hcl

вклю­ча­ем метод аутен­ти­фи­ка­ции по паролю

vault auth enable userpass

теперь для мето­да userpass поль­зо­ва­те­лю ubuntu  веша­ем нашу поли­ти­ку our-policy 

vault write auth/userpass/users/ubuntu password="somepass" policies="our-policy"

 

пере­хо­дим к сер­ве­ру на кото­рый мы будем заходить:

wget https://releases.hashicorp.com/vault-ssh-helper/0.2.1/vault-ssh-helper_0.2.1_linux_amd64.zip

unzip -q vault-ssh-helper_0.2.1_linux_amd64.zip -d /usr/local/bin

chmod 0755 /usr/local/bin/vault-ssh-helper

chown root:root /usr/local/bin/vault-ssh-helper

mkdir /etc/vault-ssh-helper.d/

теперь настра­и­ва­ем SSHd 

cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig

vim /etc/ssh/sshd_config

systemctl restart sshd

Centos

Ubuntu

вери­фи­ци­ру­ем кон­фи­гу­ра­цию и доба­вим пользователя:

vault-ssh-helper -verify-only -config /etc/vault-ssh-helper.d/config.hcl

добав­ля­ем поль­зо­ва­те­ля  пароль можем задать 123

adduser ubuntu

настрой­ка завер­ше­на, теперь воз­вра­ща­ем­ся волт сервер

kubectl exec -ti -n vault vault-0 sh

vault login -method=userpass username=ubuntu password=somepass

созда­ём токен(временный пароль)

vault write ssh/creds/otp_key_role ip=192.168.1.180

в поле key мы полу­ча­ем пароль, его и исполь­зу­ем для аутентификации

всё можем логиниться

ssh ubuntu@192.168.1.180

в каче­стве паро­ля исполь­зу­ем key  e4f6d3ee-ce0c-d13d-a20d-0e3b9e1a6f55

вот лог сер­ве­ра на кото­рый логинимся:

ВАЖНОЕ!!!!!!!!!! 
дан­ный пароль рабо­та­ет толь­ко на 1 раз, при сле­ду­ю­щей аутен­ти­фи­ка­ции нуж­но будет запра­ши­вать новый токен. при ста­ром токене воз­ни­ка­ет сле­ду­ю­щая ошиб­ка при попыт­ке авторизоваться:

 

что­бы логи­нить­ся в vault с тачек нуж­но ска­чать бинарник:

wget https://releases.hashicorp.com/vault/1.13.0/vault_1.13.0_linux_amd64.zip
unzip -q vault_1.13.0_linux_amd64.zip -d /usr/local/bin/

логи­ним­ся

vault login -address=https://vault.test.ru -tls-skip-verify -method=userpass username=ubuntu password=somepass

запра­ши­ва­ем OTP(временный пароль)

vault write -address=https://vault.test.ru -tls-skip-verify ssh/creds/otp_key_role ip=192.168.1.180

полу­ча­ем пароль:

с кото­рым можем логи­нить­ся на сер­вер 192.168.1.180

10.2 SSH аутентификация через vault SSH (certificate authority)

 

созда­ём сек­рет и пишем в него пуб­лич­ный ключ:

vault secrets enable -path=ssh-user-ca ssh

vault write ssh-user-ca/config/ca generate_signing_key=true

потом если что можем посмот­реть этот ключ сле­ду­ю­щим образом:

vault read -field=public_key ssh-user-ca/config/ca

теперь созда­ём роль для поль­зо­ва­те­ля test

вре­мя жиз­ни это­го сер­ти­фи­ка­та зада­ём в 5 минут

созда­ём policy

при­креп­ля­ем эту policy к наше­му пользователю:
(ВАЖНО!!!!!! необ­хо­ди­мо ука­зы­вать все policy ина­че новая затрёт все старые)

vault write auth/userpass/users/myuser policies="default","my-policy","ssh-user"

теперь смот­рим сер­ти­фи­кат кото­рый надо доба­вить на целе­вую тач­ку к кото­рой будем подключаться:

вот в этот файл:

 /etc/ssh/ssh_ca.pub

меня­ем для него права

chmod 0600 /etc/ssh/ssh_ca.pub

так же пра­вим файл:

/etc/ssh/sshd_config

и в самый конец добавляем:

TrustedUserCAKeys /etc/ssh/ssh_ca.pub

а так же добав­ля­ем пользователя:

useradd -m test -s /bin/bash

рестар­ту­ем sshd

systemctl restart ssh

с ЦЕЛЕВОЙ тачкой(куда будем под­клю­чать­ся закончили)

 

Теперь настро­ем тач­ку с кото­рой будем подключаться:

wget https://releases.hashicorp.com/vault/1.13.0/vault_1.13.0_linux_amd64.zip

unzip -q vault_1.13.0_linux_amd64.zip -d /usr/local/bin/

добав­ля­ем в хосты наш vault

cat /etc/hosts
192.168.1.191 vault.test.ru

логи­ним­ся:

vault login -address=https://vault.test.ru -tls-skip-verify -method=userpass username=myuser password=mypassword

как видим в policy есть наша поли­ти­ка ssh-user

vault write -address=https://vault.test.ru -tls-skip-verify -field=signed_key ssh-user-ca/sign/ssh-test public_key=@$HOME/.ssh/id_rsa.pub valid_principals="test" >test.cert

рас­смот­рим параметры:

-field=signed_key ssh-user-ca/sign/ssh-test    - тут мы под­пи­сы­ва­ем сер­ти­фи­кат и как раз к нему мы в policy доступ и давали.

public_key=@$HOME/.ssh/id_rsa.pub  - тут мы ука­зы­ва­ем путь до наше­го пуб­лич­но­го ключа

valid_principals - исполь­зу­ет­ся для огра­ни­че­ния спис­ка раз­ре­шен­ных поль­зо­ва­те­лей или групп, кото­рые могут исполь­зо­вать SSH сер­ти­фи­кат для аутен­ти­фи­ка­ции на уда­лен­ном хосте

 

меня­ем пра­ва на полу­чен­ном сертификате:

chmod 600 test.cert

всё теперь мож­но под­клю­чать­ся к целе­вой тачке:

ssh test@192.168.1.180 -i test.cert -i ~/.ssh/id_rsa

тут test.cert сер­ти­фи­кат кото­рый мы полу­чи­ли из vault
~/.ssh/id_rsa наш пуб­лич­ный сертификат

в логе /var/log/auth.log на целе­вой тач­ке мы видим:

всё ок.

напом­ню что когда мы созда­ва­ли role ssh-test мы зада­ли вре­мя жиз­ни 5 минут.

спу­стя 5 минут если мы вновь пыта­ем­ся под­клю­чить­ся то ниче­го не вый­дет, так как ttl истёк:

ssh test@192.168.1.180 -i test.cert -i ~/.ssh/id_rsa
test@192.168.1.180's password:

на целе­вой тач­ке в логе мы видим:

sshd[918]: error: Certificate invalid: expired

всё ок.
так и задумывалось.

 

что­бы вновь под­клю­чить­ся нам нуж­но пере­за­про­сить сертификат:

посмот­реть какие роли назна­че­ны на сек­рет мож­но командой:

посмот­реть эту роль мож­но так: