terraform - 在 Terraform 中隐藏秘密
问题描述
我正在尝试使用 Terraform 在帕洛阿尔托创建 IPSEC 隧道。代码将通过管道推送。我希望隧道的所有信息都是可读的,除了pre_shared_key
. 我了解如何为一个实例加密它,但由于会有多个隧道,如何加密密钥并将其映射到它的实例?
vpns.yml:
vpns:
- name: "Test"
template: "template_name"
ip_type: "IP"
ip_remote: "1.1.1.1"
firewall_interface: "vlan.xxxx"
local_ip: "public_ip/24"
ikev2_profile: "VerySecure"
tunnel_interface: "tunnel1"
pre_shared_key: "*******"
我迭代的隧道模块如下所示:
locals {
tunnel = yamldecode(file(var.vpn_file))
}
resource "panos_panorama_ike_gateway" "gateway" {
for_each = { for e in local.tunnel : e.Name => e }
name = each.value.name
template = each.value.template
version = "ikev2-preferred"
peer_ip_type = each.value.ip_type
peer_ip_value = each.value.ip_remote
interface = each.value.firewall_interface
local_ip_address_type = "ip"
local_ip_address_value = each.value.local_ip
pre_shared_key = each.value.pre_shared_key
ikev2_crypto_profile = each.value.ikev2_profile
enable_dead_peer_detection = true
dead_peer_detection_interval = "10"
dead_peer_detection_retry = "3"
liveness_check_interval = "5"
}
解决方案
Gruntwork 的机密管理指南涵盖了很多内容,因此可能值得一读。
理想情况下,您将使用外部密钥管理器(例如 Hashicorp Vault 或 AWS SSM Parameter Store/Secrets Manager)并使用 生成密钥random_password
,将其存储在隧道一侧的密钥存储中,然后在应用时从密钥存储中检索它隧道的另一边。
如果您打算使用单个创建隧道的两侧terraform apply
(例如,您将两者的配置保存在同一个目录中),那么您甚至不需要秘密存储并且可以只依赖于秘密只被存储的事实处于 Terraform 状态,永远不会出现在只有random_password
资源输入的仓库中。
在您的情况下,您将拥有以下内容:
locals {
tunnel = {
"vpns" = [
{
"firewall_interface" = "vlan.xxxx"
"ikev2_profile" = "VerySecure"
"ip_remote" = "1.1.1.1"
"ip_type" = "IP"
"local_ip" = "public_ip/24"
"name" = "TestLeft"
"template" = "template_name"
"tunnel_interface" = "tunnel1"
},
{
"firewall_interface" = "vlan.xxxx"
"ikev2_profile" = "VerySecure"
"ip_remote" = "2.2.2.2"
"ip_type" = "IP"
"local_ip" = "public_ip/24"
"name" = "TestRight"
"template" = "template_name"
"tunnel_interface" = "tunnel1"
},
]
}
}
resource "random_password" "pre_shared_key" {
length = 32
}
resource "panos_panorama_ike_gateway" "gateway" {
for_each = { for e in local.tunnel : e.Name => e }
name = each.value.name
template = each.value.template
version = "ikev2-preferred"
peer_ip_type = each.value.ip_type
peer_ip_value = each.value.ip_remote
interface = each.value.firewall_interface
local_ip_address_type = "ip"
local_ip_address_value = each.value.local_ip
pre_shared_key = random_password.pre_shared_key.result
ikev2_crypto_profile = each.value.ikev2_profile
enable_dead_peer_detection = true
dead_peer_detection_interval = "10"
dead_peer_detection_retry = "3"
liveness_check_interval = "5"
}
另一种选择是使用GPG或age之类的东西加密你的 repo 中的整个 YAML 文件,使用SOPS或Ansible Vault之类的东西有选择地加密文件的一部分,或者将秘密分离到另一个完全加密的文件中上述任何选项,其余的非秘密配置以纯文本形式保留。然后,您可以在运行 Terraform 命令之前解密相关机密。
您需要确保安全访问和加密您的 Terraform 状态文件,因为这些文件将以纯文本形式保存秘密。Terraform 远程状态后端通常提供执行此操作的方法,例如指定用于加密 S3 中的状态文件的 KMS 密钥。
从 Terraform 0.14 开始,您还可以将变量标记为敏感变量,这将在将它们写入标准输出时屏蔽它们。使用上面的使用模式random_password
会自动为您处理,但如果您要将预共享密钥作为变量输入,那么您需要明确地将其标记为敏感:
variable "pre_shared_key" {
description = "The pre-shared key for the VPN tunnel"
type = string
sensitive = true
}
推荐阅读
- java - 如何将 Spring Integration XML 转换为 Java DSL
- variables - 是否可以将哈希表作为 AzureDevops 中的变量从一个代理阶段传递到另一个代理阶段
- mysql - Erlang 无法连接到 mysql/mariadb
- python - 从整个列的 DF 中获取索引值的索引值的 DataFrame
- django - 使用 ReactJS 作为前端时,我们需要渲染模板吗?
- python - 如何获取先前的行值并用作输入来计算 Pandas 中的当前行值?
- python - 在算法运行之前,我将如何创建一个函数来测试我的树?
- oracle - 连接到 Teamcity 到 OCI 自治事务处理数据库
- django - Django Celery:任务永远不会执行
- python - 为什么元组或列表中的最后一个值索引在python中给出不同的类而切片给出不同的?