Ansible 中基于路径的参数的流程替换

2023-12-23

许多 Ansible 模块被设计为接受文件路径作为参数,但无法直接提供文件内容。如果输入数据实际上来自文件以外的其他内容,这会强制人们在磁盘上的某个位置创建一个临时文件,将预期的参数值写入其中,然后将该临时文件的路径提供给 Ansible 模块。

为了说明目的,举一个现实生活中的例子:java_certAnsible模块 https://docs.ansible.com/ansible/latest/collections/community/general/java_cert_module.html接受参数pkcs12_路径包含要导入给定 Java 密钥库的密钥对的 PKCS12 密钥库的路径。现在假设该数据是通过 Vault 查找检索的,因此为了能够为模块提供所需的路径,我们必须将 Vault 查找结果写入临时文件,使用文件的路径作为参数,然后处理临时文件的安全删除,因为数据可能是机密的。

当在 Shell/bash 脚本环境中出现此类情况时,即命令行工具的标志仅支持与文件交互,进程替换的魔力(例如--file=<(echo $FILE_CONTENTS))允许通过透明地提供一个命名管道来将工具的输入和输出数据与其他命令链接起来,该命名管道的作用就像磁盘上的(大部分)普通文件一样。

在 Ansible 中,是否有任何类似的机制可以用更灵活的结构替换基于文件的参数,从而允许使用来自变量或其他命令的数据?如果没有内置方法可以实现这一点,是否有第三方解决方案可以实现这一点,或者可以像我描述的那样简化工作流程?例如,类似于自定义查找插件,它提供文件内容数据,然后在后台透明地处理文件管理(即创建、写入数据和最终删除)并提供临时路径作为其返回值,而用户不一定需要知道它。

这种插件的示例用法可以是:

    ...
    pkcs_path: "{{ lookup('as_file', '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY----- ') }}"
    ...

使用插件然后在例如下创建一个文件/tmp/as_file.sg7N3bX包含第二个参数中的文本键并返回此文件路径作为查找结果。然而,我不确定在这种情况下如何准确地实现文件的持续管理(尤其是敏感数据的及时删除)。


免责声明:

  • 我(显然!)以下合集的作者,该合集是为了回应上述问题而创建的
  • 查找插件尚未经过彻底测试,对于特定模块可能会失败。

由于这是一个非常好的主意,而且什么都不存在,所以我决定尝试一下。这一切最终都集中在一个集合中,现在称为thoteam.var_as_file这是可用的在 github 仓库中 https://github.com/ansible-ThoTeam/thoteam.var_as_file。我不会将所有文件粘贴到这个答案中,因为它们都可以在提到的存储库中使用完整的自述文件 https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/README.md安装、测试和使用。

全球的想法如下:

  • 创建一个查找插件,负责推送具有给定内容的新临时文件并返回使用它们的路径。
  • 在 playbook 运行结束时清理创建的文件。对于这一步,我创建了一个回调插件,它启动监听的清理操作v2_playbook_on_stats events.

我仍然对并发性(尚未清理的文件存储在磁盘上的静态 json 文件中)和可靠性(不确定stats阶段在所有情况下都会发生,尤其是在崩溃时)。我也不完全确定使用回调是一个好的实践/最佳选择。

同时,编写代码非常有趣并且它完成了工作。我将看看这项工作是否被其他人使用,并且可能会在接下来的几周内很好地增强所有这些(如果您有 PR 来修复已知的问题,我很乐意接受它们)。

安装并启用回调插件后(请参阅https://github.com/ansible-ThoTeam/thoteam.var_as_file#installing-the-collection https://github.com/ansible-ThoTeam/thoteam.var_as_file#installing-the-collection),可以在任何地方使用查找来获取包含传递内容的文件路径。例如:

- name: Get a filename with the given content for later use
  ansible.builtin.set_fact:
    my_tmp_file: "{{ lookup('thoteam.var_as_file.var_as_file', some_variable) }}"
    
- name: Use in place in a module where a file is mandatory and you have the content in a var
  community.general.java_cert:
    pkcs12_path: "{{ lookup('thoteam.var_as_file.var_as_file', pkcs12_store_from_vault) }}"
    cert_alias: default
    keystore_path: /path/to/my/keystore.jks
    keystore_pass: changeit
    keystore_create: yes
    state: present

这些是两个插件文件的相关部分。我删除了 ansible 文档变量(为了简洁),如果您愿意,您可以直接在 git 存储库中找到它。

plugins/lookup/var_as_file.py https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/plugins/lookup/var_as_file.py

from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.thoteam.var_as_file.plugins.module_utils.var_as_file import VAR_AS_FILE_TRACK_FILE
from hashlib import sha256
import tempfile
import json
import os

def _hash_content(content):
    """
    Returns the hex digest of the sha256 sum of content
    """
    return sha256(content.encode()).hexdigest()

class LookupModule(LookupBase):

    created_files = dict()

    def _load_created(self):
        if os.path.exists(VAR_AS_FILE_TRACK_FILE):
            with open(VAR_AS_FILE_TRACK_FILE, 'r') as jfp:
                self.created_files = json.load(jfp)

    def _store_created(self):
        """
        serialize the created files as json in tracking file
        """

        with open(VAR_AS_FILE_TRACK_FILE, 'w') as jfp:
            json.dump(self.created_files, jfp)

    def run(self, terms, variables=None, **kwargs):

        '''
        terms contains the content to be written to the temporary file
        '''
        try:
            self._load_created()

            ret = []
            for content in terms:
                content_sig = _hash_content(content)
                file_exists = False

                # Check if file was already create for this content and check it.
                if content_sig in self.created_files:
                    if os.path.exists(self.created_files[content_sig]):
                        with open(self.created_files[content_sig], 'r') as efh:
                            if content_sig == _hash_content(efh.read()):
                                file_exists = True
                                ret.append(self.created_files[content_sig])
                            else:
                                os.remove(self.created_files[content_sig])

                # Create / Replace the file
                if not file_exists:
                    temp_handle, temp_path = tempfile.mkstemp(text=True)
                    with os.fdopen(temp_handle, 'a') as temp_file:
                        temp_file.write(content)
                        self.created_files[content_sig] = temp_path
                        ret.append(temp_path)

            self._store_created()

            return ret

        except Exception as e:
            raise AnsibleError(to_native(repr(e)))

plugins/callback/clean_var_as_file.py https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/plugins/callback/clean_var_as_file.py

from ansible.plugins.callback import CallbackBase
from ansible_collections.thoteam.var_as_file.plugins.module_utils.var_as_file import VAR_AS_FILE_TRACK_FILE
from ansible.module_utils.common.text.converters import to_native
from ansible.errors import AnsibleError
import os
import json

def _make_clean():
    """Clean all files listed in VAR_AS_FILE_TRACK_FILE"""
    try:
        with open(VAR_AS_FILE_TRACK_FILE, 'r') as jfp:
            files = json.load(jfp)
            for f in files.values():
                os.remove(f)
        os.remove(VAR_AS_FILE_TRACK_FILE)
    except Exception as e:
        raise AnsibleError(to_native(repr(e)))

class CallbackModule(CallbackBase):
    ''' This Ansible callback plugin cleans-up files created by the thoteam.var_as_file.var_as_file lookup '''
    CALLBACK_VERSION = 2.0
    CALLBACK_TYPE = 'utility'
    CALLBACK_NAME = 'thoteam.var_as_file.clean_var_as_file'

    CALLBACK_NEEDS_WHITELIST = False
    # This one doesn't work for a collection plugin
    # Needs to be enabled anyway in ansible.cfg callbacks_enabled option
    CALLBACK_NEEDS_ENABLED = False

    def v2_playbook_on_stats(self, stats):
        _make_clean()

如果您尝试一下,我将很高兴收到任何反馈。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ansible 中基于路径的参数的流程替换 的相关文章

  • Ansible sudo 在执行 5 个任务后挂起

    设置要求 本地用户 goagent1 ansible从GoCD启动 远程用户 myadmin myadmin 是一个需要密码的 sudoer 我们在剧本级别启用了 sudo Problem 该剧本似乎在执行了大约 5 个任务后停止了 发生得
  • ansible 有 yaml 编辑模块吗?

    我需要修改 yaml 文件 施洛德配置 http schleuder2 nadir org documentation v2 2 index html 并且我想从 ansible 剧本中执行此操作 是否有模块可以执行此操作 很难用谷歌搜索这
  • Ansible:shell 脚本输出始终为空

    我试图将 Linux shell 的输出插入到变量中 但由于某种原因 该变量始终为空 这是 Ansible 代码 name Check PHP version shell php v 2 gt dev null awk print 2 ex
  • 如何在 playbook 中使用 Ansible Tower 登录凭据?

    是否可以使用我用来直接在剧本中登录 Ansible Tower 的凭据 是的 您可以通过使用 保存您的凭据 来完成此操作安西布尔塔 Ansible Tower 上的凭证类型 从 Ansible Tower UI 中 转至 Credentia
  • 在 Mac OS X 上静态嵌入 Python 时动态符号查找失败

    我正在构建一个嵌入 Python 的 Mac OS X 应用程序 从技术上讲 我的应用程序是一个捆绑包 即它的主要可执行文件是 MH BUNDLE 它是另一个应用程序的插件 我希望它静态嵌入 Python 但希望能够动态加载扩展 我做了以下
  • 在 ansible 角色中引用 defaults/main.yml 中的变量

    我的角色设置如下 角色 测试 任务 main yml name Generate people files template src test j2 dest tmp item name cfg loop people 角色 测试 模板 t
  • Ansible 手册:错误! “command”不是 Play 的有效属性[重复]

    这个问题在这里已经有答案了 我只是想写一个基本的剧本 并不断收到下面的错误 尝试了很多东西但仍然无法做到正确 我知道这一定是语法问题 但不知道在哪里 这是我的代码 This playbook runs a basic DF command
  • 如何将命名管道字符串从非托管代码空间发送到托管代码空间?

    我似乎遇到了命名管道 101 问题 我有一个非常简单的设置来连接从 C 非托管应用程序传输到 C 托管应用程序的单工命名管道 管道已连接 但我无法通过管道发送 消息 除非我关闭似乎刷新缓冲区并传递消息的句柄 就好像消息被屏蔽了一样 我尝试颠
  • 如何在命名管道 (mkfifo) 上执行非阻塞 fopen?

    如果我有一个程序使用 mkfifo 创建并尝试打开命名管道 如何在不阻塞的情况下打开管道进行读取或写入 具体来说 我正在编写一个 C 程序 它可以在有或没有 GUI 的情况下运行 用 Java 编写 在 C 程序中 我使用 mkfifo 成
  • Ansible:即使成为 sudo 用户,也无法配置 sudo 命令

    testuser 是 sudo 用户 sudo cat etc sudoers d 90 cloud init testuser testuser ALL ALL NOPASSWD ALL 我可以手动登录 testuser 并在没有密码的情
  • 使用 Python API 2.0.0.1 运行 Ansible Playbook

    安塞布尔版本 2 0 0 1 我现在已经四处寻找了很多 我发现的大多数文档要么不完整 要么已弃用 这篇文章适用于1 8 4版本 即 https stackoverflow com questions 27590039 running ans
  • 附加到 group_vars 中的 Ansible 字典而不使用 hash_behaviour = merge

    我想定义一个字典变量 各个主机组可以将自己的密钥添加到其中在group vars中 不使用set fact 例如 像这样的东西 group vars ftp servers yml important ports ftp 21 group
  • 如何在 jinja2 中缩进嵌套的 if/for 语句

    我有一个很长的 Jinja2 模板 其中有很多嵌套if for声明 很难读 我想缩进 位 使其更清晰 但是 如果我这样做 这些块的内容也会进一步缩进 我怎样才能缩进just the bits 我正在使用安塞布尔 重现步骤 template
  • 自动打开命名管道和 tcp\ip

    我正在安装一个需要修改 SQL Server 的新产品 具体来说 启用 tcp ip 并打开命名管道 我知道如何手动完成 我想要的是一种通过 SQL 或 C 代码为新客户自动化执行此操作的方法 我希望有任何关于正确方向的建议 您可以使用 C
  • 如何更改 ansible_default_ipv4?

    我想将 ansible default ipv4 更改为指向 eth1 而不是 eth0 我可以在剧本中或通过 extra vars 选项来执行此操作吗 ansible 使用命令 https github com ansible ansib
  • if else 在 ansible 打印语句中

    我需要有关具有多个条件的打印语句的语法的帮助 目前 报价为 inventory hostname 导致错误 如果我删除剧本运行的引号 但列出文本 inventory hostname 而不是变量 我想知道如何打印变量以及 if else 语
  • R中的字典数据结构

    在 R 中 我有 例如 gt foo lt list a 1 b 2 c 3 如果我输入foo I get a 1 1 b 1 2 c 1 3 我怎样才能看透foo仅获取 键 列表 在这种情况下 a b c R 列表可以具有命名元素 因此可
  • local_action:shell 连接文件时出错

    我的剧本中有这样的错误 为什么以及如何解决它 获取远程主机的更新列表 将列表连接到一个文件中 name Save update deb packs in file on ansible host copy content update de
  • 在单元格中查找以逗号分隔的多个值并返回以逗号分隔的多个值

    如果有人可以帮忙的话 我们将此表称为 1 我想在此处执行查找 可以将工作表 2 中 B 列的值引入工作表 1 中的 B 列 返回的多个值也应该用逗号分隔 我在这里尝试使用 textjoin 公式 但它搞砸的地方是 例如它将 A12 计为 A
  • 在 Ansible 中使用模板模块附加文件

    所以我有一个 ansible 剧本 它使用 Jinja2 模板来创建日志文件 每次我运行剧本时 它都会从customers yml中提取客户信息 并将完整的模板输出到 stunnel conf 文件中 该模板工作正常 但我试图找到一种方法来

随机推荐

  • 防止 contenteditable 元素在单击父级时获得焦点

    点击时anywhere在以下示例中 在 外部 div 容器上方 contenteditable span 元素获得焦点 div style margin 30px span style background eee Hello World
  • 如何获取从 sstream 变量中提取字符串后剩余的字符串?

    就像我有一个stringstream变量包含 abc gg rrr ff 当我使用 gt gt 在那stringstream变量 它给了我 abc 我怎样才能得到剩余的字符串 gg rrr ff 看来两者都不是str nor rdbuf 这
  • ”?' aria-label='如何修复“无法从方法组转换为 'Func”?'> 如何修复“无法从方法组转换为 'Func”?

    try var login ToServiceLogin lgParameters await Task Factory FromAsync loginOperation BeginLogin loginOperation EndLogin
  • 带有自定义图像的活动指示器

    I am loading a UIWebView and in the meantime I wan t to show a blank page with this activity indicator spinning siri act
  • 使用纯 JavaScript 获取元素的尺寸和位置[重复]

    这个问题在这里已经有答案了 情况 我想获取元素的尺寸和位置 Context 我正在制作一款纸牌游戏 卡片可以放置在板上 我需要能够检查他们的目的地是否在板上 然后我将存储它们相对于板的尺寸和位置的位置 这将有助于在可能使用不同屏幕尺寸的一群
  • 如何限制 Python 线程?

    我有一个线程执行大量 CPU 密集型处理 这似乎阻塞了其他线程 我该如何限制它 这是专门针对 web2py 的 但通用的解决方案就可以了 事实上 我不久前刚刚开始研究这个问题 你将无法更改线程优先级 但有一些方法可以解决这个问题 为了给您提
  • Google App Engine 中的 Memcache 1 MB 限制

    如何在 memcache 中存储大小大于 1 MB 的对象 有没有办法将其拆分 但仍然可以使用相同的密钥访问数据 我使用以下模块 blobcache 在 GAE 的内存缓存中存储大小大于 1Mb 的值 import pickle impor
  • 格式化目录中的所有 XML 文件并将它们保存在子目录中

    我正在尝试编写一个脚本来查看目录 找到所有 XML 文件 然后运行它们xmllint 并将格式化结果保存到名为的子目录中的同名文件中formatted 这是我到目前为止的脚本 find maxdepth 1 type f iname xml
  • Python:-mno -cygwin

    我正在尝试在 Windows 上学习大量 Python 其中包括安装多个软件包 但是每次我调用 python setup py install 时 我都会遇到 gcc 的 mno cygwin 问题 我已经阅读了很多文章 似乎他们希望这些单
  • R:取消列出为两列数据框(名称,值)

    我想从命名列表创建两列data frame 列表名称出现在第一列中 列表元素出现在第二列中 我设法做到了这一点 这完成了工作 但远非优雅 my list lt list one digit 0 9 two digits 10 29 thre
  • Netbeans 7.0 中的 SVN 1.7+

    我有一个使用totoiseSVN 的项目 在升级到 1 7 版本之前 一切正常 但是当我将 tortoiseSVN 升级到 1 7 版本时 当我尝试提交或显示历史日志或更新时 它会给我一个错误 org tigris subversion j
  • 使用 CAEmitterLayer 围绕圆或 CGPath 绘制粒子

    我正在尝试使用 iOS 5 的粒子系统 CAEmitterLayer 和 CAEmitterCell 围绕圆 或者更好的是 CGPath 绘制粒子 但我不知道该怎么做 我能做的最好的事情就是制作一个圆弧 通过修改 CAEmitterCell
  • MySQL 错误 1205:超出锁定等待超时

    我正在使用 SQLyog 将生产数据库同步到开发数据库 在 4 张桌子上 我得到 Error No 1205 Lock wait timeout exceeded try restarting transaction 研究网络似乎表明事务已
  • 获取 IntentService 中的地理定位上下文

    我正在创建一个 Android 类库 它调用内部 REST API 并且还利用需要 Context 的 Android 地理编码器类 特别是 getFromLocation 我计划将库设为 IntentService 以允许其异步运行 但我
  • Android - 获取当前时间而不依赖于设备时钟

    我注意到 System currentTimeMillis 时间取决于设备 如果我更改设备时钟上的时间 此方法将返回不同的答案 例如 如果现在的实时时间是 10 00 并且我将设备上的时钟更改为 9 30 则 System currentT
  • 如何在 dart/flutter 中继承静态方法?

    Dart Flutter 是否可以继承静态方法或工厂 或者我是否需要通过创建一个实例来访问该静态方法来解决这个问题 我的情况是 我想序列化一个对象 但需要访问它们的通用解析函数 abstract class Foo static Foo p
  • Android:带有毫秒的计时器?

    我想要的是以毫秒为单位测量时间 但是使用Chronometer有一个问题 它没有精度 它的最高分辨率是秒 我见过这个 使用 Android Chronometer 显示毫秒 https stackoverflow com questions
  • 将 IList> 转换为 List> 形式

    在以下代码中 response Values 返回 IList gt IList
  • 无法列出 *v1alpha1.Order:orders.certmanager.k8s.io 被禁止

    几个月前 我配置了自动 SSL 证书管理 如下所述 http docs cert manager io en latest tutorials acme dns validation html http docs cert manager
  • Ansible 中基于路径的参数的流程替换

    许多 Ansible 模块被设计为接受文件路径作为参数 但无法直接提供文件内容 如果输入数据实际上来自文件以外的其他内容 这会强制人们在磁盘上的某个位置创建一个临时文件 将预期的参数值写入其中 然后将该临时文件的路径提供给 Ansible