o nnh@s&ddlmZdZdZdZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlmZddlmZmZmZddlmZdd lmZdd lmZddlm m!m"Z#Gd d d ej$Z%zej&'e#(e)ej*+d Z,ej-fe,j._/e0e%e,j._1dZ2Wn e3ydZ2Ynwe 4dZ5ddZ.Gddde6Z7Gddde7Z8Gddde8Z9Gddde7Z:Gddde7Z;Gddde7ZGd#d$d$e7Z?Gd%d&d&e7Z@Gd'd(d(e@ZAd)d*ZBeCd+kreBdSdS),) annotationsa3 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. - On macOS, this defaults to the O(name) option. type: str hidden: description: - macOS only, optionally hide the user from the login window and system preferences. - The default will be V(true) if the O(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). - On macOS, this defaults to V('staff') type: str groups: description: - A list of supplementary groups which the user is also a member of. - By default, the user is removed from all other groups. Configure O(append) to modify this. - When set to an empty string V(''), 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 V(true), add the user to the groups specified in O(groups). - If V(false), user will only be added to the groups specified in O(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 V(/usr/bin/false). Since Ansible 2.5, the default shell for non-system users on macOS is V(/bin/bash). - On other operating systems, the default shell is determined by the underlying tool invoked by this module. See Notes for a per platform list of invoked tools. type: str home: description: - Optionally set the user's home directory. type: path skeleton: description: - Optionally set a home skeleton directory. - Requires O(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 V('!') or V('*'). - To create an account with a locked/disabled password on OpenBSD, set this to V('*************'). - B(OS X/macOS:) Enter the cleartext password as the value. Be sure to take relevant security precautions. - On macOS, the password specified in the C(password) option will always be set, regardless of whether the user account already exists or not. - When the password is passed as an argument, the C(user) module will always return changed to C(true) for macOS systems. Since macOS no longer provides access to the hashed passwords directly. type: str state: description: - Whether the account should exist or not, taking action if the state is different from what is stated. - See this L(FAQ entry,https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#running-on-macos-as-a-target) for additional requirements when removing users on macOS systems. type: str choices: [ absent, present ] default: present create_home: description: - Unless set to V(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 O(createhome) to O(create_home) in Ansible 2.5. type: bool default: yes aliases: [ createhome ] move_home: description: - "If set to V(true) when used with O(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 O(state=present), setting this to V(true) makes the user a system account. - This setting cannot be changed on existing users. type: bool default: no force: description: - This only affects O(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 O(generate_ssh_key=yes) this forces an existing key to be overwritten. type: bool default: no remove: description: - This only affects O(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 O(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 V(.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: - V(always) will update passwords if they differ. - V(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 V(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. - Can set multiple profiles using comma separation. - To delete all the profiles, use O(profile=''). - Currently supported on Illumos/Solaris. Does nothing when used with other platforms. type: str version_added: "2.8" authorization: description: - Sets the authorization of the user. - Can set multiple authorizations using comma separation. - To delete all authorizations, use O(authorization=''). - Currently supported on Illumos/Solaris. Does nothing when used with other platforms. type: str version_added: "2.8" role: description: - Sets the role of the user. - Can set multiple roles using comma separation. - To delete all roles, use O(role=''). - Currently supported on Illumos/Solaris. Does nothing when used with other platforms. 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" password_expire_warn: description: - Number of days of warning before password expires. - Supported on Linux only. type: int version_added: "2.16" umask: description: - Sets the umask of the user. - Currently supported on Linux. Does nothing when used with other platforms. - Requires O(local) is omitted or V(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: Create a user 'johnd' with a home directory ansible.builtin.user: name: johnd create_home: yes - 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 - name: Set number of warning days for password expiration ansible.builtin.user: name: jane157 password_expire_warn: 30 a append: description: Whether or not to append the user to groups. returned: When O(state) is V(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 O(state) is V(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 O(groups) is not empty and O(state) is V(present) type: str sample: 'chrony,apache' home: description: "Path to user's home directory." returned: When O(state) is V(present) type: str sample: '/home/asmith' move_home: description: Whether or not to move an existing home directory. returned: When O(state) is V(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 O(state) is V(present) and O(password) is not empty type: str sample: 'NOT_LOGGING_PASSWORD' remove: description: Whether or not to remove the user account. returned: When O(state) is V(absent) and user exists type: bool sample: True shell: description: User login shell. returned: When O(state) is V(present) type: str sample: '/bin/bash' ssh_fingerprint: description: Fingerprint of generated SSH key. returned: When O(generate_ssh_key) is V(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 O(generate_ssh_key) is V(True) type: str sample: /home/asmith/.ssh/id_rsa ssh_public_key: description: Generated SSH public key file. returned: When O(generate_ssh_key) is V(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 O(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 O(uid) is passed to the module type: int sample: 1044 N)distro)to_bytes to_nativeto_text) AnsibleModule)get_best_parsable_locale)get_platform_subclassc @sXeZdZdejfdejfdejfdejfdejfdejfdejfdejfd ejfg Zd S) StructSpwdTypesp_nampsp_pwdp sp_lstchgsp_minsp_maxsp_warnsp_inact sp_expiresp_flagN)__name__ __module__ __qualname__ctypesc_char_pc_longc_ulong_fields_rr?/usr/local/lib/python3.10/dist-packages/ansible/modules/user.pyr sr cTFz[^a-zA-Z0-9./=]cCs t|jSN)_LIBCgetspnamcontents)b_namerrrr!s r!cseZdZdZdZdZdZdZdZdZ dZ fd d Z d d Z d dZ dCddZddZddZddZddZddZddZdd ZdDd!d"ZdEd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-d.Zd/d0Zd1d2Zd3d4Zd5d6Z d7d8Z!d9d:Z"d;d<Z#d=d>Z$d?d@Z%dAdBZ&Z'S)FUsera| 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/shadowz/etc/login.defsz%Y-%m-%dcstt}t|||Sr)r r$super__new__)clsargskwargsnew_cls __class__rrr)sz User.__new__c Cs||_|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!|_$|jd"|_%|j%dur|jr|j&d#d$|jd%durd&'|jd%|_|jd'dur'z t()|jd'|_Wn t*y&}z|j&d(|jt+|fd$WYd}~nd}~ww|jd)dur6|jd)|_,n t-j.'d*d+|j|_,|jdurR|jrT|/d,dSdSdS)-Nstatenameuidhidden non_uniqueseusergroupcommentshellpasswordforceremove create_home move_homeskeletonsystem login_classappendgenerate_ssh_key ssh_key_bits ssh_key_typessh_key_commentssh_key_passphraseupdate_passwordhome password_locklocalprofile authorizationrolepassword_expire_maxpassword_expire_minpassword_expire_warnumaskz$'umask' can not be used with 'local'msggroups,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.)0moduleparamsr0r1r2r3r4r5r6r7r8r9r:r;r<r=r>r?r@rA sshkeygenssh_bitsssh_type ssh_commentssh_passphraserGrHrVrIrTrJrKrLrMrNrOrPrQ fail_jsonjointimegmtime Exceptionrssh_fileospathwarn)selfrXerrr__init__#sl                                   &z User.__init__csBjjdrjdkrd}jjdtgdvrd}nutfdddDr)d}d jjdvr4d}n]jjdd }t|d krtt |d rNd}|d d kr^t|d dkr^d}|d dkrnt|d dkrnd}|d dkr~t|d dkr~d}|d dkrt|d dkrd}nd}|rj ddSdSdSdS)Nr9DarwinF)*!z *************c3s |] }|jjdvVqdS)r9N)rXrY).0charrhrr lsz0User.check_password_encrypted..z:*!T$15+6VyzThe input password appears not to have been hashed. The 'password' argument must be encrypted for this module to work properly.) rXrYplatformsetanysplitlenbool_HASH_REsearchrg)rh maybe_invalidfieldsrrprcheck_password_encryptedas4 !zUser.check_password_encryptedFTcCs@|jjr|r|jd|dSdd|D}|jj|||dS)N#In check mode, would have run: "%s"rrcSg|]}t|qSr)strrnxrrr z(User.execute_command..)use_unsafe_shelldata)rX check_modedebug run_command)rhcmdrrobey_checkmoderrrexecute_commands zUser.execute_commandcCs$|jjs|jr|j|jSdSdSr)rXr SHADOWFILE backup_localrprrr backup_shadowszUser.backup_shadowcCs\|jrd}nd}|j|dg}|jr|js|d|jr#|d||j||S)NluserdeluserdelT-f-r)rJrX get_bin_pathr:rAr;r1r)rh command_namerrrrremove_user_userdels     zUser.remove_user_userdelcCs|jrd}|jdd}|jdd}nd}|j|dg}|jdur6|d||j|jr6|d|jdurF|d||j|jdurg||js[|jj d |jd |d ||jnT||j r|jrv|d nEt j d rt}t|dd}|dkr|d n(|dn"t j drt}t|dd}|dkr|dn|d|jdurt|jr|}|js|d|d||jdur|d||j|jdur|jrt j |j}t j |s||j|d||j|jdur#|d||j|jdurL|jsL|d|jtdkrA|dn |t |j!|j|j"durj|d|j#rd|d|j"n||j"|jr|jsw|d|j$dur|d||j$|j%dur|d|d |j%n|d!|j&r|d"||j |'|\} } } |jr| dkr| | | fS|jdur|jtdkrd#} n tt()|jj*d$d%} |'|d&t+| |j g\} } }| | 7} | |7} | dkr| | | fS|jdust|jdkr| | | fS|D]$}|'|d!|j |g\} } }| | 7} | |7} | dkr>| | | fSq| | | fS)'Nluseradd lgroupmodTlchageuseradd-u-o-ZGroup %s does not existrR-g-nz/etc/redhat-release.r-Nz/etc/SuSE-release -GrU-c-d-s-er-p!%s-m-k-KUMASK=-MrrtrVQ-E),rJrXrr2rAr4r5r6 group_existsr_r1rerfexistsrversionintrrTrget_groups_setr`r7rHr<dirnameisdircreate_homedirr8rVrarbstrftime DATE_FORMATr9rIr>rQr?rmathfloorrYr)rhr lgroupmod_cmd lchage_cmdrdist major_releaserTparentrcouterrlexpires_out_err add_grouprrrcreate_user_useradds                                                  zUser.create_user_useraddc Cs|jrd}nd}|j|d}t|tjsdS|dg}|j|dd\}}}||}t|d}|D] } | dr?dSq3dS) NlusermodusermodTFz--helpr z -a, --append) rJrXrreaccessX_OKrrrstrip startswith) rhr usermod_pathrrdata1data2helpoutlineslinerrr_check_usermod_append,szUser._check_usermod_appendcCs|jrd}|jdd}t}t}|jdd}d}nd}|j|dg}|}|} |jdurO|dt|jkrO|d||j|j rO|d|j dur~| |j sd|jj d |j d | |j } |d | dkr~|d || d|jdur|jd d} d } g} |jdkr| r|jsd} n*|jd dd} t| | }|r|jr| D]}||vr| r|dd} nqnd} | r|jr|jrt| | }t}n/t| | }t| | }n |jr| s|d|d|n |d|d| |jdur!|d|jkr!|d||j|jdurC|d|jkrC|d||j|jrC|d|jdur\|d|jkr\|d||j|jdur|dpjd}t|}|jtdkr|dkr|jrd}nG|d |dn.rrNrrrr)*rJrXrr~ user_inforr2rrAr4r6rr_ group_inforTuser_group_membershiprsymmetric_difference differencer`r7rHr=r8rV user_passwordrarbrrrYrrrIrrGr9lstriprr1rr)rhrr lgroupmod_add lgroupmod_delrrrinfo has_appendginfocurrent_groupsgroups_need_modrT group_diffgcurrent_expirescurrent_expire_daterrrrrr del_grouprrrmodify_user_usermodGs                          &   4            zUser.modify_user_usermodc CsRz tt|WdSttfy(z t|WYdSty'YYdSww)NTF)grpgetgrgidr ValueErrorKeyErrorgetgrnamrhr6rrrrs  zUser.group_existsc CsH||sdSz ttt|WSttfy#tt|YSwNF)rlistr r rr r rrrrrrs zUser.group_infocCs|jdurdS|}tdd|jdD}t}|D]0}||s/|jjd|d||}|rF|rF|d|dkrF| |q|rO| |dq|rT|S|S) Ncss|] }|r|VqdSr)rrrrrrqsz&User.get_groups_set..rUrrRrrsr) rTrr~rcopyrrXr_rr;add)rhrrrrT group_namesrrrrrrs"     zUser.get_groups_setcCsZg}|}tD] }|j|jvr*|s||dq |d|jkr*||dq |S)z- Return a list of groups the user belongs to rrs) get_pwd_infor getgrallr1gr_memrAgr_gid)rhrrTrr6rrrrs  zUser.user_group_membershipcCs|jrWtj|js|jjd|jdd}d|j}t |jd*}| ddd}|D] }| t |r.)stdinstdoutstderr preexec_fnenvs+Enter passphrase (empty for no passphrase):sEnter same passphrase againi(stricterrors sOverwrite (y/n)?)NzKey already existsrrr)'rr5rcrrerfrrrXrmkdirrchownOSErrorr:rgunlinkrrAr\r[r]r^rptyopenptyenvironrr subprocessPopensetsidpollselectreadwriter returncoder)rhr overwriterWpub_filerissh_dirr master_in_fd slave_in_fd master_out_fd slave_out_fd master_err_fd slave_err_fdr@p out_buffer err_bufferr_list first_prompt second_promptpromptfdchunkrrrrrr ssh_key_gens  "                           zUser.ssh_key_gencCs^|}tj|sdd|dfS|jddg}|d|d|||j|dd S) NruzSSH Key file %s does not existrr9Tz-lrFr)r5rerfrrXrrAr)rhrWrrrrssh_key_fingerprints    zUser.ssh_key_fingerprintcCsbd|}z t|d}|}WdW|S1swYW|Sty0YdSw)Nz%s.pubr/)r5rrSrIOError)rhssh_public_key_filer!ssh_public_keyrrrget_ssh_public_keys    zUser.get_ssh_public_keycC|Sr)rrprrr create_user zUser.create_usercCrnr)rrprrr remove_user rpzUser.remove_usercCrnr)r rprrr modify_userrpzUser.modify_userc Cstj|s|jdur|j}nd}tj|rE|tjkrEz tj||ddWnDtyD}z|jj ddt |dWYd}~n+d}~wwzt |Wntyj}z|jj ddt |dWYd}~nd}~wwtj|j rt |j dJ}|D]>}td|}|rt|dd }d |@}zt||Wq{ty}z|jj ddt |dWYd}~q{d}~wwq{WddS1swYdSdSdS) Nz /etc/skelT)symlinks%sfailedrSr/z^UMASK\s+(\d+)$rur7i)rerfrr>devnullshutilcopytreerIrX exit_jsonrmakedirs LOGIN_DEFSrrematchrr6chmod) rhrfr>rir!rmrQmoderrrrsF  $$  $"zUser.create_homedirc Csz?t|||t|D]/\}}}|D]}ttj||||q|D]}tj||} tj| s;t| ||q%q WdSty^} z|jjddt | dWYd} ~ dSd} ~ ww)NTrtru) rerHwalkrfr`islinkrIrXrzr) rhr2gidrfrootdirsfilesdr! full_pathrirrr chown_homedir3s  &zUser.chown_homedir)FNT)TF)T)(rrr__doc__r} distributionrrr3r|rr)rjrrrrrrr rrrrr#rrr,rr-r5rhrirmrorqrrrr __classcell__rrr.rr$sN > '  #   h  r$c@sDeZdZdZdZdZdZdZdZddZ d d Z d d Z d dZ dS) FreeBsdUsera1 This is a FreeBSD User manipulation class - it uses the pw command to manipulate the user database, followed by the chpass command to change the password. This overrides the following methods from the generic class:- - create_user() - remove_user() - modify_user() FreeBSDN/etc/master.passwdrz%d-%b-%YcCs|}|jr7|dds7|jddd|jg}|jdur2|dt|jkr2|d||j| |S|jdurl|ddrl|jddd |jg}|jdurg|dt|jkrg|d||j| |Sd S) Nru*LOCKED*pwTlockrrFunlockr) rrIrrXrr1r2rrAr)rhrrrrr _handle_lockUs(        zFreeBsdUser._handle_lockcCs2|jdddd|jg}|jr|d||S)NrTrrrrXrr1r;rArrhrrrrrqns   zFreeBsdUser.remove_userc Cs|jdddd|jg}|jdur$|d||j|jr$|d|jdur4|d||j|jdurD|d||j|jdurd| |jsY|jj d |jd |d ||j|j durz| }|d |d ||jr|d|jdur|d||j|jdur|d|d|j|jdur|d||j|jdur|d||j|jdur|d|jtdkr|dn |tt|j||\}}}|dur|dkr|jj |j||d|jdur-|jddd|j|jg}||\}}}|dur%|}||7}||7}|\}}}|dur;|}||7}||7}|||fS)NrTrrrrrrrrRrrrUrrrrrrrrrr1rSrchpassr)rXrr1r2rAr4r7rHr6rr_rTrr`r<r>rQr8r@rVrarbrcalendartimegmrr9r) rhrrTrrr_rcrrrrrrozs                                     zFreeBsdUser.create_usercCs|jdddd|jg}t|}|}|jdur5|dt|jkr5|d||j|jr5|d|j durL|d|j krL|d ||j |j dur|d |j kr[|j set j |j sj|jrj|d |d |j kr||d ||j |jdur|d ||j|jdur|d|d|j|jdur||js|jjd|jd||j}|d|dkr|d||j|jdur|d|jkr|d||j|jdur:d}t j |jr)t |jt jr)t|jd}|D]}|d|jr|dd}qWdn 1s$wY|j|kr:|d||j|jdur|}|j dd} t!|"| } d} | rl|jrj| D] } | | vrgd} nq\nd} | r|d| } |jr| t!|B} |d#| |j$dur|%dpd}t|}|j$t&'d kr|d kr|d!|dn(t&'|}|d ks|dd|j$ddkr|d!|t(t)*|j$d"\}}}|t|kr |+|\}}}||7}||7}|dur |d kr |jj|j||d#|j,d$krJ|j-durJ|d.d%|j-.d%krJ|jd&dd'|j-|jg}|+|\}}}|durB|}||7}||7}|/\}}}|durX|}||7}||7}|||fS)(NrTrrrrrrrrrrrrrrrRrsrrrr/r0r1rrFrrUrurrrrrrrrr)0rXrr1rrr2rrAr4r7rHr=rerfrr<r>rQr6rr_rr8r@rrr2rrrrTrrr~rr`rVrrarbrrrrrGr9rr)rhrcmd_lenrruser_login_classr!rrrTrrr new_groupsrrrrrrrrrrrrrs       (                "             &  4    zFreeBsdUser.modify_user) rrrrr}rrr3rrrqrorrrrrrrCs  Zrc@seZdZdZdZdS)DragonFlyBsdUserz This is a DragonFlyBSD User manipulation class - it inherits the FreeBsdUser class behaviors, such as using the pw command to manipulate the user database, followed by the chpass command to change the password. DragonFlyN)rrrrr}rrrrr`src@4eZdZdZdZdZdZddZddZd d Z dS) OpenBSDUsera, This is a OpenBSD User manipulation class. Main differences are that OpenBSD:- - has no concept of "system" account. - has no force delete user This overrides the following methods from the generic class:- - create_user() - remove_user() - modify_user() OpenBSDNrcCs|jddg}|jdur |d||j|jr |d|jdur@||js5|jjd|jd|d||j|jdurV| }|d|d ||j durf|d ||j |j durv|d ||j |j dur|d ||j |jdur|d ||j|jdur|jdkr|d||j|jr|d|jdur|d||j|jdur|d|d|j||j||S)NrTrrrrRrrrUrrrrrlrrrrr)rXrr2rAr4r6rr_rTrr`r7rHr8r@r9r<r>rQr1rrhrrTrrrro|sP                                zOpenBSDUser.create_usercC6|jddg}|jr|d||j||SNrTrrXrr;rAr1rrrrrr    zOpenBSDUser.remove_user_userdelcCs@|jddg}|}|jdur-|dt|jkr-|d||j|jr-|d|jdur[||jsB|jj d|jd| |j}|d|dkr[|d ||j|j dur| }d }d }g}|j d krw|rv|jsvd}n$|j dd }t||}|r|jr|D] } | |vrd}d}nqnd}|r|||d||jdur|d|jkr|d||j|jdur|d|jkr|jr|d|d||j|jdur|d|jkr|d||j|jdurBd} |jdd|jg} |j| d d\} } }| D]}|}|ddkr/t|dkr/|d} q|j| krB|d||j|jrT|ddsT|dn|jd urg|ddrg|d|jd kr|jdur|jdkr|d|jkr|d!||jt|dkrd"S||j||S)#NrTrrrrrRrsrF-SrrrrUrrrrrrruserinforrclassrurrlrrrrr)rXrrr2rrAr4r6rr_rrTrrr~rr`r7rHr=r8r@r1r splitlinesrrrIrrGr9)rhrrrrr groups_optionrTrrr userinfo_cmdrrrrtokensrrrrrs                               zOpenBSDUser.modify_user rrrrr}rrrorrrrrrrrks 7 rc@r) NetBSDUsera+ This is a NetBSD User manipulation class. Main differences are that NetBSD:- - has no concept of "system" account. - has no force delete user This overrides the following methods from the generic class:- - create_user() - remove_user() - modify_user() NetBSDNrcCs|jddg}|jdur |d||j|jr |d|jdur@||js5|jjd|jd|d||j|jdurg| }t |dkrZ|jjd t |d|d |d ||j durw|d ||j |j dur|d ||j |jdur|d||j|jdur|d||j|jdur|d||j|jr|d|jdur|d||j|jdur|d|d|j||j||S)NrTrrrrRr.Too many groups (%d) NetBSD allows for 16 max.rrUrrrrrrrrr)rXrr2rAr4r6rr_rTrrr`r7rHr8r@r9r<r>rQr1rrrrrro+sT                                  zNetBSDUser.create_usercCrrrrrrrrdrzNetBSDUser.remove_user_userdelc Cs|jddg}|}|jdur-|dt|jkr-|d||j|jr-|d|jdur[||jsB|jj d|jd| |j}|d|dkr[|d ||j|j dur| }d }g}|j d kru|rt|jstd}n)|j dd }t||}|r|jr|D]}||vrt||}d}nqnd}|rt|d kr|jj dt|d|d|d||jdur|d|jkr|d||j|jdur|d|jkr|jr|d|d||j|jdur |d|jkr |d||j|jdur|d||j|jdkr=|jdur=|d|jkr=|d||j|jrO|ddsO|dn|jd urb|ddrb|dt|dkrkdS||j||S) NrTrrrrrRrsrFrrrrrrUrrrrrrrrrrurrz-C yesz-C nor)rXrrr2rrAr4r6rr_rrTrrr~runionrr`r7rHr=r8r@rGr9rIrr1r) rhrrrrrrTrrrrrrrks                        (      zNetBSDUser.modify_userrrrrrrs 9 rcsXeZdZdZdZdZdZdZddZddZ d d Z d d Z fd dZ ddZ ZS)SunOSa This is a SunOS User manipulation class - The main difference between this class and the generic user class is that Solaris-type distros don't support the concept of a "system" account and we need to edit the /etc/shadow file manually to set a password. (Ugh) This overrides the following methods from the generic class:- - create_user() - remove_user() - modify_user() - user_info() Nr&z/etc/user_attrc Cszad}d}d}tddL}|D]A}|}|ds|dkrqtd|}|r,|d}|d\}}|dkr=|d }q|d krG|d }q|d krP|d }qWdn1s[wYWnty~} z|j j d t | d WYd} ~ nd} ~ ww|||fS)Nrz/etc/default/passwdr/#z^([^#]*)#(.*)$ru=MINWEEKSrMAXWEEKS WARNWEEKSz&failed to read /etc/default/passwd: %srR) rrrr}r~r6rrstriprcrXr_r) rhminweeksmaxweeks warnweeksr!rrkeyvaluerrrrget_password_defaultss8      " zSunOS.get_password_defaultscCrrrrrrrrq    zSunOS.remove_userc Cs|jddg}|jdur |d||j|jr |d|jdur@||js5|jjd|jd|d||j|jdurV| }|d|d ||j durf|d ||j |j durv|d ||j |j dur|d ||j |jr|d |jdur|d||j|jdur|d|d|j|jdur|d||j|jdur|d||j|jdur|d||j||j||\}}}|dur|dkr|jj|j||d|jjs|jdur||\}}}zg} t|jd} | D]} t| dd} | d} | d|jksB| | q$|j| d<tt t!!d| d<|rmz tt |d| d<Wn t"ylYnw|rz tt |d| d<Wn t"yYnw|rz tt |d| d <Wn t"yYnwd | } | d!| q$Wdn 1swYt|jd" } | #| Wdn 1swYWnt$y}z|jjd#t|dWYd}~nd}~ww|||fS)$NrTrrrrRrrrUrrrrrrr-Pr-Rrrrsurrogate_or_strictrCr1rurrr'rsrr%s w+#failed to update users password: %s)%rXrr2rAr4r6rr_rTrr`r7rHr8r<r>rQrKrLrMr1rrr9rrrrrrrrrrar  writelinesrc) rhrrTrrrrrrrr!rrrrrros                                          " zSunOS.create_userc Cs|jddg}t|}|}|jdur1|dt|jkr1|d||j|jr1|d|jdur_| |jsF|jj d|jd| |j}|d|dkr_|d ||j|j dur| }|jdd }t||}d }|r|jr|D] } | |vrd}nq~nd}|r|d |} |jr| ||d | |jdur|d|jkr|d||j|jdur|d|jkr|jr|d|d||j|jdur|d|jkr|d||j|jdur |d|jkr |d||j|jdur$|d|jkr$|d||j|jdur=|d|jkr=|d||j|t|krg||j||\} } } | durf| dkrf|jj |j| | dnd\} } } |jdkrS|jdurS|d|jkrS|d \} } } |jjsS| \}}}zg}t!|j"d!n}|D]c}t#|d"d#}|$%d$}|d|jks||q|j|d<t&tt''d%|d<|rt&t|d|d<|rt&t|d|d<|rt&t|d|d<d$|}|d&|qWdn 1swYt!|j"d' }|(|Wdn 1s,wYd} Wnt)yR} z|jj d(t#| dWYd} ~ nd} ~ ww| | | fS))NrTrrrrrRrsrrFrrUrrrrrrrr'rr7r rrrrrrurrrrCr1rrrr)*rXrrrr2rrAr4r6rr_rrTrrr~rupdater`r7rHr=r8rKrLrMr1rrGr9rrrrrrrrrrarrc)rhrrrrrrTrrrrrrrrrrrr!rrrrrr [s                           (       " zSunOS.modify_user_usermodcs"tt|}|r||7}|Sr)r(rr_user_attr_infor$r.rrrs zSunOS.user_infocCsdgd}t|jdB}|D]6}|d}|d|jkrDtdd|dd D}|d d|d<|d d|d<|d d|d <qWd|S1sPwY|S)Nrrsr/z::::rcss|]}|dVqdS)rN)rrrrrrqsz(SunOS._user_attr_info..ru;profilesauthsrolesr)r USER_ATTRrrr1dictget)rhr file_handlerrrtmprrrrs  zSunOS._user_attr_info)rrrrr}rrrrrqror rrrrrr.rrs i nrcseZdZdZdZdZdZdZgdZfddZ dd Z d d Z d d Z d#ddZ ddZddZddZddZddZddZddZd$dd Zd!d"ZZS)% DarwinUsera This is a Darwin macOS User manipulation class. Main differences are that Darwin:- - Handles accounts in a database managed by dscl(1) - Has no useradd/groupadd - Does not create home directories - User password must be cleartext - UID must be given - System users must ben under 500 This overrides the following methods from the generic class:- - user_exists() - create_user() - remove_user() - modify_user() rkNr))r7RealName)rHNFSHomeDirectory)r8 UserShell)r2UniqueID)r6PrimaryGroupIDr3IsHiddencsZtt|||jdur|jrd|_n |jrd|_nd|_|jdur+|jddSdS)Nrurr)r(rrjr3r?rrA)rhrXr.rrrjs  zDarwinUser.__init__cCs|jdd|jgS)NdsclT)rXrdscl_directoryrprrr _get_dscl szDarwinUser._get_dsclcCsl|}|ddd|jg7}|j|dd\}}}g}|D]}|ds)|dr*q||dq|S) Nz-searchz/GroupsGroupMembershipFr )r)rr1rrrrAr)rhrrrrrTrrrr_list_user_groups s zDarwinUser._list_user_groupscCs|}|dd|j|g7}|j|dd\}}}|dkrdS|}t|dkr1|dddSt|d krGd |dg|d dSt|d krS|dSdS) zCReturn user PROPERTY as given my dscl(1) read or None if not found.-read /Users/%sFrrNruz: rr)rr1rrrrr`r)rhpropertyrrrrrrrr_get_user_property s     zDarwinUser._get_user_propertyc Cs|}|gd7}|j|dd\}}}|dkr"|jjd|||dd}d}|D]}t|dd} || kr;| }|| krE| d krE| }q*|rZd|krUd krZ|d S|d S|d S) zv Return the next available uid. If system=True, then uid should be below of 500, if possible. )z-listz/UsersrFrrz$Unable to get the next available uid)rSrrrrrtiiru)rrrXr_rrr) rhr?rrrrmax_uidmax_system_uidr current_uidrrr _get_next_uid/ s.  zDarwinUser._get_next_uidcCsr|}|jr|dd|j|jg7}n |dd|jddg7}||\}}}|dkr4|jjd|||d|||fS) zsChange password for SELF.NAME against SELF.PASSWORD. Please note that password must be cleartext. z-passwdr-createPasswordrlrzError when changing passwordrSrrr)rr9r1rrXr_rhrrrrrrr_change_user_passwordL s  z DarwinUser._change_user_passwordcCs\|jdurd|_z t|jj|_Wnty%|jjd|jdYnwt|j|_dS)zDConvert SELF.GROUP to is stringed numerical value suitable for dscl.NnogroupzBGroup "%s" not found. Try to create it first using "group" module.rR)r6r rrr rXr_rrprrr_make_group_numericalb s  z DarwinUser._make_group_numericalcCsj|dkrd}nd}ddd||jdd|g}||\}}}|d kr0|jjd ||j|f|||d |||fS) Add or remove SELF.NAME to or from GROUP depending on ACTION. ACTION can be 'add' or 'remove' otherwise 'remove' is assumed. rrr dseditgroupreditr:userrz"Cannot %s user "%s" to group "%s".r)r1rrXr_)rhr6actionoptionrrrrrrr__modify_groupm s  zDarwinUser.__modify_groupc Csd}d}d}d}t|}|jdur|jdd}ntg}|jdurA||D]}||d\}} } ||7}|| 7}|| 7}d}q'||D]} || d\}} } ||7}|| 7}|| 7}d}qE||||fS) rrrFNTrdeleter)r~rrTrrA_DarwinUser__modify_group) rhrrrchangedcurrenttargetr;rrrrrrr _modify_group{ s,      zDarwinUser._modify_groupc Cs6d}dd|dg}|j|dd\}}}g}|ddD]}z |d d}Wn ty4|}Ynw||q|jri|j|vrgdd |dd |jg}||\}}}|d kre|jj d |j|||dd SdS|j|vr|| |j=dd |ddg|}||\}}}|d kr|jj d|j|||dd SdS)zvHide or show user on login window according SELF.SYSTEM. Returns 0 if a change has been made, None otherwise.z0/Library/Preferences/com.apple.loginwindow.plistdefaultsrSHiddenUsersListFrrurtr8rTz -array-addrz%Cannot user "%s" to hidden user list.rz-arrayz.Cannot remove user "%s" from hidden user list.N) rrr IndexErrorrrAr?r1rXr_index)rh plist_filerrrr hidden_usersrrrr_update_system_user s6      zDarwinUser._update_system_usercCs8|}|dd|jdg7}|j|dd\}}}|dkS)z1Check is SELF.NAME is a known user on the system.rrrFrr)rr1rrrrrr# szDarwinUser.user_existscCs|}|}|dd|jg7}||\}}}|dkr*|jjd|j|||d|jrDtj |drDt |d|d|d7}|||fS)zCDelete SELF.NAME. If SELF.FORCE is true, remove its home directory.z-deleterrzCannot delete user "%s".rrz Removed %s) rrr1rrXr_r:rerfrrxrmtree)rhrrrrrrrrrq s zDarwinUser.remove_userrc Cs|}|dd|jg7}||\}}}|dkr&|jjd|j|||d|jdur/|j|_|jdur7d|_||jdurIt | |j |_|j rv|j durWd|j|_ |jjsvtj|j sht|j |t|jt|j|j |j s|jdurd|_|jD]V}|d|jvr|j|dr|}|dd|j|d|j|dg7}||\}}}|dkr|jjd |d|jf|||d||7}||7}|dkr|||fSq|\}}}||7}||7}||jr|\}}}} ||7}||7}|||fS) NrrrzCannot create user "%s".rstaffz /bin/bashruz&Cannot add property "%s" to user "%s".)rr1rrXr_r7r6rr2rrr?r<rHrrerfrr{rrr8r__dict__rr rTr) rhrrrrrfieldrrrrrrro sT       $" zDarwinUser.create_userc Csnd}d}d}|jr ||jD]c}|d|jvrs|j|drs||d}|dus6|t|j|dkrs|}|dd|j|d|j|dg7}||\}}} |dkri|j j d|d|jf|||d|}||7}|| 7}q|j dkr|j dur| \}}} ||7}|| 7}|}|jr|\}}} } ||7}|| 7}| d ur|}|}|dkr|}|||fS) Nrrrurrz*Cannot update property "%s" for user "%s".rrT)r6rrr rrrr1rrXr_rGr9rrTrr ) rhrrrrrrrrr_changedrrrrr sL $  zDarwinUser.modify_userr)r)rrrrr}rrrrrjrrrrrrrrr r#rqrorrrrrr.rrs*    ) eZdZdZdZdZdZddZd ddZd d Z d d Z dS)AIXz This is a AIX User manipulation class. This overrides the following methods from the generic class:- - create_user() - remove_user() - modify_user() - parse_shadow_file() Nz/etc/security/passwdcCrrrrrrrrqS rzAIX.remove_userrcCs|j|dg}|jdur|d||j|jdur8||js-|jjd|jd|d||j|jdurSt|jrS| }|d|d ||j durc|d||j |j durs|d ||j |j dur|d ||j |jr|d |jdur|d ||j|jdur|d |d|j||j||\}}}|jdurg}||jdd|d|d|j|d|j|jfd|||fS)NTrrrRrrrUrrrrrrrchpasswdr%s:%srF)rXrr2rAr6rr_rTrrr`r7rHr8r<r>rQr1rr9)rhrrrTrrrrrrr[ sN                            zAIX.create_user_useraddcCs|jddg}|}|jdur%|dt|jkr%|d||j|jdurS||js:|jjd|jd| |j}|d|dkrS|d||j|j dur| }d }g}|j d krm|rl|jsld}n"|j dd }t ||}|r|jr|D] }||vrd}nqnd}|r|d |d ||jdur|d|jkr|d||j|jdur|d|jkr|jr|d|d||j|jdur|d|jkr|d||jt|dkrd\} } } n||j||\} } } |jdkr@|jdur@|d|jkr@g}||jdd|d|d|j|d|j|jfd\} } }nd\} } }| durS| | | | |fS| | | | |fS)NrTrrrrRrsrFrrrrUrrrrrrrrurrrrrrF)rXrrr2rrAr6rr_rrTrrr~rr`r7rHr=r8rr1rrGr9)rhrrrrrrTrrrrrrc2out2err2rrrr  sv                      (  "  zAIX.modify_user_usermodc Cs(t|j}d}d}tj|jrt|jtjrt|jd }| }Wdn1s-wYd}d}z||js3|jjd|jd|d||j|jdurN|d||j|j dur^|d ||j |j durn|d ||j |j sv|d |j dur|d ||j |j dur|d |d|j |jr|d||j||\}}}|dur|dkr|jj|j||d|jdur|jddg}|ddj|j|jd}|j||d\}}}|dur|dkr|jj|j||d|jdur6t|jr6|}|jdd}|D]%}||j|g}||\}}}|dur4|dkr4|jj|j||dq|||fS)NadduserTz-DrzGroup {0} does not existrRrrz-hrz-Hrrrrrrr --encrypted{name}:{password}r1r9rF)rXrrAr2r6rr_rr7rHr8r<r>rQr?r1rr9rTrr) rhrrrrrrT add_cmd_binr6rrrro sd                             zBusyBox.create_usercCs.|jdd|jg}|jr|d||S)NdeluserTz --remove-homerrrrrrq s   zBusyBox.remove_usercCs|}g}d}d}d}|}|jdd}|jdd}|jdurt|jr|}t||} | r|D]&} | | vr]||j | g} | | \}}}|dur]|dkr]|jj |j ||dq7| D])} | |vr|j s||j | g} | | \}}}|dur|dkr|jj |j ||dq`|j dkr|jdur|d|jkr|jd dg} | d d j|j |jd }|j | |d \}}}|dur|dkr|jj |j ||d|||fS)Nrr!Tdelgrouprrrrurr"r#r$rF)rrrXrrTrrr~rr1rr_rArGr9r)rhrrTrrrrr%remove_cmd_binrradd_cmd remove_cmdrrrrrrr sD  "  zBusyBox.modify_userN)rrrrrorqrrrrrrr  s E r c@seZdZdZdZdZdS)Alpinez This is the Alpine User manipulation class. It inherits the BusyBox class behaviors such as using adduser and deluser commands. LinuxN)rrrrr}rrrrrr+# sr+c Cs6tddddtd}ttdVidtddddgd d tdd d gd dtdddtddddtdddtddddtdddtdddtdddtdd ddtddd tdddd!tdddd"tdddd#tddd$tddd%tdddd&tdddd'tdd d(gd)d*tddd+tdddd,tdddd-tdddd.tddd/td|d0dd1td|d2dd3tddd4td|ddd5tdd dd6tdd7d7d8gdd9d:td;ddtddd?tddd@tdddAtddd dB}t|}||dC|j|jr4|dD|jd}dE}dE}i}|j |d <|j |d<|j dkr{| rz|j r[|j d dF|\}}}|dkrp|j|j ||dG|j|d%<|j|d&<n|j dkr | s|j r|j d dFd}|jr|jrtj|j}tj|sd }|\}}}|r|} | dur|| dH| dI|j|j r|j |d+<n|j|d+<|j|d'<n|\}}}|j|d-<|j|d,<|dur|dkr|j|j ||dG|jdur dJ|d<|durd|dK<nd |dK<|r!||dL<|r(||dM<| r|j dkr|} | durGdN|j |dO<d |dP<| dH|d<| dI|d<| dQ|d<| dR|d<| dS|d<|j durp|j |d<|} |jdur| dR|_tj!|js|jr|j s|"|j|| dH| dI|jd |dK<|j#r|$\}}}|dur|dkr|j|j ||dG|dkrd |dK<|%\}}}|dkr|&|dT<n|&|dT<|'|d3<|(|dU<|)\}}}|durn|dkr |j|j ||dGnd |dK<|j dVi|dS)WNrrsazansible-generated on %s)bitstype passphraser7r0rpresentabsent)r/defaultchoicesr1Tr)r/requiredaliasesr2r)r/r4rF)r/r3r6rTr)r/elementsr7rHrfr8r9)r/no_logr@rNrOrPr3r5r:r;r< createhome)r/r3r6r>r?r=rArBrCr.rDr/rWrErFrGr on_create)r/r3r4r8rVfloatrIrJrKrLrMrQ) argument_specsupports_check_modezUser instantiated - platform %sz#User instantiated - distribution %sr)rrrrsNOT_LOGGING_PASSWORDrr=r>zfailed to look up user name: %srSrvrrrssh_fingerprintrlr)*rsocket gethostnamerr$rrr}rr1r0r#rrzrqr_r:r;rHr<rerfrrrorrr?rrrAr=r9rTrrrZrhrirr5rmr,) ssh_defaultsrXrrrrresultpath_needs_parentsrrrrrmain, s`                        !" #$ % & ' ( ) * +-1                                      rE__main__)D __future__r DOCUMENTATIONEXAMPLESRETURN ctypes.utilrr rrer}rKrrRrxr@rNraransible.module_utilsr+ansible.module_utils.common.text.convertersrrransible.module_utils.basicr"ansible.module_utils.common.localer$ansible.module_utils.common.sys_infor "ansible.module_utils.compat.typing module_utilscompattypingt Structurer cdll LoadLibrarycastrutil find_libraryr rr!argtypesPOINTERrestyper&AttributeErrorcompilerobjectr$rrrrrrrrr r+rErrrrrs %=f        A /%!jJ  1