首页 > 解决方案 > 使用 Ansible 的文件模块时如何防止 ToCToU 问题?

问题描述

我的工作环境:

我正在编写一个 Ansible 剧本,其中包含一个任务,该任务创建一个指向其他地方的目录的符号链接。任务使用file模块(为了讨论方便,我简化了代码):

- name: Link the app configuration.
  file:
    path: "/home/username/appConfig.lnk"
    src: "/usr/share/app_name/appConfig"
    state: link
    force: no
  become: no

如果任务执行成功,/home/username/appConfig.lnk则会创建一个符号链接并指向目录/usr/share/app_name/appConfiig

但是,在实际用例中,用户可能会修改appConfig.lnk以指向其他内容,即适合他们需要的自定义配置。这在我们的使用中是预期和有效/usr/share/app_name/appConfig的,并且唯一尝试提供可用的初始配置。

因此,我希望剧本任务仅appConfig.lnk在它根本存在时创建。如果路径/home/username/appConfig.lnk已经存在,无论它是指向默认配置的符号链接、指向其他一些自定义配置、文件或目录的符号链接,我都想跳过创建。

但是,设置为的file模块的行为如下:forceno

为了解决这个问题,我之前添加了一个任务来调用stat模块

- name: Get the app configuration status.
  stat:
    path: "/home/username/appConfig.lnk"
  register: stat_config
  become: no

- name: Link the app configuration.
  when: not stat_config.stat.exists  # <-- New condition
  file:
    path: "/home/username/appConfig.lnk"
    src: "/usr/share/app_name/appConfig"
    state: link
    force: no
  become: no

但我认为这会引入ToCToU 问题,因为尽管不太可能,但可能会在调用appConfig.lnk后立即删除,因此模块被跳过,我最终得到一个系统,显示一切都已成功完成,但未创建链接。statfile

所以我想知道是否有办法实现我想要的但避免可能的 ToCToU 问题。

标签: ansibletocttou

解决方案


一种选择是使用“命令创建”结构。

- name: Create link
  command: ln -s /usr/share/app_name/appConfig /home/username/appConfig.lnk
  args:
    creates: /home/username/appConfig.lnk

关于命令模块的讨论在这里


推荐阅读