File: //usr/lib/python3.9/site-packages/ansible/modules/__pycache__/user.cpython-39.pyc
a
�)g�� � @ s@ d dl mZmZmZ eZdZdZdZd dl Z d dl
Z d dlZd dlZd dl
Z
d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZmZmZ d dlmZ d d l m!Z! d d
l"m#Z# d dl$m% m& m'Z( G dd� de j)�Z*z>e j+�,e(�-e.e j/�0d
���Z1e j2fe1j3_4e �5e*�e1j3_6dZ7W n e8�y` dZ7Y n0 e�9d�Z:dd� Z3G dd� de;�Z<G dd� de<�Z=G dd� de=�Z>G dd� de<�Z?G dd� de<�Z@G dd� de<�ZAG dd � d e<�ZBG d!d"� d"e<�ZCG d#d$� d$e<�ZDG d%d&� d&e<�ZEG d'd(� d(eE�ZFd)d*� ZGeHd+k�r<eG� dS ),� )�absolute_import�division�print_functiona20
module: user
version_added: "0.2"
short_description: Manage user accounts
description:
- Manage user accounts and user attributes.
- For Windows targets, use the M(ansible.windows.win_user) module instead.
options:
name:
description:
- Name of the user to create, remove or modify.
type: str
required: true
aliases: [ user ]
uid:
description:
- Optionally sets the I(UID) of the user.
type: int
comment:
description:
- Optionally sets the description (aka I(GECOS)) of user account.
type: str
hidden:
description:
- macOS only, optionally hide the user from the login window and system preferences.
- The default will be C(true) if the I(system) option is used.
type: bool
version_added: "2.6"
non_unique:
description:
- Optionally when used with the -u option, this option allows to change the user ID to a non-unique value.
type: bool
default: no
version_added: "1.1"
seuser:
description:
- Optionally sets the seuser type (user_u) on selinux enabled systems.
type: str
version_added: "2.1"
group:
description:
- Optionally sets the user's primary group (takes a group name).
type: str
groups:
description:
- List of groups user will be added to.
- By default, the user is removed from all other groups. Configure C(append) to modify this.
- When set to an empty string C(''),
the user is removed from all groups except the primary group.
- Before Ansible 2.3, the only input format allowed was a comma separated string.
type: list
elements: str
append:
description:
- If C(true), add the user to the groups specified in C(groups).
- If C(false), user will only be added to the groups specified in C(groups),
removing them from all other groups.
type: bool
default: no
shell:
description:
- Optionally set the user's shell.
- On macOS, before Ansible 2.5, the default shell for non-system users was C(/usr/bin/false).
Since Ansible 2.5, the default shell for non-system users on macOS is C(/bin/bash).
- See notes for details on how other operating systems determine the default shell by
the underlying tool.
type: str
home:
description:
- Optionally set the user's home directory.
type: path
skeleton:
description:
- Optionally set a home skeleton directory.
- Requires C(create_home) option!
type: str
version_added: "2.0"
password:
description:
- If provided, set the user's password to the provided encrypted hash (Linux) or plain text password (macOS).
- B(Linux/Unix/POSIX:) Enter the hashed password as the value.
- See L(FAQ entry,https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module)
for details on various ways to generate the hash of a password.
- To create an account with a locked/disabled password on Linux systems, set this to C('!') or C('*').
- To create an account with a locked/disabled password on OpenBSD, set this to C('*************').
- B(OS X/macOS:) Enter the cleartext password as the value. Be sure to take relevant security precautions.
type: str
state:
description:
- Whether the account should exist or not, taking action if the state is different from what is stated.
type: str
choices: [ absent, present ]
default: present
create_home:
description:
- Unless set to C(false), a home directory will be made for the user
when the account is created or if the home directory does not exist.
- Changed from C(createhome) to C(create_home) in Ansible 2.5.
type: bool
default: yes
aliases: [ createhome ]
move_home:
description:
- "If set to C(true) when used with C(home: ), attempt to move the user's old home
directory to the specified directory if it isn't there already and the old home exists."
type: bool
default: no
system:
description:
- When creating an account C(state=present), setting this to C(true) makes the user a system account.
- This setting cannot be changed on existing users.
type: bool
default: no
force:
description:
- This only affects C(state=absent), it forces removal of the user and associated directories on supported platforms.
- The behavior is the same as C(userdel --force), check the man page for C(userdel) on your system for details and support.
- When used with C(generate_ssh_key=yes) this forces an existing key to be overwritten.
type: bool
default: no
remove:
description:
- This only affects C(state=absent), it attempts to remove directories associated with the user.
- The behavior is the same as C(userdel --remove), check the man page for details and support.
type: bool
default: no
login_class:
description:
- Optionally sets the user's login class, a feature of most BSD OSs.
type: str
generate_ssh_key:
description:
- Whether to generate a SSH key for the user in question.
- This will B(not) overwrite an existing SSH key unless used with C(force=yes).
type: bool
default: no
version_added: "0.9"
ssh_key_bits:
description:
- Optionally specify number of bits in SSH key to create.
- The default value depends on ssh-keygen.
type: int
version_added: "0.9"
ssh_key_type:
description:
- Optionally specify the type of SSH key to generate.
- Available SSH key types will depend on implementation
present on target host.
type: str
default: rsa
version_added: "0.9"
ssh_key_file:
description:
- Optionally specify the SSH key filename.
- If this is a relative filename then it will be relative to the user's home directory.
- This parameter defaults to I(.ssh/id_rsa).
type: path
version_added: "0.9"
ssh_key_comment:
description:
- Optionally define the comment for the SSH key.
type: str
default: ansible-generated on $HOSTNAME
version_added: "0.9"
ssh_key_passphrase:
description:
- Set a passphrase for the SSH key.
- If no passphrase is provided, the SSH key will default to having no passphrase.
type: str
version_added: "0.9"
update_password:
description:
- C(always) will update passwords if they differ.
- C(on_create) will only set the password for newly created users.
type: str
choices: [ always, on_create ]
default: always
version_added: "1.3"
expires:
description:
- An expiry time for the user in epoch, it will be ignored on platforms that do not support this.
- Currently supported on GNU/Linux, FreeBSD, and DragonFlyBSD.
- Since Ansible 2.6 you can remove the expiry time by specifying a negative value.
Currently supported on GNU/Linux and FreeBSD.
type: float
version_added: "1.9"
password_lock:
description:
- Lock the password (C(usermod -L), C(usermod -U), C(pw lock)).
- Implementation differs by platform. This option does not always mean the user cannot login using other methods.
- This option does not disable the user, only lock the password.
- This must be set to C(False) in order to unlock a currently locked password. The absence of this parameter will not unlock a password.
- Currently supported on Linux, FreeBSD, DragonFlyBSD, NetBSD, OpenBSD.
type: bool
version_added: "2.6"
local:
description:
- Forces the use of "local" command alternatives on platforms that implement it.
- This is useful in environments that use centralized authentication when you want to manipulate the local users
(in other words, it uses C(luseradd) instead of C(useradd)).
- This will check C(/etc/passwd) for an existing account before invoking commands. If the local account database
exists somewhere other than C(/etc/passwd), this setting will not work properly.
- This requires that the above commands as well as C(/etc/passwd) must exist on the target host, otherwise it will be a fatal error.
type: bool
default: no
version_added: "2.4"
profile:
description:
- Sets the profile of the user.
- Does nothing when used with other platforms.
- Can set multiple profiles using comma separation.
- To delete all the profiles, use C(profile='').
- Currently supported on Illumos/Solaris.
type: str
version_added: "2.8"
authorization:
description:
- Sets the authorization of the user.
- Does nothing when used with other platforms.
- Can set multiple authorizations using comma separation.
- To delete all authorizations, use C(authorization='').
- Currently supported on Illumos/Solaris.
type: str
version_added: "2.8"
role:
description:
- Sets the role of the user.
- Does nothing when used with other platforms.
- Can set multiple roles using comma separation.
- To delete all roles, use C(role='').
- Currently supported on Illumos/Solaris.
type: str
version_added: "2.8"
password_expire_max:
description:
- Maximum number of days between password change.
- Supported on Linux only.
type: int
version_added: "2.11"
password_expire_min:
description:
- Minimum number of days between password change.
- Supported on Linux only.
type: int
version_added: "2.11"
umask:
description:
- Sets the umask of the user.
- Does nothing when used with other platforms.
- Currently supported on Linux.
- Requires C(local) is omitted or False.
type: str
version_added: "2.12"
extends_documentation_fragment: action_common_attributes
attributes:
check_mode:
support: full
diff_mode:
support: none
platform:
platforms: posix
notes:
- There are specific requirements per platform on user management utilities. However
they generally come pre-installed with the system and Ansible will require they
are present at runtime. If they are not, a descriptive error message will be shown.
- On SunOS platforms, the shadow file is backed up automatically since this module edits it directly.
On other platforms, the shadow file is backed up by the underlying tools used by this module.
- On macOS, this module uses C(dscl) to create, modify, and delete accounts. C(dseditgroup) is used to
modify group membership. Accounts are hidden from the login window by modifying
C(/Library/Preferences/com.apple.loginwindow.plist).
- On FreeBSD, this module uses C(pw useradd) and C(chpass) to create, C(pw usermod) and C(chpass) to modify,
C(pw userdel) remove, C(pw lock) to lock, and C(pw unlock) to unlock accounts.
- On all other platforms, this module uses C(useradd) to create, C(usermod) to modify, and
C(userdel) to remove accounts.
seealso:
- module: ansible.posix.authorized_key
- module: ansible.builtin.group
- module: ansible.windows.win_user
author:
- Stephen Fromm (@sfromm)
a�
- name: Add the user 'johnd' with a specific uid and a primary group of 'admin'
ansible.builtin.user:
name: johnd
comment: John Doe
uid: 1040
group: admin
- name: Add the user 'james' with a bash shell, appending the group 'admins' and 'developers' to the user's groups
ansible.builtin.user:
name: james
shell: /bin/bash
groups: admins,developers
append: yes
- name: Remove the user 'johnd'
ansible.builtin.user:
name: johnd
state: absent
remove: yes
- name: Create a 2048-bit SSH key for user jsmith in ~jsmith/.ssh/id_rsa
ansible.builtin.user:
name: jsmith
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa
- name: Added a consultant whose account you want to expire
ansible.builtin.user:
name: james18
shell: /bin/zsh
groups: developers
expires: 1422403387
- name: Starting at Ansible 2.6, modify user, remove expiry time
ansible.builtin.user:
name: james18
expires: -1
- name: Set maximum expiration date for password
ansible.builtin.user:
name: ram19
password_expire_max: 10
- name: Set minimum expiration date for password
ansible.builtin.user:
name: pushkar15
password_expire_min: 5
a�
append:
description: Whether or not to append the user to groups.
returned: When state is C(present) and the user exists
type: bool
sample: True
comment:
description: Comment section from passwd file, usually the user name.
returned: When user exists
type: str
sample: Agent Smith
create_home:
description: Whether or not to create the home directory.
returned: When user does not exist and not check mode
type: bool
sample: True
force:
description: Whether or not a user account was forcibly deleted.
returned: When I(state) is C(absent) and user exists
type: bool
sample: False
group:
description: Primary user group ID
returned: When user exists
type: int
sample: 1001
groups:
description: List of groups of which the user is a member.
returned: When I(groups) is not empty and I(state) is C(present)
type: str
sample: 'chrony,apache'
home:
description: "Path to user's home directory."
returned: When I(state) is C(present)
type: str
sample: '/home/asmith'
move_home:
description: Whether or not to move an existing home directory.
returned: When I(state) is C(present) and user exists
type: bool
sample: False
name:
description: User account name.
returned: always
type: str
sample: asmith
password:
description: Masked value of the password.
returned: When I(state) is C(present) and I(password) is not empty
type: str
sample: 'NOT_LOGGING_PASSWORD'
remove:
description: Whether or not to remove the user account.
returned: When I(state) is C(absent) and user exists
type: bool
sample: True
shell:
description: User login shell.
returned: When I(state) is C(present)
type: str
sample: '/bin/bash'
ssh_fingerprint:
description: Fingerprint of generated SSH key.
returned: When I(generate_ssh_key) is C(True)
type: str
sample: '2048 SHA256:aYNHYcyVm87Igh0IMEDMbvW0QDlRQfE0aJugp684ko8 ansible-generated on host (RSA)'
ssh_key_file:
description: Path to generated SSH private key file.
returned: When I(generate_ssh_key) is C(True)
type: str
sample: /home/asmith/.ssh/id_rsa
ssh_public_key:
description: Generated SSH public key file.
returned: When I(generate_ssh_key) is C(True)
type: str
sample: >
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC95opt4SPEC06tOYsJQJIuN23BbLMGmYo8ysVZQc4h2DZE9ugbjWWGS1/pweUGjVstgzMkBEeBCByaEf/RJKNecKRPeGd2Bw9DCj/bn5Z6rGfNENKBmo
618mUJBvdlEgea96QGjOwSB7/gmonduC7gsWDMNcOdSE3wJMTim4lddiBx4RgC9yXsJ6Tkz9BHD73MXPpT5ETnse+A3fw3IGVSjaueVnlUyUmOBf7fzmZbhlFVXf2Zi2rFTXqvbdGHKkzpw1U8eB8xFPP7y
d5u1u0e6Acju/8aZ/l17IDFiLke5IzlqIMRTEbDwLNeO84YQKWTm9fODHzhYe0yvxqLiK07 ansible-generated on host'
stderr:
description: Standard error from running commands.
returned: When stderr is returned by a command that is run
type: str
sample: Group wheels does not exist
stdout:
description: Standard output from running commands.
returned: When standard output is returned by the command that is run
type: str
sample:
system:
description: Whether or not the account is a system account.
returned: When I(system) is passed to the module and the account does not exist
type: bool
sample: True
uid:
description: User ID of the user account.
returned: When I(uid) is passed to the module
type: int
sample: 1044
password_expire_max:
description: Maximum number of days during which a password is valid.
returned: When user exists
type: int
sample: 20
password_expire_min:
description: Minimum number of days between password change
returned: When user exists
type: int
sample: 20
N)�distro)�to_bytes� to_native�to_text)�
AnsibleModule)�get_best_parsable_locale)�get_platform_subclassc
@ sX e Zd Zdejfdejfdejfdejfdejfdejfdejfdejfd ejfg Zd
S )�StructSpwdTypeZsp_namp�sp_pwdpZ sp_lstchg�sp_min�sp_maxZsp_warnZsp_inact� sp_expireZsp_flagN)�__name__�
__module__�__qualname__�ctypes�c_char_pZc_longZc_ulongZ_fields_� r r �8/usr/lib/python3.9/site-packages/ansible/modules/user.pyr � s �r �cTFz[^a-zA-Z0-9./=]c C s t �| �jS �N)�_LIBC�getspnam�contents)�b_namer r r r � s r c s e Zd ZdZdZdZdZdZdZdZ dZ
� fd d
�Zdd� Zd
d� Z
dCdd�Zdd� Zdd� Zdd� Zdd� Zdd� Zdd� Zdd � ZdDd!d"�ZdEd#d$�Zd%d&� Zd'd(� Zd)d*� Zd+d,� Zd-d.� Zd/d0� Zd1d2� Zd3d4� Zd5d6� Z d7d8� Z!d9d:� Z"d;d<� Z#d=d>� Z$d?d@� Z%dAdB� Z&� Z'S )F�Usera|
This is a generic User manipulation class that is subclassed
based on platform.
A subclass may wish to override the following action methods:-
- create_user()
- remove_user()
- modify_user()
- ssh_key_gen()
- ssh_key_fingerprint()
- user_exists()
All subclasses MUST define platform and distribution (which may be None).
�GenericNz/etc/passwd�/etc/shadow� z/etc/login.defsz%Y-%m-%dc s t t�}t| |��|�S r )r r �super�__new__)�cls�args�kwargsZnew_cls�� __class__r r r# s zUser.__new__c
C s� || _ |jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _ |jd | _
|jd
| _|jd | _|jd | _
|jd
| _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _|jd | _d | _|jd | _d | _|jd | _|jd | _|jd | _ |jd | _!|jd | _"|jd | _#|jd! | _$| j$d u�r�| j�r�|j%d"d#� |jd$ d u�r�d%�&|jd$ �| _|jd& d u�rHzt'�(|jd& �| _W n@ t)�yF } z&|j%d'| jt*|�f d#� W Y d }~n
d }~0 0 |jd( d u�rf|jd( | _+nt,j-�&d)d*| j �| _+| jd u �r�| j�r�|�.d+� d S ),N�state�name�uid�hidden�
non_unique�seuser�group�comment�shell�password�force�remove�create_home� move_home�skeleton�system�login_class�append�generate_ssh_key�ssh_key_bits�ssh_key_type�ssh_key_comment�ssh_key_passphrase�update_password�home�
password_lock�local�profile�
authorization�role�password_expire_max�password_expire_min�umaskz$'umask' can not be used with 'local'��msg�groups�,�expiresz"Invalid value for 'expires' %s: %s�ssh_key_filez.sshzid_%sz�'append' is set, but no 'groups' are specified. Use 'groups' for appending new groups.This will change to an error in Ansible 2.14.)/�module�paramsr) r* r+ r, r- r. r/ r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r: � sshkeygen�ssh_bits�ssh_type�ssh_comment�ssh_passphraser@ rA rN rB rL rC rD rE rF rG rH rI � fail_json�join�time�gmtime� Exceptionr �ssh_file�os�path�warn)�selfrP �er r r �__init__ sd 0z
User.__init__c s" � j jd �r� jdk�rd}� j jd tg d��v r<d}n�t� fdd�dD ��rVd}d � j jd vrld}n�� j jd �d �}t|�d
k�rtt� |d ��r�d}|d d
kr�t|d �dkr�d}|d dkr�t|d �dkr�d}|d dk�rt|d �dk�rd}nd}|�r� j �
d� d S )Nr2 �DarwinF)�*�!z
*************c 3 s | ]}|� j jd v V qdS )r2 N)rP rQ )�.0�char�r` r r � <genexpr>e � z0User.check_password_encrypted.<locals>.<genexpr>z:*!T�$� ���� �1� �5�+ �6�V zThe input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly.)rP rQ �platform�set�any�split�len�bool�_HASH_RE�searchr_ )r` Z
maybe_invalid�fieldsr rh r �check_password_encryptedZ s* zUser.check_password_encryptedFTc C sD | j jr |r | j �d| � dS dd� |D �}| j j|||d�S d S )N�#In check mode, would have run: "%s"�r � r� c S s g | ]}t |��qS r )�str�rf �xr r r �
<listcomp>� rj z(User.execute_command.<locals>.<listcomp>)�use_unsafe_shell�data)rP �
check_mode�debugZrun_command)r` �cmdr� r� �obey_checkmoder r r �execute_command~ s
zUser.execute_commandc C s | j js| jr| j �| j�S d S r )rP r� �
SHADOWFILEZbackup_localrh r r r �
backup_shadow� s zUser.backup_shadowc C s\ | j rd}nd}| j�|d�g}| jr6| j s6|�d� | jrF|�d� |�| j� | �|�S )NZluserdel�userdelT�-f�-r)rC rP �get_bin_pathr3 r: r4 r* r� )r` �command_namer� r r r �remove_user_userdel� s
zUser.remove_user_userdelc C s� | j r(d}| j�dd�}| j�dd�}nd}| j�|d�g}| jd url|�d� |�| j� | jrl|�d� | jd ur�|�d� |�| j� | jd ur�| �| j�s�| jj d | j d
� |�d� |�| j� n�| �| j
��r�| j r�|�d� n�tj�
d
��r8t�� }t|�d�d �}|dk�r,|�d� n
|�d� nHtj�
d��rvt�� }t|�d�d �}|dk�r�|�d� n
|�d� | jd u�r�t| j��r�| �� }| j �s�|�d� |�d�|�� | jd u�r�|�d� |�| j� | jd u�r6| j�r tj�| j�}tj�|��s | �| j� |�d� |�| j� | jd u�rX|�d� |�| j� | jd u�r�| j �s�|�d� | jt�d�k �r�|�d� n|�t� | j!| j�� | j"d u�r�|�d� | j#�r�|�d| j" � n|�| j"� | j�rJ| j �s |�d� | j$d u�r"|�d� |�| j$� | j%d u�rT|�d� |�d | j% � n
|�d!� | j&�rf|�d"� |�| j
� | �'|�\} }
}| j �r�| dk�r�| |
|fS | jd u�r| jt�d�k �r�d#}ntt(�)| jj*d$ ��d% }| �'|d&t+|�| j
g�\} }
}|
|
7 }
||7 }| dk�r| |
|fS | jd u �s:t| j�dk�rD| |
|fS |D ]H}| �'|d!| j
|g�\} }
}|
|
7 }
||7 }| dk�rH| |
|f S �qH| |
|fS )'NZluseradd� lgroupmodT�lchage�useradd�-u�-o�-Z�Group %s does not existrJ �-g�-nz/etc/redhat-release�.r � �-Nz/etc/SuSE-release� �-GrM �-c�-d�-s�-er� �-p�!%s�-m�-k�-K�UMASK=�-Mr� rm rN �Q �-E),rC rP r� r+ r: r- r. r/ �group_existsrW r* r] r^ �existsr �version�intrx rL ry �get_groups_setrX r0 rA r5 �dirname�isdir�create_homedirr1 rN rY rZ �strftime�DATE_FORMATr2 rB r7 rI r8 r� �math�floorrQ r )r` r� �
lgroupmod_cmd�
lchage_cmdr� ZdistZ
major_releaserL �parent�rc�out�err�lexpires�_out�_err� add_groupr r r �create_user_useradd� s�
zUser.create_user_useraddc
C s� | j rd}nd}| j�|d�}t�|tj�s0dS |dg}| j|dd�\}}}|| }t|��d�}|D ]} | � � �
d�rf dS qfdS ) N�lusermod�usermodTFz--help�r� �
z-a, --append)rC rP r� r] �access�X_OKr� r rx �strip�
startswith)
r` r� Zusermod_pathr� r� Zdata1Zdata2Zhelpout�lines�liner r r �_check_usermod_append" s zUser._check_usermod_appendc C s� | j r8d}| j�dd�}t� }t� }| j�dd�}d }nd}| j�|d�g}| �� }| �� } | jd ur�|d t| j�kr�|�d� |�| j� | j r�|�d� | j
d ur�| �| j
�s�| jjd | j
d
� | �
| j
�}
|d |
d kr�|�d� |�|
d � | jd u�r(| jd
d�}d
}g }
| jdk�r<|�r�| j�s�d}n^| jd
d�}
t|��|
�}|�r�| j�r�|
D ]*}||v �rh| �r�|�d� d} �q��qhnd}|�r(| j �r�| j�r�t|
��|�}t� }nt|
��|�}t|��|
�}nD| j�r| �s|�d� |�d�|�� n|�d� |�d�|
�� | jd u�rZ|d | jk�rZ|�d� |�| j� | jd u�r�|d | jk�r�|�d� |�| j� | j�r�|�d� | jd u�r�|d | jk�r�|�d� |�| j� | jd u�r�t| �� d �}| jt�d�k �r,|dk�r�| j �rd}n|�d� |�d� nxt�|d �}|dk �s`|d d� | jd d� k�r�| j �r�tt�| jjd! ��d }n |�d� |�t�| j | j�� | j!�r�|d �"d"��s�|�d#� n&| j!d
u �r�|d �"d"��r�|�d$� | j#d%k�r`| j$d u�r`|d �%d"�| j$�%d"�k�r`d&d'� |D �}|�d(� | j!�rT|�d)| j$ � n|�| j$� d*\}}}t&|�dk�r�|�| j'� | �(|�\}}}| j �r�|d u �s�|dk�s�|||fS |d u�r| �(|d+t)|�| j'g�\}}}||7 }||7 }|dk�r|||fS t&|�dk�r,t&|�dk�r,|||fS |D ]H}| �(|d,| j'|g�\}}}||7 }||7 }|dk�r0|||f S �q0|D ]H}| �(|d| j'|g�\}}}||7 }||7 }|dk�r~|||f S �q~|||fS )-Nr� r� Tr� r� � r� r� r� rJ rl r� F)�exclude_primaryr� ��remove_existing�-a�-ArM r� � r� r� r� r� � r� rn r rm r� r� rN re �-L�-U�alwaysc S s g | ]}|d vr|�qS ))r� r� r �rf r r r r r� � rj z,User.modify_user_usermod.<locals>.<listcomp>r� r� �Nr� r� r� r� )*rC rP r� rv � user_infor� r+ r� r: r- r/ r� rW �
group_inforL �user_group_membershipr� �symmetric_difference�
differencerX r0 rA r6 r1 rN �
user_passwordrY rZ r� r� rQ r� r� rB r� r@ r2 �lstripry r* r� r )r` r� r� Z
lgroupmod_addZ
lgroupmod_delr� r� r� �infoZ
has_append�ginfo�current_groups�groups_need_modrL �
group_diff�g�current_expires�current_expire_dater� r� r� r� r� r� Z del_groupr r r �modify_user_usermod= s�
&
4
zUser.modify_user_usermodc C sZ zt �t|�� W dS ttfyT zt �|� W Y dS tyN Y Y dS 0 Y n0 d S )NTF)�grp�getgrgidr� �
ValueError�KeyError�getgrnam�r` r/ r r r r� � s
zUser.group_existsc C sL | � |�sdS ztt�t|���W S ttfyF tt�|�� Y S 0 d S �NF)r� �listr� r� r� r� r� r� r� r r r r� � s
zUser.group_infoc C s� | j d u rd S | �� }tdd� | j �d�D ��}|�� D ]H}| �|�sX| jjd| d� |r8|r8| �|�d |d kr8|� |� q8|S )Nc s s | ]}|r|� � V qd S r )r� r� r r r ri � rj z&User.get_groups_set.<locals>.<genexpr>rM r� rJ r� rl )
rL r� rv rx �copyr� rP rW r� r4 )r` r� r� rL r� r r r r� � s
zUser.get_groups_setc C sZ g }| � � }t�� D ]@}| j|jv r|s8|�|d � q|d |jkr|�|d � q|S )z- Return a list of groups the user belongs to r rl )�get_pwd_infor� �getgrallr* �gr_memr: �gr_gid)r` r� rL r� r/ r r r r� � s zUser.user_group_membershipc C s� | j r�tj�| j�s*| jjd�| j�d� d}d�| j�}t | jd��B}|�
� d d d� }|D ]}|�t|��r^d} qzq^W d � n1 s�0 Y |s�| j�
dj| j| jd �� |S zt�| j�r�W dS W n ty� Y dS 0 d S )
NzK'local: true' specified but unable to find local account file {0} to parse.rJ Fz{0}:�rbrm Tz�'local: true' specified and user '{name}' was not found in {file}. The local user account may already exist if the local account database exists somewhere other than {file}.)�filer* )rC r] r^ r� �PASSWORDFILErP rW �formatr* �open� readlinesr� r r_ �pwd�getpwnamr� )r` r� Z name_test�fZreversed_linesr� r r r �user_exists s. $��
zUser.user_existsc C s | � � sdS tt�| j��S r� )r r� r r r* rh r r r r� / s zUser.get_pwd_infoc C sH | � � sdS | �� }t|d �dks4t|d �dkrD| �� d |d<