ansible官方文档翻译——become篇

注:由于本文中用到了playbook,所以建议您先看playbook篇
原文链接:点这里哦

理解权限的升级:become

ansible使用已有的权限升级系统,以root或其他用户的权限来执行任务。因为这个特性允许您“become”(成为)其他用户,与使用该用户登陆不一样,我们称之为become。become关键字利用了当前已存在的权限工具比如sudo,su, pfexec,doas,pbrun,dzdo,ksu,runas,machinectl等。

使用become

您可以使用play、任务的链接、连接变量或者命令行来控制become。如果您使用了不同的方式设置了权限的升级,请您查看这个页面来了解被使用的设置。
您可以在 Plugin List中找到所有的ansible插件。

become命令

您可以在play或者task中看见become命令。您可以使用连接变量来覆盖这些变量,连接变量在不同主机之间通常是不同的。这些值和指令是独立的。比如,设置become_user而不是become

  • become
    设置为yes来激活权限升级
  • become_user
    设置为某个您想要具有其权限的用户,不是那个您登陆的用户。需要设置become: yes。默认值是root。
  • become_method
    (在play或者task中)不使用ansible.cfg中的默认配置,设置为使用任意的become插件。
  • become_flag
    (在play或者task中)允许使用某个特定的task或者role。常用如当shell被设置为nologin时把用户变为nobody。
    例如,当以no-user连接时要管理一个系统服务(需要root权限),您可以使用become来使用root用户的权限:
- name: Ensure the httpd service is running
  service:
    name: httpd
    state: started
  become: yes

以用户apache的身份执行命令:

- name: Run a command as the apache user
  command: somecommand
  become: yes
  become_user: apache

当shell是nologin时执行某些命令:

- name: Run a command as nobody
  command: somecommand
  become: yes
  become_method: su
  become_user: nobody
  become_flags: '-s /bin/sh'

如果您没有配置sudo免密,那么在运行ansible-playbook时请加上--ask-become-pass(或-K)。如果您挂起的playbook中使用了become,那么有可能是因为权限的问题,请您ctrl+c强制终止ansible,然后加上-K命令和正确的密码来重新执行playbook。

become连接变量

您可以针对不同的受控节点或组定义不同的become选项。您可以把这些变量定义在inventory中或者将它们当作普通变量来使用。

  • ansible_become
    与become指令一样,决定是否升级权限。
  • ansible_become_method
    使用哪种权限升级方式。
  • ansible_become_user
    设置您升级权限后想要使用的用户,不意味着ansible_become: yes。
  • ansible_become_password
    设置升级权限的密码,查看Using encrypted variables and files了解如何处理文件中的私密东西。

例如,如果您想要以root的身份在webserver服务器上运行所有的任务,但是您只能以manager用户的身份来登陆,您可以使用如下的清单:

webserver ansible_user=manager ansible_become=yes

上面定义的变量对所有的become插件都适用但也可以设置适用于特定插件的变量。有关某个插件中的选项和其使用方法,可以参照这个插件的文档。所有插件的文档都可以在Become Plugins找到。

become命令行参数

  • –ask-become-pass, -K
    询问权限升级的密码,不代表become被使用,这个密码会被当作所有主机的密码。
  • –become,-b
    使用become执行操作(不会要求输入密码)
  • –become-method=BECOME_METHOD
    提升权限所使用的方法,默认为sudo,可选的选项: [ sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl ]
  • –become-user=BECOME-USER
    以某个用户的身份执行操作,不代表become被使用。

become的局限性与风险

即使权限升级都是很直观的,在执行上它仍有一些局限性。用户们应当认识并避免这些问题。

becoming为一个非授权用户的风险

ansible模块通过改变模块文件来调整远程主机,然后把文件复制到远程主机,最后在远程主机上执行。

如果不使用become,那么一切都安好,当become_user为root或者与远程主机的连接是以root用户的身份执行的,ansible创建的模块文件只对于root用户和所使用的用户是可读的,或者只是对切换到的无权限的用户可读。

然而,如果connect_user和become_user都未被授权,这个模块文件将以ansible连接的用户的身份被写入,但是这个文件需要become_user可读。这种情况下,在ansible模块执行期间,ansible使这个模块文件全局可读(world-readable)。当模块执行完毕之后,ansible会删除这个临时文件。

如果传给模块的信息在现实中是敏感的,同时您并不信任这个客户端,这是就会有潜在的危险。

解决这个问题的方法:

  • 使用管道。当管道开启时,ansible将不会把信息存在客户端的临时文件中。它会把信息传输到远程主机的python解释器标准输入中。如果python模块中包含文件传输或者没有python模块,管道将不会工作。
  • 在受控结点上安装POSIX.1e文件系统acl支持。如果远程主机上的临时文件是以 POSIX acls挂载且setfal工具在远程PATH中,ansible就会使用POSIX acls与第二个用户共用权限而不是使文件对于每个人都可读
  • 避免become为一个没有权限的用户。如果您become为root用户或者不用become,那么临时文件就会被UNIX文件权限保护,在ansible2.1及之前的版本,如果您以root用户的身份连接主机然后become为一个没有权限的用户,UNIX文件权限也一样是安全的。

即使 Solaris ZFS文件系统有文件系统ACL,但是他的ACL并不是POSIX.1e文件系统ACL(它们是NFSv4 ACLs)ansible无法用这种ACL管理它的临时文件,所以如果远程主机使用的是ZFS,那么您可能需要向allow_world_readable_tmpfiles求助

在2.1版本作出修改。

ansible使使用become且不自知变得更难了,从2.1开始,如果不能安全地执行become,那么ansible会报错。如果您不能使用管道或者POSIX ACLs,那您必须以一个不具权限的用户连接,您必须使用become才可以使用不同的不具权限的用户,同时您必须确定您的受控节点足够安全因为您想要在那里以任何人都可以执行的权限运行,您可以在ansible.cfg文件中打开allow_world_readable_tmpfiles选项。打开allow_world_readable_tmpfiles选项将会把这个error变为warning,然后程序会像2.1(版本)之前运行。

不是所有插件都支持become

使用的模块必须支持权限升级。不支持become的插件大部分都会警告。有些会直接忽略它,因为它们通常以root身份运行。

每个主机可能都只开启一个方法

方法是不能被连接的。您可以使用sudo /bin/su -become为一个用户,这个用户必须有sudo或su权限(pbrun, pfexec或者其它的可支持的方法也可以)。

权限升级必须常规

您不能对于某个命令限制其权限。ansible不是用特定的命令去执行而是从一个每次都会改变名称的临时文件中运行模块(代码)。如果您把/sbin/service或/bin/chmod作为命令,那ansible将会执行错误,因为那与ansible创建的用于运行模块的临时文件的路径不匹配。如果您有安全策略使ansible使您使用 sudo/pbrun/doas命令时必须使用特定的路径,请您使用一个不具有这种策略的ansible用户。或者您也可以使用 Red Hat Ansible Tower来管理ssh的间接访问。

可能无法访问由pamd_systemd填充的环境变量

对于使用systemd初始化的linux,systemd默认不会新开一个会话,因为pam_systemd模块不会新开一个完整的会话,与平常使用ssh打开会话相比您可能会感到吃惊:有些环境变量是由pam_systemd来设置的,大部分的XDG_RUNTIME_DIR不会被新用户填充,而是被继承或者清空。
使用XDG_RUNTIME_DIR的systemd访问总线时可能会遇到问题:

$ echo $XDG_RUNTIME_DIR

$ systemctl --user status
Failed to connect to bus: Permission denied

如果您想要强制使become通过pam_systemd打开一个新的systemd会话,您可以使用becocme_method: mechinectl
更多相关内容可以查看这个页面

become与网络自动化

在2.6版本,ansible在所有支持enable模式的所有ansible管理平台上支持become升级权限(输入enable模式或者权限执行模式)使用become替换provider字典中的authorize和auth_pass选项。

在网络设备中您必须色只ansible.netcommon.network_cli或者ansible.netcommon.httpapi作为连接方式,这样您才可以成功地升级权限。查看这个页面获取详细信息。

您只能在需要升级权限的特定任务中使用权限升级,也许是一个play中,也许是所有的play中。添加、become: yes和become_method: enable来使ansible在执行设定这些参数的任务与play或者playbook 时开启enable模式。

如果您看到这个报错信息,那就代表这个任务需要enable模式来继续:

Invalid input (privileged mode required)

如果您想要在某个任务中启动enable模式,那么您需要在task选项中添加become:

- name: Gather facts (eos)
  arista.eos.eos_facts:
    gather_subset:
      - "!hardware"
  become: yes
  become_method: enable

如果您想要在一个play中启动enable模式,那么请您在play选项中添加become:

 - hosts: eos-switches
  become: yes
  become_method: enable
  tasks:
    - name: Gather facts (eos)
      arista.eos.eos_facts:
        gather_subset:
          - "!hardware"

为所有的任务都设置enable选项

如果您希望在您所有的task和play中都使用权限的升级,那么您最好使用group_vars:
group_vars/eos.yml

ansible_connection: ansible.netcommon.network_cli
ansible_network_os: arista.eos.eos
ansible_user: myuser
ansible_become: yes
ansible_become_method: enable

enable模式的密码

如果您需要一个enable模式的密码,您可以通过如下两种方式来指定它:

  • 在命令行下加上–ask-become-pass选项
  • 在公共变量中设置ansible_become_password

切忌密码不能放在明文文件中。要加密您的密码或者信息,请您查看使用ansible-vault加密内容

authorize与auth_pass

ansible也支持带有connection: local的传统网络playbook的enable模式。如果您想要进入带有connection: local的enable模式,那么请使用authorize与auth_pass选项:

- hosts: eos-switches
  ansible_connection: local
  tasks:
    - name: Gather facts (eos)
      eos_facts:
        gather_subset:
          - "!hardware"
      provider:
        authorize: yes
        auth_pass: " {
     { secret_auth_pass }}"

我们推荐您在网络设备中保持become开启。这种使用authorize和provider的方式在未来将被淘汰。查看plantform options和network module以了解更多。

windows上的become

从2.3版本开始,使用runas方法就可以使become用于windows。在非windows上使用相同的inventory设置和调用参数在windows上become,它的设置和变量名与本文都一致。

become用来认证为别的用户,windows也是多用户的。一个重要的使用方法就是在windows上执行时绕过那些限制,比如网络限制或者访问那些如WUA API的系统。您可以become为一个和ansible_user相同的用户来绕过这些限制或者执行一些所有用户都有权限的命令。

管理员权限

windows中许多任务都需要管理员权限才能完成。这种权限默认被分配给管理员,如果debug权限不够,那么become将会以一个受限的权限和组来执行。

如果您想要确认ansible得到的token类型,请您执行下列任务:

- Check my user name
  ansible.windows.win_whoami:
  become: yes

它的输出应该如下所示:

ok: [windows] => {
     
    "account": {
     
        "account_name": "vagrant-domain",
        "domain_name": "DOMAIN",
        "sid": "S-1-5-21-3088887838-4058132883-1884671576-1105",
        "type": "User"
    },
    "authentication_package": "Kerberos",
    "changed": false,
    "dns_domain_name": "DOMAIN.LOCAL",
    "groups": [
        {
     
            "account_name": "Administrators",
            "attributes": [
                "Mandatory",
                "Enabled by default",
                "Enabled",
                "Owner"
            ],
            "domain_name": "BUILTIN",
            "sid": "S-1-5-32-544",
            "type": "Alias"
        },
        {
     
            "account_name": "INTERACTIVE",
            "attributes": [
                "Mandatory",
                "Enabled by default",
                "Enabled"
            ],
            "domain_name": "NT AUTHORITY",
            "sid": "S-1-5-4",
            "type": "WellKnownGroup"
        },
    ],
    "impersonation_level": "SecurityAnonymous",
    "label": {
     
        "account_name": "High Mandatory Level",
        "domain_name": "Mandatory Label",
        "sid": "S-1-16-12288",
        "type": "Label"
    },
    "login_domain": "DOMAIN",
    "login_time": "2018-11-18T20:35:01.9696884+00:00",
    "logon_id": 114196830,
    "logon_server": "DC01",
    "logon_type": "Interactive",
    "privileges": {
     
        "SeBackupPrivilege": "disabled",
        "SeChangeNotifyPrivilege": "enabled-by-default",
        "SeCreateGlobalPrivilege": "enabled-by-default",
        "SeCreatePagefilePrivilege": "disabled",
        "SeCreateSymbolicLinkPrivilege": "disabled",
        "SeDebugPrivilege": "enabled",
        "SeDelegateSessionUserImpersonatePrivilege": "disabled",
        "SeImpersonatePrivilege": "enabled-by-default",
        "SeIncreaseBasePriorityPrivilege": "disabled",
        "SeIncreaseQuotaPrivilege": "disabled",
        "SeIncreaseWorkingSetPrivilege": "disabled",
        "SeLoadDriverPrivilege": "disabled",
        "SeManageVolumePrivilege": "disabled",
        "SeProfileSingleProcessPrivilege": "disabled",
        "SeRemoteShutdownPrivilege": "disabled",
        "SeRestorePrivilege": "disabled",
        "SeSecurityPrivilege": "disabled",
        "SeShutdownPrivilege": "disabled",
        "SeSystemEnvironmentPrivilege": "disabled",
        "SeSystemProfilePrivilege": "disabled",
        "SeSystemtimePrivilege": "disabled",
        "SeTakeOwnershipPrivilege": "disabled",
        "SeTimeZonePrivilege": "disabled",
        "SeUndockPrivilege": "disabled"
    },
    "rights": [
        "SeNetworkLogonRight",
        "SeBatchLogonRight",
        "SeInteractiveLogonRight",
        "SeRemoteInteractiveLogonRight"
    ],
    "token_type": "TokenPrimary",
    "upn": "[email protected]",
    "user_flags": []
}

在label关键字中,account_name表示用户是否有管理员权限。返回的的标签以及他们所代表的意思:

  • Medium:ansible没有得到升级的token,将会在一个受限的token下运行。在执行任务的时候,用户只有一个权限的子集,他没有管理员权限。
  • High:在执行任务的时候,用户有一个升级的tocken,同时拥有这个用户的所有的权限。
  • System:表示使用的是NT AUTHORITY\System用户,用户有着最高权限。

输出也会显示用户被授予的权力。当权限变量的值为disabled时,权限被分配给登入权限,但是这些权限并没有被激活。在大部分场景中这些权限都会被自动激活。

如果您的ansible版本在2.5之前或者runas进程失败,您也可以这样来升级token。

  • 设置become_user和System为具有完全的权限的用户。
  • 在winRM上为连接至ansible的用户授予SeTcbPrivilege权限。SeTcbPrivilege是授予对操作系统完全的掌控权。默认情况下没有被授予这个权限的用户,如果您授予了某个用户或某个组这个权限,那么请您一定要谨慎行事,更多有关这个权限的内容,请移步: Act as part of the operating system。在windows主机上您可以使用如下任务来设置这个权限:
- name: grant the ansible user the SeTcbPrivilege right
  ansible.windows.win_user_right:
    name: SeTcbPrivilege
    users: '{
     {ansible_user}}'
    action: add
  • 在become之前,请您检查主机上的UAC是否关闭。UAC是使用户运行在最小权限下的安全策略。您可以使用如下task来关闭UAC:
- name: turn UAC off
  win_regedit:
    path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system
    name: EnableLUA
    data: 0
    type: dword
    state: present
  register: uac_result

- name: reboot after disabling UAC
  win_reboot:
  when: uac_result is changed

授予SeTcbPrivilege权限或者关闭UAC会对windows的安全造成威胁,如果您做了这些事情,那请您务必当心。

本地service用户

在2.5版本之前,become只能在windows上的本地或者域用户上使用。在之前的版本上本地服务用户例如system或者networkservice不能被当作become_user。自从2.5版本之后就没了这种限制。在become_user下可以被设置为如下三个用户:

  • system
  • networkservice
  • localservice

因为本地service用户没有密码,如果您设置了ansible_become_password参数,那么也是无用的。

become免密

在ansible2.8之后,become可以免密成为一个windows本地用户或者域用户。要启动这个特征,您必须满足下列要求:

  • 连接用户必须有SeDebugPrivilege权限
  • 连接用户必须在BUILTIN\Administrators用户组内
  • become_user拥有SeBatchLogonRight或SeNetworkLogonRight权限

become免密可以通过下面两种方法的任一种来实现:

  • 复制一个已经存在会话且已经注册的用户的token
  • 用S4U生成一个仅在远程主机上生效的token

在第一种情况下,become进程是借助别的用户的身份登陆。这种方法必须要有一个已经登陆的会话,但是它不太稳定。这与一个计划任务的只在用户登陆的情况下运行选项一样。

在第二种情况下,S4U用来创建一个新的登陆并且通过它运行模块。这与无论用户是否登陆都执行或者不存储密码选项相似。这种情况下,become进程无法像普通WinRM进程一样管理网络。

为了区别become免密与become为一个没有密码的用户,请您不要定义或者设置ansible_become_password。

由于ansible运行时不能保证有一个已存在的token,那么become进程就只能访问本地资源。如果您执行的任务需要访问网络资源,那么请您使用带有密码的become。

无密码的用户

[ warning] 一般情况下,为了安全起见,您应当避免存在无密码的用户。

ansible可以become为一个无密码的windows用户(如guest用户)。如果您想要become为一个无密码的用户,请您设置将ansible_become_password参数设置为ansible_become_password: ''

在执行这种become指令之前,您需要禁用您的本地策略 Accounts: Limit local account use of blank passwords to console logon only。您可以通过设置组策略对象(GPO)或者执行下列ansible任务来实现上述内容:

- name: allow blank password on become
  ansible.windows.win_regedit:
    path: HKLM:\SYSTEM\CurrentControlSet\Control\Lsa
    name: LimitBlankPasswordUse
    data: 0
    type: dword
    state: present

注意:这只是对无需密码的用户而言的,如果您的become_user有密码,那您仍然需要在ansible_become_password下设置您的用户密码。

windows下的become标识

ansible2.5为runas方法添加了become_flags参数。您可以直接使用become_flags或者在ansible配置文件中设置ansible_become_flags。这个参数最先支持的两个参数有logon_type和logon_flags。

只有在become为一个普通用户时才可以设置这些参数,而不是例如localsystem的本地service用户。

logon_type参数设置了平台的登陆类型,它可以被设置为以下值之一:

  • interactive:默认的登陆类型,进程将在一个与在本地运行相同的情境下运行。它避免了所有WinRM的限制,因此是我们推荐使用的方法。
  • batch:在类似于已设置密码的计划任务的批处理上下文中运行流程。这样可以绕过大多数的WinRM限制。在become_user不能交互地登陆的情况下很有用。
  • new_credentials:与调用用户在同一证书下运行,与runas.exe /netonly相似,外部连接在有become_user和become_password下才可以运行。logon_flags标签也应该被设置为netcredentials_only。如果进程需要使用不同的证书访问网络资源,那么请您使用这个标签。
  • network:在没有缓存证书的网络环境下运行进程。这种情况下会话将会运行在一个没有证书授权的情况下运行一个普通的进程,也会有相应的限制。
  • network_cleartext:与network登陆方式类似,但它可以缓存证书,因此它可以访问网路资源。它与正常情况下运行一个WinRM进程相似。

如果您想要了解更多,那么请您移步这里:dwLogonType。

logon_flags指定了当创建新的进程时windows将会以那种方式登陆。这个值可以为none或者以下任意一个值。

  • with_profile:默认的flag,进程将会把HKEY_USERS中的配置文件加载到HKEY_CURRENT_USER中。
  • netcredentials_only:进程将会使用与调用者相同的tocken但是使用become_user和become_password访问远程资源。这在不信任的域间方案中很有用,同时要与new_credentials和logon_type同时使用。

默认情况下采用logon_flags=with_profile,如果您不想加载配置文件,那么请使用logon_flags=。如果您想要使用netcredentials_only加载配置文件,请使用logon_flags=with_profile,netcredentials_only

如果您想要了解更多,那么请您移步这里:dwLogonType。

下面有一个在windows任务中使用become_flags的小例子:

- name: copy a file from a fileshare with custom credentials
  ansible.windows.win_copy:
    src: \\server\share\data\file.txt
    dest: C:\temp\file.txt
    remote_src: yes
  vars:
    ansible_become: yes
    ansible_become_method: runas
    ansible_become_user: DOMAIN\user
    ansible_become_password: Password01
    ansible_become_flags: logon_type=new_credentials logon_flags=netcredentials_only

- name: run a command under a batch logon
  ansible.windows.win_whoami:
  become: yes
  become_flags: logon_type=batch

- name: run a command and not load the user profile
  ansible.windows.win_whomai:
  become: yes
  become_flags: logon_flags=

在windows上使用become的限制

  • 如果您想要在windows2008、2008 R2或者windows7上运行任务,那么您需要使用ansible2.7之后的版本
  • 默认情况下,bocome用户使用交互式的会话登陆,所以它必须具有在windows上执行某些任务的权限。如果无法继承SeAllowLogOnLocally或者SeDenyLogOnLocally权限,那么become进程将会失败。如果遇到这种情况,那么请您设置logon_type或者增加权限。
  • 在ansible2.3之前,只有在ansible_winrm_transport为basic或者credssp时become才会起作用。在2.4版本之后对于除了Windows Server 2008(不包括R2版本)的所有主机,就没有这种限制了。
  • 辅助登陆程序seclogon必须在ansible_become_method: runas运行时才可以使用。

后记(全是我自己说的废话可以不看):这篇文章翻译下来真是够呛,翻译的也不好,希望有问题大家可以不吝赐教,十分感谢。

你可能感兴趣的:(ansible官方文档翻译,ansible)