
    Vh~f                         d dl mZmZmZ eZdZdZdZd dl	m
Z
 d dlmZ d dlmZmZmZmZmZ d dlmZmZmZmZmZmZmZmZmZmZ d d	lmZ d
 Z e!dk(  r e         yy)    )absolute_importdivisionprint_functionuD)  
---
module: mysql_user
short_description: Adds or removes a user from a MySQL or MariaDB database
description:
   - Adds or removes a user from a MySQL or MariaDB database.
options:
  name:
    description:
      - Name of the user (role) to add or remove.
    type: str
    required: true
    aliases: ['user']
  password:
    description:
      - Set the user's password. Only for C(mysql_native_password) authentication.
        For other authentication plugins see the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string).
    type: str
  encrypted:
    description:
      - Indicate that the 'password' field is a `mysql_native_password` hash.
    type: bool
    default: false
  host:
    description:
      - The 'host' part of the MySQL username.
    type: str
    default: localhost
  host_all:
    description:
      - Override the host option, making ansible apply changes
        to all hostnames for a given user.
      - This option cannot be used when creating users.
    type: bool
    default: false
  priv:
    description:
      - "MySQL privileges string in the format: C(db.table:priv1,priv2)."
      - Additionally, there must be no spaces between the table and the privilege as this will yield a non-idempotent check mode.
      - "Multiple privileges can be specified by separating each one using
        a forward slash: C(db.table1:priv/db.table2:priv)."
      - The format is based on MySQL C(GRANT) statement.
      - Database and table names can be quoted, MySQL-style.
      - If column privileges are used, the C(priv1,priv2) part must be
        exactly as returned by a C(SHOW GRANT) statement. If not followed,
        the module will always report changes. It includes grouping columns
        by permission (C(SELECT(col1,col2)) instead of C(SELECT(col1),SELECT(col2))).
      - Can be passed as a dictionary (see the examples).
      - Supports GRANTs for procedures and functions (see the examples).
      - "Note: If you pass the same C(db.table) combination to this parameter
        two or more times with different privileges,
        for example, C('*.*:SELECT/*.*:SHOW VIEW'), only the last one will be applied,
        in this example, it will be C(SHOW VIEW) respectively.
        Use C('*.*:SELECT,SHOW VIEW') instead to apply both."
    type: raw
  append_privs:
    description:
      - Append the privileges defined by priv to the existing ones for this
        user instead of overwriting existing ones. Mutually exclusive with I(subtract_privs).
    type: bool
    default: false
  subtract_privs:
    description:
      - Revoke the privileges defined by the I(priv) option and keep other existing privileges.
        If set, invalid privileges in I(priv) are ignored.
        Mutually exclusive with I(append_privs).
    version_added: '3.2.0'
    type: bool
    default: false
  tls_requires:
    description:
      - Set requirement for secure transport as a dictionary of requirements (see the examples).
      - Valid requirements are SSL, X509, SUBJECT, ISSUER, CIPHER.
      - SUBJECT, ISSUER and CIPHER are complementary, and mutually exclusive with SSL and X509.
      - U(https://mariadb.com/kb/en/securing-connections-for-client-and-server/#requiring-tls).
    type: dict
    version_added: 1.0.0
  sql_log_bin:
    description:
      - Whether binary logging should be enabled or disabled for the connection.
    type: bool
    default: true
  force_context:
    description:
      - Sets the С(mysql) system database as context for the executed statements (it will be used
        as a database to connect to). Useful if you use binlog / replication filters in MySQL as
        per default the statements can not be caught by a binlog / replication filter, they require
        a database to be set to work, otherwise the replication can break down.
      - See U(https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#option_mysqld_binlog-ignore-db)
        for a description on how binlog filters work (filtering on the primary).
      - See U(https://dev.mysql.com/doc/refman/8.0/en/replication-options-replica.html#option_mysqld_replicate-ignore-db)
        for a description on how replication filters work (filtering on the replica).
    type: bool
    default: false
    version_added: '3.1.0'
  state:
    description:
      - Whether the user should exist.
      - When C(absent), removes the user.
    type: str
    choices: [ absent, present ]
    default: present
  check_implicit_admin:
    description:
      - Check if mysql allows login as root/nopassword before trying supplied credentials.
      - If success, passed I(login_user)/I(login_password) will be ignored.
    type: bool
    default: false
  update_password:
    description:
      - C(always) will update passwords if they differ. This affects I(password) and the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string).
      - C(on_create) will only set the password or the combination of I(plugin), I(plugin_hash_string), I(plugin_auth_string) for newly created users.
      - "C(on_new_username) works like C(on_create), but it tries to reuse an existing password: If one different user
        with the same username exists, or multiple different users with the same username and equal C(plugin) and
        C(authentication_string) attribute, the existing C(plugin) and C(authentication_string) are used for the
        new user instead of the I(password), I(plugin), I(plugin_hash_string) or I(plugin_auth_string) argument."
    type: str
    choices: [ always, on_create, on_new_username ]
    default: always
  plugin:
    description:
      - User's plugin to authenticate (``CREATE USER user IDENTIFIED WITH plugin``).
    type: str
    version_added: '0.1.0'
  plugin_hash_string:
    description:
      - User's plugin hash string (``CREATE USER user IDENTIFIED WITH plugin AS plugin_hash_string``).
    type: str
    version_added: '0.1.0'
  plugin_auth_string:
    description:
      - User's plugin auth_string (``CREATE USER user IDENTIFIED WITH plugin BY plugin_auth_string``).
      - If I(plugin) is ``pam`` (MariaDB) or ``auth_pam`` (MySQL) an optional I(plugin_auth_string) can be used to choose a specific PAM service.
      - You need to define a I(salt) to have idempotence on password change with ``caching_sha2_password`` and ``sha256_password`` plugins.
    type: str
    version_added: '0.1.0'
  salt:
    description:
      - Salt used to generate password hash from I(plugin_auth_string).
      - Salt length must be 20 characters.
      - Salt only support ``caching_sha2_password`` or ``sha256_password`` authentication I(plugin).
    type: str
    version_added: '3.10.0'
  resource_limits:
    description:
      - Limit the user for certain server resources. Provided since MySQL 5.6 / MariaDB 10.2.
      - "Available options are C(MAX_QUERIES_PER_HOUR: num), C(MAX_UPDATES_PER_HOUR: num),
        C(MAX_CONNECTIONS_PER_HOUR: num), C(MAX_USER_CONNECTIONS: num), C(MAX_STATEMENT_TIME: num) (supported only for MariaDB since collection version 3.7.0)."
      - Used when I(state=present), ignored otherwise.
    type: dict
    version_added: '0.1.0'
  session_vars:
    description:
      - "Dictionary of session variables in form of C(variable: value) to set at the beginning of module execution."
      - Cannot be used to set global variables, use the M(community.mysql.mysql_variables) module instead.
    type: dict
    version_added: '3.6.0'
  password_expire:
    description:
      - C(never) - I(password) will never expire.
      - C(default) - I(password) is defined using global system variable I(default_password_lifetime) setting.
      - C(interval) - I(password) will expire in days which is defined in I(password_expire_interval).
      - C(now) - I(password) will expire immediately.
    type: str
    choices: [ now, never, default, interval ]
    version_added: '3.9.0'
  password_expire_interval:
    description:
      - Number of days I(password) will expire. Requires I(password_expire=interval).
    type: int
    version_added: '3.9.0'

  column_case_sensitive:
    description:
      - The default is C(false).
      - When C(true), the module will not uppercase the field names in the privileges.
      - When C(false), the field names will be upper-cased. This is the default
      - This feature was introduced because MySQL 8 and above uses case sensitive
        fields names in privileges.
    type: bool
    version_added: '3.8.0'

  locked:
    description:
      - Lock account to prevent connections using it.
      - This is primarily used for creating a user that will act as a DEFINER on stored procedures.
      - If not specified leaves the lock state as is (for a new user creates unlocked).
    type: bool
    version_added: '3.13.0'

  attributes:
    description:
      - "Create, update, or delete user attributes (arbitrary 'key: value' comments) for the user."
      - MySQL server must support the INFORMATION_SCHEMA.USER_ATTRIBUTES table. Provided since MySQL 8.0.
      - To delete an existing attribute, set its value to null.
    type: dict
    version_added: '3.9.0'

notes:
   - Compatible with MySQL or MariaDB.
   - "MySQL server installs with default I(login_user) of C(root) and no password.
     To secure this user as part of an idempotent playbook, you must create at least two tasks:
     1) change the root user's password, without providing any I(login_user)/I(login_password) details,
     2) drop a C(~/.my.cnf) file containing the new root credentials.
     Subsequent runs of the playbook will then succeed by reading the new credentials from the file."
   - Currently, there is only support for the C(mysql_native_password) encrypted password hash module.

attributes:
  check_mode:
    support: full

seealso:
- module: community.mysql.mysql_info
- name: MySQL access control and account management reference
  description: Complete reference of the MySQL access control and account management documentation.
  link: https://dev.mysql.com/doc/refman/8.0/en/access-control.html
- name: MySQL provided privileges reference
  description: Complete reference of the MySQL provided privileges documentation.
  link: https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html

author:
- Jonathan Mainguy (@Jmainguy)
- Benjamin Malynovytch (@bmalynovytch)
- Lukasz Tomaszkiewicz (@tomaszkiewicz)
- kmarse (@kmarse)
- Laurent Indermühle (@laurent-indermuehle)
- E.S. Rosenberg (@Keeper-of-the-Keys)

extends_documentation_fragment:
- community.mysql.mysql
a  
# If you encounter the "Please explicitly state intended protocol" error,
# use the login_unix_socket argument
- name: Removes anonymous user account for localhost
  community.mysql.mysql_user:
    name: ''
    host: localhost
    state: absent
    login_unix_socket: /run/mysqld/mysqld.sock

- name: Removes all anonymous user accounts
  community.mysql.mysql_user:
    name: ''
    host_all: true
    state: absent

- name: Create database user with name 'bob' and password '12345' with all database privileges
  community.mysql.mysql_user:
    name: bob
    password: 12345
    priv: '*.*:ALL'
    state: present

- name: Create database user using hashed password with all database privileges
  community.mysql.mysql_user:
    name: bob
    password: '*EE0D72C1085C46C5278932678FBE2C6A782821B4'
    encrypted: true
    priv: '*.*:ALL'
    state: present

# Set session var wsrep_on=off before creating the user
- name: Create database user with password and all database privileges and 'WITH GRANT OPTION'
  community.mysql.mysql_user:
    name: bob
    password: 12345
    priv: '*.*:ALL,GRANT'
    state: present
    session_vars:
      wsrep_on: 'off'

- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2
  community.mysql.mysql_user:
    state: present
    name: bob
    password: 12345dd
    priv:
      'db1.*': 'ALL,GRANT'
      'db2.*': 'ALL,GRANT'

# Use 'PROCEDURE' instead of 'FUNCTION' to apply GRANTs for a MySQL procedure instead.
- name: Grant a user the right to execute a function
  community.mysql.mysql_user:
    name: readonly
    password: 12345
    priv:
      FUNCTION my_db.my_function: EXECUTE
    state: present

- name: Modify user attributes, creating the attribute 'foo' and removing the attribute 'bar'
  community.mysql.mysql_user:
    name: bob
    attributes:
      foo: "foo"
      bar: null

- name: Modify user to require TLS connection with a valid client certificate
  community.mysql.mysql_user:
    name: bob
    tls_requires:
      x509:
    state: present

- name: Modify user to require TLS connection with a specific client certificate and cipher
  community.mysql.mysql_user:
    name: bob
    tls_requires:
      subject: '/CN=alice/O=MyDom, Inc./C=US/ST=Oregon/L=Portland'
      cipher: 'ECDHE-ECDSA-AES256-SHA384'

- name: Modify user to no longer require SSL
  community.mysql.mysql_user:
    name: bob
    tls_requires:

- name: Ensure no user named 'sally'@'localhost' exists, also passing in the auth credentials
  community.mysql.mysql_user:
    login_user: root
    login_password: 123456
    name: sally
    state: absent

# check_implicit_admin example
- name: >
    Ensure no user named 'sally'@'localhost' exists, also passing in the auth credentials.
    If mysql allows root/nopassword login, try it without the credentials first.
    If it's not allowed, pass the credentials
  community.mysql.mysql_user:
    check_implicit_admin: true
    login_user: root
    login_password: 123456
    name: sally
    state: absent

- name: Ensure no user named 'sally' exists at all
  community.mysql.mysql_user:
    name: sally
    host_all: true
    state: absent

- name: Specify grants composed of more than one word
  community.mysql.mysql_user:
    name: replication
    password: 12345
    priv: "*.*:REPLICATION CLIENT"
    state: present

- name: Revoke all privileges for user 'bob' and password '12345'
  community.mysql.mysql_user:
    name: bob
    password: 12345
    priv: "*.*:USAGE"
    state: present

# Example privileges string format
# mydb.*:INSERT,UPDATE/anotherdb.*:SELECT/yetanotherdb.*:ALL

- name: Example using login_unix_socket to connect to server
  community.mysql.mysql_user:
    name: root
    password: abc123
    login_unix_socket: /var/run/mysqld/mysqld.sock

- name: Example of skipping binary logging while adding user 'bob'
  community.mysql.mysql_user:
    name: bob
    password: 12345
    priv: "*.*:USAGE"
    state: present
    sql_log_bin: false

- name: Create user 'bob' authenticated with plugin 'AWSAuthenticationPlugin'
  community.mysql.mysql_user:
    name: bob
    plugin: AWSAuthenticationPlugin
    plugin_hash_string: RDS
    priv: '*.*:ALL'
    state: present

- name: Create user 'bob' authenticated with plugin 'caching_sha2_password' and static salt
  community.mysql.mysql_user:
    name: bob
    plugin: caching_sha2_password
    plugin_auth_string: password
    salt: 1234567890abcdefghij

- name: Limit bob's resources to 10 queries per hour and 5 connections per hour
  community.mysql.mysql_user:
    name: bob
    resource_limits:
      MAX_QUERIES_PER_HOUR: 10
      MAX_CONNECTIONS_PER_HOUR: 5

- name: Ensure bob does not have the DELETE privilege
  community.mysql.mysql_user:
    name: bob
    subtract_privs: true
    priv:
      'db1.*': DELETE

- name: Create locked user to act as a definer on procedures
  community.mysql.mysql_user:
    name: readonly_procedures_locked
    locked: true
    priv:
      db1.*: SELECT

# Example .my.cnf file for setting the root password
# [client]
# user=root
# password=n<_665{vS43y
#)AnsibleModule)SQLParseError)mysql_connectmysql_drivermysql_driver_fail_msgmysql_common_argument_specset_session_vars)
convert_priv_dict_to_strget_modeInvalidPrivsErrorlimit_resourcesprivileges_unpacksanitize_requiresuser_adduser_deleteuser_existsuser_mod)	to_nativec                     t               } | j                  t        dddgddddg      t        dd      t        d	d
      t        dd      t        d	d
      t        ddddg      t        d      t        d      t        d	d
      t        d	d
      t        d      t        d	d
      t        ddg dd
      t        d	d      t        d d      t        d d      t        d d      t        d d      t        d      t        d	d
      t        d      t        d	d       t        dg dd      t        ddgd      t        d	             t        | dd      }|j                  d   }|j                  d    }|j                  d!   }|j                  d"   }|j                  |j                  d#         }|j                  d$   j                         }|j                  d%   }|j                  d&   }	|j                  d'   }
t        |j                  d(         }|j                  d)   }|j                  d*   }|j                  d+   }|j                  |j                  d,         }|j                  |j                  d-         }|j                  d.   }|j                  d/   }|j                  d0   }|j                  d1   }|j                  d2   }|j                  d3   }d4}|j                  d5   rd6}|j                  d7   }|j                  d8   }|j                  d9   }|j                  d:   }|j                  d;   }|j                  d<   }|j                  d=   }|j                  d>   }|j                  d?   } |j                  d@   }!|j                  |j                  dA         }"|
r4t        |
t        t        f      s|j                  dBt        |
      z  C       |
rt        |
t              rt        |
      }
t        |j                  t        C       |!r|!dDk  r|j                  dEC       |rJ|s|j                  dFC       t        |      dGk7  r|j                  dHC       |dIvr|j                  dJC       d }#	 |r	 t!        |dKd4|||||||dL      \  }#}$|#st!        ||||||||||dL      \  }#}$|d
}|j'                  dO       |s|#j)                  dP       |rt+        ||#|       |
	 t-        |#      }&t/        |
&|| Q      }
d
}'d }(|	dk(  rt1        |#|||      r|	 |dk(  rt3        |#||||||||||
|||||| |!|"R      })nBt3        d_i dS|#d|d$|d%|d"d d#|d8d d9d d:d d;d dT|
d,|d-|d/|d(|dU|d?| d@|!dA|"})|)dV   }*|)dW   }+|)dX   }'|)d/   }(nN|r|j                  dYC       	 |rd }
|dZk(  },t;        |#||||||||||
|||,|| |!|"R      })|)dV   }*|)dX   }'|)d/   }(|*rd[}+|rRt=        ||#||||j>                        xs *}*n3|	dk(  r.t1        |#|||      rtA        |#||||j>                        }*d\}+nd
}*d]}+|jC                  *|+|'|(^       y # t"        $ r Y w xY w# t"        $ r,}%|j                  dM|dNt%        |%      C       Y d }%~%d }%~%ww xY w# t"        $ r&}%|j                  t%        |%      C       Y d }%~%d }%~%ww xY w# t4        t6        t        j8                  f$ r&}%|j                  t%        |%      C       Y d }%~%$d }%~%ww xY w# t4        t6        t        j8                  f$ r&}%|j                  t%        |%      C       Y d }%~%kd }%~%ww xY w)`NstrTuserz5.0.0zcommunity.mysql)nameversioncollection_name)typerequiredaliasesdeprecated_aliases)r   no_logboolF)r   default	localhostpresentabsent)r   r%   choicesraw)r   dictalways)r,   	on_createon_new_username)r   r%   r)   r#   )r%   r   )nowneverr%   interval)r   r)   r#   int)password_expirer1   T)r   required_ifr#   )r   password	encryptedhosthost_allstateprivtls_requiresappend_privssubtract_privs
attributescheck_implicit_adminupdate_passwordsql_log_binpluginplugin_hash_stringplugin_auth_stringsaltresource_limitsforce_contextsession_varscolumn_case_sensitiver3   password_expire_intervallocked))r<   r=   )argument_specsupports_check_modemutually_exclusive
login_userlogin_passwordr   r5   r6   r7   r8   r9   r:   r;   r?   connect_timeoutconfig_filer<   r=   r@   r>   client_cert
client_keyca_certcheck_hostname rG   mysqlrA   rB   rC   rD   rE   rF   rH   rI   r3   rJ   rK   z4priv parameter must be str or dict but %s was passed)msg   zUpassword_expire_interval value                              should be positive numberz salt requires plugin_auth_string   zsalt must be 20 characters long)caching_sha2_passwordsha256_passwordz=salt requires caching_sha2_password or sha256_password pluginroot)rQ   rV   
autocommitzRunable to connect to database, check login_user and login_password are correct or z) has the credentials. Exception message: zOption column_case_sensitive is not provided. The default is now false, so the column's name will be uppercased. The default will be changed to true in community.mysql 4.0.0.zSET SQL_LOG_BIN=0;)ensure_usage)rK   cursornew_privmodulechangedrY   password_changedz4host_all parameter cannot be used when adding a userr.   z
User addedzUser deletedzUser doesn't exist)rd   r   rY   re   r>    )"r   updater+   r   paramsbooleanlowerr   
isinstancer   	fail_jsonr   r   r
   r   lenr	   	Exceptionr   warnexecuter   r   r   r   r   r   r   Errorr   r   
check_moder   	exit_json)-rL   rc   rO   rP   r   r5   r6   r7   r8   r9   r:   r;   r?   rQ   rR   r<   r=   r@   r>   ssl_certssl_keyssl_carV   dbrA   rB   rC   rD   rE   rF   rH   rI   r3   rJ   rK   ra   db_connemodere   final_attributesresultrd   rY   reuse_existing_passwords-                                                n/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/mysql/plugins/modules/mysql_user.pymainr     s`   .0MutfX"#4S 
 5.FE2uk2651y8Y:OPuv&vu57V$!vu=%Cmv{|fd3Du-5959$U+&)6v&"=%1Xaef!%5?d>enr!s ?   B # @F
 |,J]]#34N== D}}Z(Hv}}[9:I== &&(D}}Z(HMM'"E== D$V]]>%BCL!==)?@mm$56O--.K>>&--"?@L^^FMM2B$CDNmm$56O|,J}}]+HmmL)G]]9%F]]#34N	B}}_%--.K]]8$F';<';<== Dmm$56O==0L"MM*ABmm$56O%}}-GH^^FMM(34FJtc4[1SVZ[_V``a
4&'-23$<q$@ 8 	9 !!CDt9?!BCEE!`aFT"/KQY[bdjln@O`n{#A
 +FJP[]egnpvxz<K\jw{}OFG $ % T 	U +,6	/F#D !t-BUcQcd	vtT843"h.%fdD(Hi&,.@BTVZ&*L.*Vbdj&57OX^`F & 5V 5$ 5T 5T\ 5gk 5095BF5[_5tx5+/5:>5MY5jx5 2<5 KW5 `f5 7F	5 ay	5
 .45F !+Um#)*<#= #),#7 
   %[ \3!D*9=N*N'!&$h)"(*<>PRV"&
LBY[a"13KTZ\ !+#)*<#= #),#7 &C
 %ffdD/SYSdSdepipG	(	vtT84!&$h@Q@QRG CG&C
W4SK[hxyk    T8CYq\S 	T 	TT(  	/1..	/6 "#4l6H6HI 3  Yq\ 223& "#4l6H6HI 3  Yq\ 223s   Y) Y Y) 2Z! %A:[ 59\ 	Y&"Y) %Y&&Y) )	Z2!ZZ!	[*[[\1\\]8]]__main__N)"
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNansible.module_utils.basicr   Aansible_collections.community.mysql.plugins.module_utils.databaser   >ansible_collections.community.mysql.plugins.module_utils.mysqlr	   r
   r   r   r   =ansible_collections.community.mysql.plugins.module_utils.userr   r   r   r   r   r   r   r   r   r   ansible.module_utils._textr   r   __name__rf       r~   <module>r      sl    A @fPun 
 4 [    1|z~ zF r   