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_configshared_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   
    

最新更新