如何通过Terraform为AWS SFTP服务器用户绑定多个SSH密钥
问题
需要为AWS SFTP服务器的多个用户创建并绑定多个唯一SSH密钥,模块调用时通过对象映射传递用户和SSH密钥信息:
module "users" { source = "../../sftp_user" users = { "user1" = { region = "us-east-1", server_id = module.sftp_server.server_id, (...其他参数), public_keys = ["ssh key 1", "ssh key 2", "ssh key 3"] }, "user2" = {(...参数)} } }
当前的资源块仅能为每个用户绑定第一个SSH密钥:
resource "aws_transfer_ssh_key" "sshkeysattachment" { for_each = var.users server_id = each.value.server_id user_name = each.key body = each.value.public_keys[0] # 仅获取第一个SSH密钥 depends_on = [aws_transfer_user.users] # 确保用户已创建完成 }
尝试同时使用count和for_each时触发Terraform报错:
The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number of resources to be created.
尝试的错误代码如下:
resource "aws_transfer_ssh_key" "sshkeysattachment" { for_each = { for user, config in var.users : "${user}-${count.index}" => config if length(config.public_keys) > 0 } count = length(each.value.public_keys) server_id = each.value.server_id user_name = each.key body = each.value.public_keys[count.index] depends_on = [aws_transfer_user.user] }
需要实现为每个用户绑定其对应的所有SSH密钥。
解决方案
要实现每个用户绑定所有SSH密钥,需要先将用户与密钥的组合扁平化为一个唯一的键值对集合,再用for_each遍历这个集合,避免同时使用count和for_each。
具体代码如下:
resource "aws_transfer_ssh_key" "sshkeysattachment" { # 扁平化用户和密钥的组合:生成格式为"用户名-密钥索引"的唯一键 for_each = flatten([ for user_name, user_config in var.users : [ for idx, pub_key in user_config.public_keys : { key = "${user_name}-${idx}" server_id = user_config.server_id user = user_name public_key = pub_key } ] ]) server_id = each.value.server_id user_name = each.value.user body = each.value.public_key depends_on = [aws_transfer_user.users] }
代码说明
- 扁平化处理:通过嵌套的
for表达式,遍历每个用户的所有SSH密钥,为每个密钥生成一个包含server_id、user_name、public_key的对象,并用${user_name}-${idx}作为唯一标识键。 - for_each遍历:将扁平化后的列表转换为适合
for_each的映射(Terraform会自动将列表转换为以元素key字段为键的映射),确保每个SSH密钥对应一个独立的aws_transfer_ssh_key资源。 - 避免冲突:这种方式完全依赖
for_each,无需使用count,规避了两者互斥的问题,同时保证每个资源实例的唯一标识。
内容的提问来源于stack exchange,提问作者Satyam Raj
相关产品推荐
相关产品推荐

