Совместное использование конфиденциальных переменных между ansible и terraform

Простое доказательство концепции, как разделить некоторые конфиденциальные переменные между terraform и ansible таким образом, чтобы это позволяло делать коммиты в git, а также достаточно легко расшифровывалось и использовалось изначально через ansible play.

Ансибль

Давайте создадим несколько чувствительных переменных в ansible play, env-default-secure-vars.yml:

---
  

  shared_secure_var1: securevalue1

  shared_secure_var2: securevalue2

и зашифровать этот файл с помощью ansible-vault encrypt env-default-secure-vars.yml

Давайте проверим, может ли ansible работать с зашифрованными переменными, используя playbook


---
- name: TerraformAnsiblePOC
  hosts: localhost
  gather_facts: no

  pre_tasks:

    - include_vars: "env-default-secure-vars.yml"

    - include_vars:  "env-default-vars.yml"

  tasks:
    
    - debug: var="shared_secure_var1"

    - debug: var="shared_secure_var2"



PLAY [TerraformAnsiblePOC] *****************

TASK [debug] *******************************
ok: [localhost] => {
    "shared_secure_var1": "securevalue1"
}

TASK [debug] *******************************
ok: [localhost] => {
    "shared_secure_var2": "securevalue2"
}

PLAY RECAP ******************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0   

Терраформ

Теперь давайте посмотрим, как мы можем использовать те же данные при терраформировании?

К счастью, у нас есть встроенный внешний провайдер, который позволяет использовать json-канал.
возвращается внешней программой


data "external" "ansible" {
  program  = [ "tf_ansible_vault.sh", "env-default-secure-vars.yml"]
}

output "shared_secure_var1" {
  value = "${data.external.ansible.result.shared_secure_var1}"
}

output "shared_secure_var2" {
  value = "${data.external.ansible.result.shared_secure_var2}"
}


Давайте напишем процедуру оболочки, которая будет возвращать json-представление зашифрованных переменных.


#!/bin/bash

set -ef -o pipefail

export LC_ALL="C"

readonly TMP_DIR="/tmp"
readonly TMP_OUTPUT="${TMP_DIR}/$$.out"
readonly BASE_DIR="$(dirname "$(realpath "$0")")"
readonly MY_NAME="${0##*/}"
# Cleanup on exit
trap 'rm -rf ${TMP_OUTPUT}' \
  EXIT SIGHUP SIGINT SIGQUIT SIGPIPE SIGTERM

if [[ -z "$ANSIBLE_VAULT_IDENTITY_LIST" ]]
then
      echo "Please export path to vault id via ANSIBLE_VAULT_IDENTITY_LIST"
      exit 1
fi

if [[ -z "$1" ]]
then
      echo "Please provide path to secrets file"
      exit 1
fi

#echo cp $1 $TMP_OUTPUT
cp $1 $TMP_OUTPUT

ansible-vault decrypt $TMP_OUTPUT > /dev/null

python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)' < $TMP_OUTPUT

rm $TMP_OUTPUT


Проверяем, работает ли скрипт…


./tf_ansible_vault.sh env-default-secure-vars.yml 
{
    "shared_secure_var2": "securevalue2", 
    "shared_secure_var1": "securevalue1"
}

а теперь давайте проверим с помощью terraform play:


terraform apply            
data.external.ansible: Refreshing state...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

shared_secure_var1 = securevalue1
shared_secure_var2 = securevalue2


Кажется, это работает. Выглядит очень многообещающе, но давайте заглянем в terraform.tfstate.


{
    "version": 3,
    "terraform_version": "0.11.11",
    "serial": 1,
    "lineage": "7f589f33-7ef8-7d45-19ab-d053412dd875",
    "modules": [
        {
            "path": [
                "root"
            ],
            "outputs": {},
            "resources": {
                "data.external.ansible": {
                    "type": "external",
                    "depends_on": [],
                    "primary": {
                        "id": "-",
                        "attributes": {
                            "id": "-",
                            "program.#": "2",
                            "program.0": "tf_ansible_vault.sh",
                            "program.1": "env-default-secure-vars.yml",
                            "result.%": "2",
                            "result.shared_secure_var1": "securevalue1",
                            "result.shared_secure_var2": "securevalue2"
                        },
                        "meta": {},
                        "tainted": false
                    },
                    "deposed": [],
                    "provider": "provider.external"
                }
            },
            "depends_on": []
        }
    ]
}


Мы видим там наши расшифрованные безопасные переменные, так что будьте осторожны, как вы их храните. Терраформ имеет
количество обращений по схожим вопросам (за
несколько лет, но до сих пор нет хорошего решения.

Резюме

POC показывает, как вы можете поделиться некоторыми своими переменными подготовки с terraform и обратно (terraform
может генерировать файл переменных yml). Может быть подходящим для некоторых ситуаций, хотя и не идеальным.

Посмотрите пример на

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *