You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

关键改进说明

  1. 直接指定root路径:避免依赖ansible_env.HOME,become: yes切换到root后环境变量可能未正确更新,直接写死/root/.ssh/authorized_keys更可靠
  2. 使用lineinfile的insertbefore参数:这是实现“插入到指定行之前”的最优方式,blockinfile模块设计目标是插入带标记的代码块,不适合单行插入场景
  3. 修正when条件写法:when条件本身处于Jinja2上下文,直接使用变量名即可,无需额外添加{{ }},彻底解决警告问题
  4. 先检查注释存在性:通过check_mode: yes执行注释检查任务,不会修改文件,仅判断注释是否已存在;后续插入任务仅在注释已存在时执行
  5. 避免重复插入:lineinfile的state: present会自动检查目标密钥行是否已存在,无需额外校验

内容的提问来源于stack exchange,提问作者safesploit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:39:57