
    VhH                        d dl mZmZmZ eZdZdZdZd dl	Z	d dl
Z
d dlmZmZ d dlmZ d dlmZmZ d d	lmZmZ d d
lmZmZmZ d dlmZmZ d dlmZ dZdZ dZ!	 d dl"Z"d dl#m$Z$ d dl%m&Z'  ee"jP                        Z)dZ* G d de      Z- G d de      Z.d Z/e0dk(  r e/        yy# e+$ r  e
jX                         Z!dZ*Y Aw xY w)    )absolute_importdivisionprint_functiona  
module: openssl_publickey
short_description: Generate an OpenSSL public key from its private key
description:
  - This module allows one to (re)generate public keys from their private keys.
  - Public keys are generated in PEM or OpenSSH format. Private keys must be OpenSSL PEM keys. B(OpenSSH private keys are
    not supported), use the M(community.crypto.openssh_keypair) module to manage these.
  - The module uses the cryptography Python library.
requirements:
  - cryptography >= 1.2.3 (older versions might work as well)
  - Needs cryptography >= 1.4 if O(format) is C(OpenSSH)
author:
  - Yanis Guenane (@Spredzy)
  - Felix Fontein (@felixfontein)
extends_documentation_fragment:
  - ansible.builtin.files
  - community.crypto.attributes
  - community.crypto.attributes.files
attributes:
  check_mode:
    support: full
  diff_mode:
    support: full
  safe_file_operations:
    support: full
  idempotent:
    support: partial
    details:
      - The module is not idempotent if O(force=true).
options:
  state:
    description:
      - Whether the public key should exist or not, taking action if the state is different from what is stated.
    type: str
    default: present
    choices: [absent, present]
  force:
    description:
      - Should the key be regenerated even it it already exists.
    type: bool
    default: false
  format:
    description:
      - The format of the public key.
    type: str
    default: PEM
    choices: [OpenSSH, PEM]
  path:
    description:
      - Name of the file in which the generated TLS/SSL public key will be written.
    type: path
    required: true
  privatekey_path:
    description:
      - Path to the TLS/SSL private key from which to generate the public key.
      - Either O(privatekey_path) or O(privatekey_content) must be specified, but not both. If O(state) is V(present), one
        of them is required.
    type: path
  privatekey_content:
    description:
      - The content of the TLS/SSL private key from which to generate the public key.
      - Either O(privatekey_path) or O(privatekey_content) must be specified, but not both. If O(state) is V(present), one
        of them is required.
    type: str
    version_added: '1.0.0'
  privatekey_passphrase:
    description:
      - The passphrase for the private key.
    type: str
  backup:
    description:
      - Create a backup file including a timestamp so you can get the original public key back if you overwrote it with a
        different one by accident.
    type: bool
    default: false
  select_crypto_backend:
    description:
      - Determines which crypto backend to use.
      - The default choice is V(auto), which tries to use C(cryptography) if available.
      - If set to V(cryptography), will try to use the L(cryptography,https://cryptography.io/) library.
    type: str
    default: auto
    choices: [auto, cryptography]
  return_content:
    description:
      - If set to V(true), will return the (current or generated) public key's content as RV(publickey).
    type: bool
    default: false
    version_added: '1.0.0'
seealso:
  - module: community.crypto.x509_certificate
  - module: community.crypto.x509_certificate_pipe
  - module: community.crypto.openssl_csr
  - module: community.crypto.openssl_csr_pipe
  - module: community.crypto.openssl_dhparam
  - module: community.crypto.openssl_pkcs12
  - module: community.crypto.openssl_privatekey
  - module: community.crypto.openssl_privatekey_pipe
a  
---
- name: Generate an OpenSSL public key in PEM format
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    privatekey_path: /etc/ssl/private/ansible.com.pem

- name: Generate an OpenSSL public key in PEM format from an inline key
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    privatekey_content: "{{ private_key_content }}"

- name: Generate an OpenSSL public key in OpenSSH v2 format
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    privatekey_path: /etc/ssl/private/ansible.com.pem
    format: OpenSSH

- name: Generate an OpenSSL public key with a passphrase protected private key
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    privatekey_path: /etc/ssl/private/ansible.com.pem
    privatekey_passphrase: ansible

- name: Force regenerate an OpenSSL public key if it already exists
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    privatekey_path: /etc/ssl/private/ansible.com.pem
    force: true

- name: Remove an OpenSSL public key
  community.crypto.openssl_publickey:
    path: /etc/ssl/public/ansible.com.pem
    state: absent
a  
privatekey:
  description:
    - Path to the TLS/SSL private key the public key was generated from.
    - Will be V(none) if the private key has been provided in O(privatekey_content).
  returned: changed or success
  type: str
  sample: /etc/ssl/private/ansible.com.pem
format:
  description: The format of the public key (PEM, OpenSSH, ...).
  returned: changed or success
  type: str
  sample: PEM
filename:
  description: Path to the generated TLS/SSL public key file.
  returned: changed or success
  type: str
  sample: /etc/ssl/public/ansible.com.pem
fingerprint:
  description:
    - The fingerprint of the public key. Fingerprint will be generated for each hashlib.algorithms available.
  returned: changed or success
  type: dict
  sample:
    md5: "84:75:71:72:8d:04:b5:6c:4d:37:6d:66:83:f5:4c:29"
    sha1: "51:cc:7c:68:5d:eb:41:43:88:7e:1a:ae:c7:f8:24:72:ee:71:f6:10"
    sha224: "b1:19:a6:6c:14:ac:33:1d:ed:18:50:d3:06:5c:b2:32:91:f1:f1:52:8c:cb:d5:75:e9:f5:9b:46"
    sha256: "41:ab:c7:cb:d5:5f:30:60:46:99:ac:d4:00:70:cf:a1:76:4f:24:5d:10:24:57:5d:51:6e:09:97:df:2f:de:c7"
    sha384: "85:39:50:4e:de:d9:19:33:40:70:ae:10:ab:59:24:19:51:c3:a2:e4:0b:1c:b1:6e:dd:b3:0c:d9:9e:6a:46:af:da:18:f8:ef:ae:2e:c0:9a:75:2c:9b:b3:0f:3a:5f:3d"
    sha512: "fd:ed:5e:39:48:5f:9f:fe:7f:25:06:3f:79:08:cd:ee:a5:e7:b3:3d:13:82:87:1f:84:e1:f5:c7:28:77:53:94:86:56:38:69:f0:d9:35:22:01:1e:a6:60:...:0f:9b"
backup_file:
  description: Name of backup file created.
  returned: changed and if O(backup) is V(true)
  type: str
  sample: /path/to/publickey.pem.2019-03-09@11:22~
publickey:
  description: The (current or generated) public key's content.
  returned: if O(state) is V(present) and O(return_content) is V(true)
  type: str
  version_added: '1.0.0'
N)AnsibleModulemissing_required_lib)	to_native)OpenSSLBadPassphraseErrorOpenSSLObjectError)PublicKeyParseErrorget_publickey_info)OpenSSLObjectget_fingerprintload_privatekey)load_file_if_exists
write_file)LooseVersionz1.2.3z1.4)default_backend)serializationTFc                       e Zd Zy)PublicKeyErrorN)__name__
__module____qualname__     v/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/crypto/plugins/modules/openssl_publickey.pyr   r      s    r   r   c                   L     e Zd Z fdZd Zd Zd Zd fd	Z fdZd Z	 xZ
S )		PublicKeyc                    t         t        |   |j                  d   |j                  d   |j                  d   |j                         || _        |j                  d   | _        |j                  d   | _        |j                  d   | _        | j                   | j                  j                  d      | _        |j                  d   | _
        d | _        d | _        |j                  d	   | _        i | _        || _        |j                  d
   | _        d | _        | j%                  d       | _        | j%                  d       | _        y )Npathstateforceformatprivatekey_pathprivatekey_contentutf-8privatekey_passphrasereturn_contentbackup)superr   __init__params
check_modemoduler#   r$   r%   encoder'   
privatekeypublickey_bytesr(   fingerprintbackendr)   backup_file	_get_infodiff_before
diff_after)selfr.   r3   	__class__s      r   r+   zPublicKey.__init__   s   i'MM&!MM'"MM'"		
 mmH-%}}->?"(--0D"E"".&*&=&=&D&DW&MD#%+]]3J%K"#$mm,<=mmH->>$/...r   c                     |
t               S t        d      }	 |j                  t        | j                  | j                  |d             d|d<   |S # t
        $ r&}|j                  |j                         Y d }~|S d }~wt        $ r Y |S w xY w)NF)can_parse_keyT)contentprefer_one_fingerprintr;   )dictupdater   r.   r3   r   result	Exception)r8   datar@   excs       r   r5   zPublicKey._get_info  s    <6ME*
	MM"KKtTX
 '+F?#
 	 # 	&MM#**%%   		s   7A 	BA==BBc                     t        | j                  | j                  | j                  | j                        | _        | j                  dk(  r| j                  dk(  rZ| j
                  j                         j                  t        j                  j                  t        j                  j                        S | j
                  j                         j                  t        j                  j                  t        j                  j                        S y )Nr    r<   
passphraser3   cryptographyOpenSSH)r   r$   r%   r'   r3   r0   r#   
public_keypublic_bytescrypto_serializationEncodingrH   PublicFormatPEMSubjectPublicKeyInfo)r8   r.   s     r   _create_publickeyzPublicKey._create_publickey  s    )%%++11LL	
 <<>){{i'113@@(1199(55== 
 113@@(1155(55JJ  *r   c                 \   | j                   At        j                  j                  | j                        st        d| j                  z        | j                  |d      r| j                  rz	 | j                  |      }| j                  |      | _
        | j                  r|| _        | j                  r |j                  | j                        | _        t!        ||       d| _        t+        | j                  | j                   | j,                  | j.                        | _        |j3                  |j4                        }|j7                  |d         rd| _        y|j9                  |d      rd| _        yy# t$        $ r}t        |      d}~wt&        t(        f$ r}t        |      d}~ww xY w)zGenerate the public key.Nz!The private key %s does not existF)perms_requiredTrE   r    )r%   osr    existsr$   r   checkr"   rP   r5   r7   r(   r1   r)   backup_localr4   r   changedr	   IOErrorOSErrorr   r'   r3   r2   load_file_common_argumentsr,   check_file_absent_if_check_modeset_fs_attributes_if_different)r8   r.   publickey_contentrC   	file_argss        r   generatezPublicKey.generate0  st    ""*277>>$BVBV3W 3d6J6JJ  zz&z74::*$($:$:6$B!"&..1B"C&&+<D(;;'-':':499'ED$6#45# +%%++11LL	
 55fmmD	11)F2CDDL229eDDL E - *$S))W% *$S))*s%   .A9E5 5	F+>F		F+F&&F+c                 R     t         t           |      } fd}|s|S  |       S )z,Ensure the resource is in its desired state.c                     j                   *t        j                  j                  j                        sy	 t        j                  d      5 } | j                         }d d d        j                        x_        _	        j                  r|_        j                  dk(  r҉j                  dk(  rbt        j                  |t!                     }|j#                  t        j$                  j&                  t        j(                  j&                        }nat        j*                  |t!                     }|j#                  t        j$                  j,                  t        j(                  j.                        }	 j3                        }||k(  S # 1 sw Y   2xY w# t0        $ r Y yw xY w# t4        $ r}t7        |      d }~ww xY w)NFrbrG   rH   )r3   )r%   rS   r    rT   r$   openreadr5   r6   r7   r(   r1   r3   r#   rK   load_ssh_public_keyr   rJ   rL   rH   rM   load_pem_public_keyrN   rO   rA   rP   r	   r   )public_key_fhr]   current_publickeydesired_publickeyrC   r.   r8   s        r   _check_privatekeyz*PublicKey.check.<locals>._check_privatekeyZ  s   &&.rww~~$$8 $))T* =m(5(:(:(<%=59^^DU5VV 4?&&+<D(<<>1{{i/,@,T,T-7H-) ->,J,J099AA0==EE-)
 -A,T,T-7H-) ->,J,J099==0==RR-)*$($:$:6$B! %(999?= =.  
 - *$S))*sB   F F DF :F, FF 	F)(F),	G5G  G)r*   r   rU   )r8   r.   rR   state_and_permsrj   r9   s   ``   r   rU   zPublicKey.checkU  s2      	46v~N&	:P "" ""r   c                     | j                   r |j                  | j                        | _        t        t
        |   |       y )N)r)   rV   r    r4   r*   r   remove)r8   r.   r9   s     r   rm   zPublicKey.remove  s0    ;;%22499=Di%f-r   c                    | j                   | j                  | j                  | j                  | j                  d}| j
                  r| j
                  |d<   | j                  rT| j                  t        | j                  d      | _        | j                  r| j                  j                  d      nd|d<   t        | j                  | j                        |d	<   |S )
z'Serialize the object into a dictionary.)r0   filenamer#   rW   r2   r4   NT)ignore_errorsr&   	publickey)beforeafterdiff)r$   r    r#   rW   r2   r4   r(   r1   r   decoder>   r6   r7   )r8   r@   s     r   dumpzPublicKey.dump  s     ..		kk||++
 $($4$4F=!##+':IIT($ 9=8L8L$$++G4RV ; ##//
v
 r   )T)r   r   r   r+   r5   rP   r_   rU   rm   rv   __classcell__)r9   s   @r   r   r      s(    /4"&# J0#d.
r   r   c                  L   t        t        t        ddddg      t        dd      t        dd	
      t        d      t        dd	      t        ddddg      t        dd	      t        dd      t        dddgd      t        dd      
      d	d	ddddgd	fgddgf      } t        }| j                  d   dk(  rt        }| j                  d   }|dk(  rDt
        xr t        t        |      k\  }|rd}|dk(  r!| j                  dj                  |             | j                  d   dk(  r|dk7  r| j                  d       |dk(  r5t
        s/| j                  t        dj                  |            t               t        j                  j                  | j                  d         xs d}t        j                  j                  |      s| j                  |d|z          	 t!        | |      }|j"                  dk(  rf| j$                  rH|j'                         }| j                  d!   xs |j)                  |        |d"<    | j*                  d#i | |j-                  |        nn| j$                  rQ|j'                         }t        j                  j/                  | j                  d         |d"<    | j*                  d#i | |j1                  |        |j'                         } | j*                  d#i | y # t2        $ r%}| j                  t5        |             Y d }~y d }~ww xY w)$Nstrpresentabsent)typedefaultchoicesboolF)r|   r}   r    T)r|   required)r|   )r|   no_logrN   rH   autorG   )r|   r~   r}   )
r!   r"   r    r$   r%   r#   r'   r)   select_crypto_backendr(   r!   r$   r%   )argument_specsupports_check_modeadd_file_common_argsrequired_ifmutually_exclusiver#   r   z?Cannot detect the required Python library cryptography (>= {0}))msgz1Format OpenSSH requires the cryptography backend.zcryptography >= {0})r   	exception.z@The directory '%s' does not exist or the file is not a directory)namer   r"   rW   r   )r   r>   MINIMAL_CRYPTOGRAPHY_VERSIONr,   $MINIMAL_CRYPTOGRAPHY_VERSION_OPENSSHCRYPTOGRAPHY_FOUNDCRYPTOGRAPHY_VERSIONr   	fail_jsonr#   r   CRYPTOGRAPHY_IMP_ERRrS   r    dirnameisdirr   r!   r-   rv   rU   	exit_jsonr_   rT   rm   r
   r   )r.   minimal_cryptography_versionr3   can_use_cryptographybase_dirrI   r@   rC   s           r   mainr     s#   E9y(>STFE26D1 f-#t<UEIu;MN"&E$"?VU3"&V^$<f#  VU;
 !!i"35I!JDQ
 /0DEG)F. $@ }}X)+'K$mm34G&  S$5Q(RR 	  $G fX&56   }}X)+>0IPQ. !()001MN /	   wwv}}V45<H77=="R 	 	
-vw/
y(  #*$*MM'$: %*BRBRC ?y! !  *6*'  #*$&GGNN6==3H$Iy!   *6*f%""6" -Ys^,,-s   #DK5 5	L#>LL#__main__)1
__future__r   r   r   r|   __metaclass__DOCUMENTATIONEXAMPLESRETURNrS   	tracebackansible.module_utils.basicr   r   +ansible.module_utils.common.text.convertersr   Fansible_collections.community.crypto.plugins.module_utils.crypto.basicr	   r
   _ansible_collections.community.crypto.plugins.module_utils.crypto.module_backends.publickey_infor   r   Hansible_collections.community.crypto.plugins.module_utils.crypto.supportr   r   r   <ansible_collections.community.crypto.plugins.module_utils.ior   r   Aansible_collections.community.crypto.plugins.module_utils.versionr   r   r   r   rG   cryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   rK   __version__r   r   ImportError
format_excr   r   r   r   r   r   r   <module>r      s    A @ bH"H(
T 
  J A 

  ' ', $ 
<T'(@(@A
 	' 	v vr\-~ zF G	  /9//1s   "B# #B>=B>