ansible - Ansible:在数组中查找字符串并从数组中返回字符串
问题描述
我正在编写一个剧本,它接受用户输入来确定目录中是否存在文件。
这是我到目前为止所拥有的
- name: Encrypt file
hosts: localhost
connection: local
vars:
working_directory: "{{ playbook_dir }}"
enc_files: []
my_file: shared_config
tasks:
- name: Get all Decrypted .yaml files
find:
paths: "{{ working_directory }}"
patterns: '*.yaml'
recurse: yes
excludes: "*.enc.yaml,decrypt.yaml,encrypt_all.yaml,encrypt_file.yaml"
register: files
- name: Add Decrypted files to Array
set_fact:
enc_files: "{{ enc_files + [item.path | basename] }}"
loop: "{{ files.files }}"
no_log: true
- debug:
msg: "{{ enc_files }}"
when: '"{{ my_file | lower }}" in "{{ enc_files | lower }}"'
我似乎无法开始工作的是,它会根据名称而不是扩展名查找文件是否存在。如果是这样,我想返回带有扩展名的文件来处理它。
这是我现在的树:
├── README.md
├── database
│ └── postgres_config.enc.yaml
├── decrypt.yaml
├── encrypt_all.yaml
├── encrypt_file.yaml
├── infra
│ ├── infra_config.enc.yaml
│ └── infra_config.yaml
├── middleware
│ ├── middleware_config.enc.yaml
│ └── middleware_config.yaml
├── services
│ ├── log_service_config.enc.yaml
│ ├── log_service_config.yaml
│
├── shared
│ ├── shared_config.enc.yaml
│ └── shared_config.yaml
我想要做的是让用户输入shared_config
或shared_config.yaml
返回shared_config.yaml
,以便我可以加密该文件。我也在试图找出一种方法,他们可以传递shared config
他们的输入(以及任何其他可能的输入,但我以后可以尝试自己弄清楚)。
解决方案
我想我不会以这种方式处理它(例如列出所有文件,然后查找用户输入是否与文件匹配)。
我可能宁愿以另一种方式处理它:获取用户的输入,然后assert
相应的文件确实存在。
然后,您只需使用 Jinja 过滤器和 Python 字符串操作来将用户输入转换为预期路径。
下面是一个建议的剧本,有好处也有陷阱。
优势:
- 它将与由空格分隔的多块路径一起使用
some path
将给出some/some_path.yaml
- 它应该足够健壮以纠正错误的多个空格:
some path
将给出some/some_path.yaml
- 它还接受下划线
some_path
会给some/some_path.yaml
- 它应该足够健壮以纠正错误的多个下划线:
some___path
将给出some/some_path.yaml
- 以及下划线和空格的混合
some path_here multispace___multiunderscore
将给出some/some_path_here_multispace_multiunderscore.yaml
- 它可以在用户输入中指定或不指定扩展名的情况下工作
- 它应该对横向路径攻击具有一定的弹性
陷阱:
- 但它不会处理最后一个单词和扩展名之间的空格,因为它会带来太多的下划线:
some path .yaml
会给some/some_path_.yaml
而且,所以,这里是所说的剧本:
- hosts: all
gather_facts: no
vars_prompt:
- name: file_name
prompt: Which decrypted file do you need?
private: no
pre_tasks:
- set_fact:
fqn: "{{ chunk.0 ~ '/' ~ chunk | join('_') if chunk | length > 1 else chunk | join('_') }}"
vars:
chunk: "{{ ((file if file.endswith('.yaml') else file ~ '.yaml') | replace('_',' ')).split() }}"
file: "{{ file_name | trim }}"
- assert:
that:
- fqn is file
- not fqn.startswith('.') # I am just trying to limit transversal path attack here
- not fqn.startswith('/') # I am just trying to limit transversal path attack here
- "'enc' != fqn.split('.')[-2]" # this one is a protection against accessing the encrypted files
msg: "{{ fqn }} is not a file"
tasks:
- debug:
msg: "Now, do whatever you like best with the file `{{ fqn | basename }}` at `{{ fqn }}` because I am sure it exists"
这是运行它的两个示例:
- 使用正确的用户输入:
Which decrypted file do you need?: middleware config PLAY [all] ********************************************************************* TASK [set_fact] **************************************************************** ok: [localhost] TASK [assert] ****************************************************************** ok: [localhost] => changed=false msg: All assertions passed TASK [debug] ******************************************************************* ok: [localhost] => msg: Now, do whatever you like best with the file `middleware_config.yaml` at `middleware/middleware_config.yaml` because I am sure it exists PLAY RECAP ********************************************************************* localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 用户输入错误:
Which decrypted file do you need?: middleware config PLAY [all] ********************************************************************* TASK [set_fact] **************************************************************** ok: [localhost] TASK [assert] ****************************************************************** fatal: [localhost]: FAILED! => changed=false assertion: fqn is file evaluated_to: false msg: fake/fake_config.yaml is not a file PLAY RECAP ********************************************************************* localhost : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
推荐阅读
- android - 使用 udpscr 时,Gstreamer 插件无法在 Android 上正确播放视频
- mysql - mysql。在更新触发器之前。如果记录不存在,我可以创建记录吗?
- swift - 如何使用swift过滤领域中的子列表对象?
- python - 如何获得模型的训练和验证准确度?
- google-cloud-platform - GCP:如何将模型转移到另一个项目
- c# - 如何使用动态对象类创建 .net 核心 MVC 模型?
- python - 抓取具有多个页面的网站的问题
- reactjs - auth0 通用重置密码页面,React
- php - 在 Laravel 中发送短信无法使用 Sinch
- typescript - Typescript 解析私有范围包的类型