Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revisionBoth sides next revision
devops:hashicorp_vault_workflow [2020/08/12 22:42] – [Автоматическое обновление сертификатов с помощью consul-template] admindevops:hashicorp_vault_workflow [2020/08/13 19:46] – [Автоматическое обновление сертификатов с помощью consul-template] admin
Line 294: Line 294:
   * в деплойменте прикладного пода (nginx) прописываются два дополнительных контейнера. Первый - init-контейнер vault-agent, который берет конфигурацию из конфигмапа и получает токен. Этот токен в дальнейшем использует второй контейнер - consul-template, который занимается тем, что обновляет данные в соответствии с темплейтом записаным в конфигмап. Обновленные данные он кладет в папку, которая смонтирована в него и в прикладной под с nginx.   * в деплойменте прикладного пода (nginx) прописываются два дополнительных контейнера. Первый - init-контейнер vault-agent, который берет конфигурацию из конфигмапа и получает токен. Этот токен в дальнейшем использует второй контейнер - consul-template, который занимается тем, что обновляет данные в соответствии с темплейтом записаным в конфигмап. Обновленные данные он кладет в папку, которая смонтирована в него и в прикладной под с nginx.
   * Для того, чтобы все работало в Vault должна быть заведена политика, которая бы разрешала доступ для заданной роли в путь, где выпускаются сертификаты.   * Для того, чтобы все работало в Vault должна быть заведена политика, которая бы разрешала доступ для заданной роли в путь, где выпускаются сертификаты.
-Создадим файл политики:+Создадим файл политики, которая разрешить выпуск сертификатов с помощью промежуточного CA:
 <code>tee cert_issue_policy.hcl <<EOF <code>tee cert_issue_policy.hcl <<EOF
 path "pki_int/issue/*" { path "pki_int/issue/*" {
Line 300: Line 300:
 } }
 EOF</code> EOF</code>
-скопируем его в **vault**:+скопируем файл политики в **vault**:
   kubectl -n vault cp cert_issue_policy.hcl vault-0:/tmp/   kubectl -n vault cp cert_issue_policy.hcl vault-0:/tmp/
-и создадим с его помощью политику:+и создадим с него помощью политику:
   kubectl -n vault exec -it vault-0 -- vault policy write cert-issue-policy /tmp/cert_issue_policy.hcl   kubectl -n vault exec -it vault-0 -- vault policy write cert-issue-policy /tmp/cert_issue_policy.hcl
-а также - создаим роль в vault:+а также - создадим роль в **vault**, которую привяжем к ServiceAccount (с правами которого будет работать pod) и назначим этой роли созданную ранее политику, разрешающую выпуск сертов:
   kubectl -n vault exec -it vault-0 -- vault write auth/kubernetes/role/cert-issue-role bound_service_account_names=vault-auth bound_service_account_namespaces=vault policies=cert-issue-policy ttl=24h   kubectl -n vault exec -it vault-0 -- vault write auth/kubernetes/role/cert-issue-role bound_service_account_names=vault-auth bound_service_account_namespaces=vault policies=cert-issue-policy ttl=24h
 +А теперь создадим объекты в K8S.
 +===== configmap =====
 +Конфигмап содержит три конфига:
 +  * для **init**-контейнера **vault-agent**, который аутентифицируется с помощью **ServiceAccount** и получит токен для контейнера **consul-template**
 +  * для **consul-template**в котором описано где взять токен, поученный **vault-agent**, что именно забрать из **vault** (сертификат и ключ), куда это потом положить (в файлы) и что сделать после этого (послать сигнал nginx для обновления конфига).
 +  * конфиг **nginx**, в котором настроен HTTPS-сервер, использующий файлы сертификата и ключа, полученные из **Vault**.
 +<code>apiVersion: v1
 +kind: ConfigMap
 +metadata:
 +  name: nginx-cert-renew-config
 +  namespace: vault
 +data:
 +  vault-agent-config.hcl: |
 +    # Comment this out if running as sidecar instead of initContainer
 +    exit_after_auth = true
 +
 +    pid_file = "/home/vault/pidfile"
 +
 +    auto_auth {
 +        method "kubernetes" {
 +            mount_path = "auth/kubernetes"
 +            config = {
 +                role = "cert-issue-role"
 +            }
 +        }
 +
 +        sink "file" {
 +            config = {
 +                path = "/home/vault/.vault-token"
 +            }
 +        }
 +    }
 +
 +  consul-template-config.hcl: |
 +    vault {
 +      renew_token = false
 +      vault_agent_token_file = "/home/vault/.vault-token"
 +      retry {
 +        backoff = "1s"
 +      }
 +    }
 +
 +    template {
 +        contents = "{{ with secret \"pki_int/issue/example-dot-ru\" \"common_name=test.example.ru\" \"ttl=2m\"}}{{ .Data.certificate }}{{ end }}"
 +        destination="/etc/secrets/tls.crt"
 +        command="sh -c 'killall -s HUP nginx || true'"
 +    }
 +    template {
 +        contents = "{{ with secret \"pki_int/issue/example-dot-ru\" \"common_name=test.example.ru\" \"ttl=2m\"}}{{ .Data.private_key }}{{ end }}"
 +        destination="/etc/secrets/tls.key"
 +    }
 +    template {
 +        contents = "{{ with secret \"pki_int/issue/example-dot-ru\" \"common_name=test.example.ru\" \"ttl=2m\"}}{{ .Data.issuing_ca }}{{ end }}"
 +        destination="/etc/secrets/int_ca.crt"
 +    }
 +
 +  nginx_ssl.conf: |
 +    server {
 +      listen              443 ssl;
 +      server_name         test.example.ru;
 +      ssl_certificate     /etc/nginx/ssl/tls.crt;
 +      ssl_certificate_key /etc/nginx/ssl/tls.key;
 +      ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
 +      ssl_ciphers         HIGH:!aNULL:!MD5;
 +
 +      location / {
 +        root   /usr/share/nginx/html;
 +        index  index.html index.htm;
 +      }
 +    }
 +</code>
 +===== Pod =====
 +Манифест Pod'а с тремя контейнерами:
 +<code>apiVersion: v1
 +kind: Pod
 +metadata:
 +  name: nginx-cert-renew-example
 +  namespace: vault
 +  labels:
 +    app: nginx
 +spec:
 +  shareProcessNamespace: true
 +  serviceAccountName: vault-auth
 +  volumes:
 +  - configMap:
 +      items:
 +      - key: vault-agent-config.hcl
 +        path: vault-agent-config.hcl
 +      - key: consul-template-config.hcl
 +        path: consul-template-config.hcl
 +      name: nginx-cert-renew-config
 +    name: config
 +  - configMap:
 +      items:
 +      - key: nginx_ssl.conf
 +        path: nginx_ssl.conf
 +      name: nginx-cert-renew-config
 +    name: nginx-config
 +  - emptyDir: {}
 +    name: shared-data
 +  - emptyDir: {}
 +    name: vault-token    
 +
 +  initContainers:
 +  - args:
 +    - agent
 +    - -config=/etc/vault/vault-agent-config.hcl
 +    - -log-level=debug
 +    env:
 +    - name: VAULT_ADDR
 +      value: http://vault:8200
 +    image: vault
 +    imagePullPolicy: IfNotPresent
 +    name: vault-agent
 +    volumeMounts:
 +    - mountPath: /etc/vault
 +      name: config
 +    - name: vault-token
 +      mountPath: /home/vault
 +
 +  containers:
 +  - image: nginx
 +    imagePullPolicy: IfNotPresent
 +    name: nginx-container
 +    ports:
 +    - containerPort: 80
 +    volumeMounts:
 +    - mountPath: /etc/nginx/ssl/
 +      name: shared-data
 +    - mountPath: /etc/nginx/conf.d/
 +      name: nginx-config
 +  - name: consul-template
 +    image: hashicorp/consul-template:alpine
 +    imagePullPolicy: IfNotPresent
 +    securityContext:
 +      runAsUser: 0
 +      capabilities:
 +        add:
 +        - SYS_PTRACE
 +    volumeMounts:
 +      - name: vault-token
 +        mountPath: /home/vault
 +      - name: config
 +        mountPath: /etc/consul-template
 +      - name: shared-data
 +        mountPath: /etc/secrets
 +    env:
 +      - name: HOME
 +        value: /home/vault
 +      - name: VAULT_ADDR
 +        value: http://vault:8200
 +    args: ["-config=/etc/consul-template/consul-template-config.hcl"]
 +</code>
 +Тут стоит обратить внимание на:
 +  shareProcessNamespace: true
 +Эта конструкция позволяет иметь процессам всех контейнеров общий **namespace**, чтобы можно было управлять процессом **nginx** из контейнера **consul-template**. \\
 +Также важно, чтобы у контейнера consul-template был такой **securityContext**:
 +    securityContext:
 +      runAsUser: 0
 +      capabilities:
 +        add:
 +        - SYS_PTRACE
 +Это значит, что процессы этого контейнера будут исполняться с **id=0** (то есть иметь права **root** с точки зрения всех процессов pod'а) и у процессов этого контейнера будут права посылать сигналы в другеи контейнеры (**SYS_PTRACE**). Подробнее тут - https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/ \\
  • devops/hashicorp_vault_workflow.txt
  • Last modified: 2020/08/13 19:48
  • by admin