注:由于本文中用到了playbook,所以建议您先看playbook篇
原文链接:点这里哦
ansible使用已有的权限升级系统,以root或其他用户的权限来执行任务。因为这个特性允许您“become”(成为)其他用户,与使用该用户登陆不一样,我们称之为become
。become关键字利用了当前已存在的权限工具比如sudo,su, pfexec,doas,pbrun,dzdo,ksu,runas,machinectl等。
您可以使用play、任务的链接、连接变量或者命令行来控制become。如果您使用了不同的方式设置了权限的升级,请您查看这个页面来了解被使用的设置。
您可以在 Plugin List中找到所有的ansible插件。
您可以在play或者task中看见become命令。您可以使用连接变量来覆盖这些变量,连接变量在不同主机之间通常是不同的。这些值和指令是独立的。比如,设置become_user
而不是become
。
become: yes
。默认值是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选项。您可以把这些变量定义在inventory中或者将它们当作普通变量来使用。
例如,如果您想要以root的身份在webserver服务器上运行所有的任务,但是您只能以manager用户的身份来登陆,您可以使用如下的清单:
webserver ansible_user=manager ansible_become=yes
上面定义的变量对所有的become插件都适用但也可以设置适用于特定插件的变量。有关某个插件中的选项和其使用方法,可以参照这个插件的文档。所有插件的文档都可以在Become Plugins找到。
即使权限升级都是很直观的,在执行上它仍有一些局限性。用户们应当认识并避免这些问题。
ansible模块通过改变模块文件来调整远程主机,然后把文件复制到远程主机,最后在远程主机上执行。
如果不使用become,那么一切都安好,当become_user为root或者与远程主机的连接是以root用户的身份执行的,ansible创建的模块文件只对于root用户和所使用的用户是可读的,或者只是对切换到的无权限的用户可读。
然而,如果connect_user和become_user都未被授权,这个模块文件将以ansible连接的用户的身份被写入,但是这个文件需要become_user可读。这种情况下,在ansible模块执行期间,ansible使这个模块文件全局可读(world-readable)。当模块执行完毕之后,ansible会删除这个临时文件。
如果传给模块的信息在现实中是敏感的,同时您并不信任这个客户端,这是就会有潜在的危险。
解决这个问题的方法:
即使 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的插件大部分都会警告。有些会直接忽略它,因为它们通常以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的间接访问。
对于使用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
。
更多相关内容可以查看这个页面
在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"
如果您希望在您所有的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模式的密码,您可以通过如下两种方式来指定它:
切忌密码不能放在明文文件中。要加密您的密码或者信息,请您查看使用ansible-vault加密内容
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以了解更多。
从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表示用户是否有管理员权限。返回的的标签以及他们所代表的意思:
NT AUTHORITY\System
用户,用户有着最高权限。输出也会显示用户被授予的权力。当权限变量的值为disabled
时,权限被分配给登入权限,但是这些权限并没有被激活。在大部分场景中这些权限都会被自动激活。
如果您的ansible版本在2.5之前或者runas进程失败,您也可以这样来升级token。
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
- 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的安全造成威胁,如果您做了这些事情,那请您务必当心。
在2.5版本之前,become只能在windows上的本地或者域用户上使用。在之前的版本上本地服务用户例如system或者networkservice不能被当作become_user。自从2.5版本之后就没了这种限制。在become_user下可以被设置为如下三个用户:
因为本地service用户没有密码,如果您设置了ansible_become_password参数,那么也是无用的。
在ansible2.8之后,become可以免密成为一个windows本地用户或者域用户。要启动这个特征,您必须满足下列要求:
become免密可以通过下面两种方法的任一种来实现:
在第一种情况下,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下设置您的用户密码。
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=
后记(全是我自己说的废话可以不看):这篇文章翻译下来真是够呛,翻译的也不好,希望有问题大家可以不吝赐教,十分感谢。