Ansible GCP IAP隧道

时间:2019-11-22 14:38:11

标签: google-cloud-platform ansible

我正在尝试通过IAP连接到GCP计算实例。我有一个具有权限的服务帐户。

我尝试了以下

  1. 基本的ping操作ansible -vvvv GCP -m ping,由于未找到主机名而导致错误,因为我没有外部ip
  2. 我将ssh_executeable=wrapper.sh设置为here

数字2几乎可以正常运行,但是正则表达式命令很黑。

有本地的ansible解决方案吗?

编辑:gcp_compute动态清单确实可用于ping实例,但不适用于管理实例。

Ansible在通过IAP建立隧道时不支持程序包或系统管理。

5 个答案:

答案 0 :(得分:3)

对于那些仍在寻找在内部 IP 上使用带有 Ansible 的 IAP SSH 的解决方案的人。我对 here

列出的脚本进行了一些更改

我的主要问题是我必须添加 --zone 作为选项,因为 gcloud 在通过 Ansible 运行时不会自动检测到这一点。 由于我不想调用 CLI,增加了更多的等待时间,因此我选择使用 group_vars 来设置我的 ssh 选项。这也允许我为 gcloud compute ssh 命令指定其他选项。

以下是设置所需文件的内容:

ansible.cfg

[inventory]
enable_plugins = gcp_compute

[defaults]
inventory = misc/inventory.gcp.yml
interpreter_python = /usr/bin/python

[ssh_connection]
# Enabling pipelining reduces the number of SSH operations required
# to execute a module on the remote server.
# This can result in a significant performance improvement 
# when enabled.
pipelining = True
scp_if_ssh = False
ssh_executable = misc/gcp-ssh-wrapper.sh
ssh_args = None

misc/gcp-ssh-wrapper.sh

#!/bin/bash
# This is a wrapper script allowing to use GCP's IAP SSH option to connect
# to our servers.

# Ansible passes a large number of SSH parameters along with the hostname as the
# second to last argument and the command as the last. We will pop the last two
# arguments off of the list and then pass all of the other SSH flags through
# without modification:
host="${@: -2: 1}"
cmd="${@: -1: 1}"

# Unfortunately ansible has hardcoded ssh options, so we need to filter these out
# It's an ugly hack, but for now we'll only accept the options starting with '--'
declare -a opts
for ssh_arg in "${@: 1: $# -3}" ; do
        if [[ "${ssh_arg}" == --* ]] ; then
                opts+="${ssh_arg} "
        fi
done

exec gcloud compute ssh $opts "${host}" -- -C "${cmd}"

group_vars/all.yml

---
ansible_ssh_args: --tunnel-through-iap --zone={{ zone }} --no-user-output-enabled --quiet

如您所见,通过使用 group_vars 中的 ansible_ssh_args,我们现在可以通过清单中已知的区域。

如果你也希望能够通过 gcloud 命令复制文件,你可以使用以下配置:

ansible.cfg

[ssh_connection]
# Enabling pipelining reduces the number of SSH operations required to
# execute a module on the remote server. This can result in a significant
# performance improvement when enabled.
pipelining = True
ssh_executable = misc/gcp-ssh-wrapper.sh
ssh_args = None
# Tell ansible to use SCP for file transfers when connection is set to SSH
scp_if_ssh = True
scp_executable = misc/gcp-scp-wrapper.sh

misc/gcp-scp-wrapper.sh

#!/bin/bash
# This is a wrapper script allowing to use GCP's IAP option to connect
# to our servers.

# Ansible passes a large number of SSH parameters along with the hostname as the
# second to last argument and the command as the last. We will pop the last two
# arguments off of the list and then pass all of the other SSH flags through
# without modification:
host="${@: -2: 1}"
cmd="${@: -1: 1}"

# Unfortunately ansible has hardcoded scp options, so we need to filter these out
# It's an ugly hack, but for now we'll only accept the options starting with '--'
declare -a opts
for scp_arg in "${@: 1: $# -3}" ; do
        if [[ "${scp_arg}" == --* ]] ; then
                opts+="${scp_arg} "
        fi
done

# Remove [] around our host, as gcloud scp doesn't understand this syntax
cmd=`echo "${cmd}" | tr -d []`

exec gcloud compute scp $opts "${host}" "${cmd}"

group_vars/all.yml

---
ansible_ssh_args: --tunnel-through-iap --zone={{ zone }} --no-user-output-enabled --quiet
ansible_scp_extra_args: --tunnel-through-iap --zone={{ zone }} --quiet

答案 1 :(得分:1)

(按照OP的要求将我的评论转换为答案)

Ansible具有一个本机gce dynamic inventory plugin,您应使用它来连接到实例。

答案 2 :(得分:1)

除非所有清单都可以公开访问,否则

gce动态清单不起作用。对于专用ip,在执行ansible命令时不会调用隧道。 gce动态清单将返回清单,但是如果仅在隧道和专用IP之后,则实际上无法发送命令。我能找到的唯一解决方法是,在自定义脚本中使用ssh二进制点,该脚本称为gcloud包装器。

答案 3 :(得分:1)

不是对 OP 的直接回答,但是在我对如何保证我的项目安全(通过 IAP)并让 ansible 以合理的速度工作感到沮丧之后,我最终混合了 IAP 和 OS 登录。如果需要,这将继续使用动态库存。

我在我的虚拟机上使用 IAP 并且没有公共 IP,然后我在整个项目范围内启用了 OS Login 并且我在项目内部创建了一个小的“ansible-server”虚拟机(这是一个 WIP,最后VPC 配对项目应该 CI/CD ansible,但这是另一回事)。

  • 在虚拟机内部,我通过
  • 设置了专用服务帐户的身份

gcloud auth activate-service-account name@project.iam.gserviceaccount.com --key-file=/path/to/sa/json/key

  • 然后我创建了一对 ssh 密钥
  • 我已通过导出公钥使 S.A. 能够登录

gcloud compute os-login ssh-keys add --key-file ~/.ssh/my-sa-public-key

  • 我从 VM 中运行所有剧本,将 -u 开关传递给 ansible。这非常快,让我可以通过 IAM 撤销任何权限,避免将浮动 ssh 密钥丢弃到项目或 VM 元数据中。

所以现在的流程是:

  • 我使用 IAP 从我的工作站登录到项目内的 ansible VM
  • 我在 VM 中克隆了 ansible 存储库
  • 我模拟 S.A. 运行 ansible

注意事项:

  • 要获得正确的用户名以传递给 ansible(通过 -u),请记录前一个 os-login 命令提供的用户名(它出现在添加的密钥的输出中,在我的情况下是类似 sa_[0- 9]*)
  • 确保 S.A. 具有服务帐户用户和操作系统管理员登录 IAM 角色,否则 ssh 将失败
  • 当然,这意味着您必须在专用于 ansible 的项目中保留一个 VM,并且您还需要将 ansible 代码克隆到 VM 中。就我而言,我缓解了“问题”,只需根据需要打开/关闭虚拟机,并使用相同的公钥授予对 ansible 存储库的只读访问权限(在我的情况下为 bitbucket)

答案 4 :(得分:0)

为了使 lotjuh 的答案起作用,我还必须更新我的inventory.gcp.yml 文件以具有以下内容

plugin: gcp_compute
projects:
  - myproject
auth_kind: application
hostnames:
  - name

如果没有 hostnames: - name,我会收到 gcloud ssh 错误,因为它尝试使用其主机 IP ssh 进入实例。

此方法还要求使用 gcloud config set project myproject

在 gcloud 配置中设置项目