如何使用Ansible在指定注释行前插入SSH密钥?
问题需求
需要使用Ansible将SSH公钥插入root用户的authorized_keys文件中指定注释行(例如# service keys)之前。目标文件结构如下:
# sysadmin keys ssh-rsa AAAAB1...key_here... ssh-rsa AAAAB2...key_here... # <ansible_insert_public_key> # service keys ssh-rsa AAAAB9...key_here...
原尝试代码
--- - name: Add SSH public key to user's authorized_keys before the specified comment hosts: all become: yes vars: ssh_public_key: "ssh-rsa AAAAB3...key_here... comment" ssh_directory: "{{ ansible_env.HOME }}/.ssh" authorized_keys_path: "{{ ssh_directory }}/authorized_keys" insert_before_comment: "# service keys" tasks: - name: Ensure the .ssh directory exists for the user file: path: "{{ ssh_directory }}" state: directory mode: '0700' - name: Add SSH public key if not already present authorized_key: user: "{{ ansible_env.USER }}" state: present key: "{{ ssh_public_key }}" path: "{{ authorized_keys_path }}" manage_dir: yes - name: Read the authorized_keys file slurp: src: "{{ authorized_keys_path }}" register: authorized_keys_content - name: Set fact to check if the comment exists set_fact: insert_before_comment_exists: "{{ insert_before_comment in (authorized_keys_content.content | b64decode()) }}" - name: Modify authorized_keys file by inserting SSH key before the comment blockinfile: path: "{{ authorized_keys_path }}" marker: "# {{ insert_before_comment }}" content: | {{ ssh_public_key }} when: insert_before_comment_exists
遇到的问题
- SSH密钥被插入到
# service keys注释行之后,而非预期的之前 when条件中使用Jinja2模板分隔符({{ }})触发警告:条件语句不应包含Jinja2模板分隔符
解决方案
修正后的Playbook
--- - name: 在指定注释前插入SSH公钥到root用户的authorized_keys hosts: all become: yes vars: ssh_public_key: "ssh-rsa AAAAB3...key_here... comment" authorized_keys_path: "/root/.ssh/authorized_keys" insert_before_comment: "# service keys" tasks: - name: 确保root用户的.ssh目录存在 file: path: "/root/.ssh" state: directory mode: '0700' owner: root group: root - name: 检查目标注释是否存在于authorized_keys中 lineinfile: path: "{{ authorized_keys_path }}" line: "{{ insert_before_comment }}" state: present check_mode: yes register: comment_check_result - name: 在目标注释前插入SSH公钥(仅当注释已存在且密钥未重复) lineinfile: path: "{{ authorized_keys_path }}" line: "{{ ssh_public_key }}" insertbefore: "{{ insert_before_comment }}" state: present when: not comment_check_result.changed
关键改进说明
- 直接指定root路径:避免依赖
ansible_env.HOME,become: yes切换到root后环境变量可能未正确更新,直接写死/root/.ssh/authorized_keys更可靠 - 使用lineinfile的insertbefore参数:这是实现“插入到指定行之前”的最优方式,blockinfile模块设计目标是插入带标记的代码块,不适合单行插入场景
- 修正when条件写法:
when条件本身处于Jinja2上下文,直接使用变量名即可,无需额外添加{{ }},彻底解决警告问题 - 先检查注释存在性:通过
check_mode: yes执行注释检查任务,不会修改文件,仅判断注释是否已存在;后续插入任务仅在注释已存在时执行 - 避免重复插入:
lineinfile的state: present会自动检查目标密钥行是否已存在,无需额外校验
内容的提问来源于stack exchange,提问作者safesploit
相关产品推荐
相关产品推荐

