
    VhW                         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Zd dlmZ d dlmZ d dlmZ d	 Zd
 Zd Zd Zd Zd ZddZd Zd Zd Zd Zd Zd Zd Zd Z d Z!e"dk(  r e!        yy)    )absolute_importdivisionprint_functionaz  
module: java_cert

short_description: Uses keytool to import/remove certificate to/from java keystore (cacerts)
description:
  - This is a wrapper module around keytool, which can be used to import certificates and optionally private keys to a given
    java keystore, or remove them from it.
extends_documentation_fragment:
  - community.general.attributes
  - ansible.builtin.files
attributes:
  check_mode:
    support: full
  diff_mode:
    support: full
options:
  cert_url:
    description:
      - Basic URL to fetch SSL certificate from.
      - Exactly one of O(cert_url), O(cert_path), O(cert_content), or O(pkcs12_path) is required to load certificate.
    type: str
  cert_port:
    description:
      - Port to connect to URL.
      - This will be used to create server URL:PORT.
    type: int
    default: 443
  cert_path:
    description:
      - Local path to load certificate from.
      - Exactly one of O(cert_url), O(cert_path), O(cert_content), or O(pkcs12_path) is required to load certificate.
    type: path
  cert_content:
    description:
      - Content of the certificate used to create the keystore.
      - Exactly one of O(cert_url), O(cert_path), O(cert_content), or O(pkcs12_path) is required to load certificate.
    type: str
    version_added: 8.6.0
  cert_alias:
    description:
      - Imported certificate alias.
      - The alias is used when checking for the presence of a certificate in the keystore.
    type: str
  trust_cacert:
    description:
      - Trust imported cert as CAcert.
    type: bool
    default: false
    version_added: '0.2.0'
  pkcs12_path:
    description:
      - Local path to load PKCS12 keystore from.
      - Unlike O(cert_url), O(cert_path) and O(cert_content), the PKCS12 keystore embeds the private key matching the certificate,
        and is used to import both the certificate and its private key into the java keystore.
      - Exactly one of O(cert_url), O(cert_path), O(cert_content), or O(pkcs12_path) is required to load certificate.
    type: path
  pkcs12_password:
    description:
      - Password for importing from PKCS12 keystore.
    type: str
  pkcs12_alias:
    description:
      - Alias in the PKCS12 keystore.
    type: str
  keystore_path:
    description:
      - Path to keystore.
    type: path
  keystore_pass:
    description:
      - Keystore password.
    type: str
    required: true
  keystore_create:
    description:
      - Create keystore if it does not exist.
    type: bool
    default: false
  keystore_type:
    description:
      - Keystore type (JCEKS, JKS).
    type: str
  executable:
    description:
      - Path to keytool binary if not used we search in PATH for it.
    type: str
    default: keytool
  state:
    description:
      - Defines action which can be either certificate import or removal.
      - When state is present, the certificate will always idempotently be inserted into the keystore, even if there already
        exists a cert alias that is different.
    type: str
    choices: [absent, present]
    default: present
  mode:
    version_added: 8.5.0
  owner:
    version_added: 8.5.0
  group:
    version_added: 8.5.0
  seuser:
    version_added: 8.5.0
  serole:
    version_added: 8.5.0
  setype:
    version_added: 8.5.0
  selevel:
    version_added: 8.5.0
  unsafe_writes:
    version_added: 8.5.0
  attributes:
    version_added: 8.5.0
requirements: [openssl, keytool]
author:
  - Adam Hamsik (@haad)
a@  
- name: Import SSL certificate from google.com to a given cacerts keystore
  community.general.java_cert:
    cert_url: google.com
    cert_port: 443
    keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts
    keystore_pass: changeit
    state: present

- name: Remove certificate with given alias from a keystore
  community.general.java_cert:
    cert_url: google.com
    keystore_path: /usr/lib/jvm/jre7/lib/security/cacerts
    keystore_pass: changeit
    executable: /usr/lib/jvm/jre7/bin/keytool
    state: absent

- name: Import trusted CA from SSL certificate
  community.general.java_cert:
    cert_path: /opt/certs/rootca.crt
    keystore_path: /tmp/cacerts
    keystore_pass: changeit
    keystore_create: true
    state: present
    cert_alias: LE_RootCA
    trust_cacert: true

- name: Import trusted CA from the SSL certificate stored in the cert_content variable
  community.general.java_cert:
    cert_content: |
      -----BEGIN CERTIFICATE-----
      ...
      -----END CERTIFICATE-----
    keystore_path: /tmp/cacerts
    keystore_pass: changeit
    keystore_create: true
    state: present
    cert_alias: LE_RootCA
    trust_cacert: true

- name: Import SSL certificate from google.com to a keystore, create it if it doesn't exist
  community.general.java_cert:
    cert_url: google.com
    keystore_path: /tmp/cacerts
    keystore_pass: changeit
    keystore_create: true
    state: present

- name: Import a pkcs12 keystore with a specified alias, create it if it doesn't exist
  community.general.java_cert:
    pkcs12_path: "/tmp/importkeystore.p12"
    cert_alias: default
    keystore_path: /opt/wildfly/standalone/configuration/defaultkeystore.jks
    keystore_pass: changeit
    keystore_create: true
    state: present

- name: Import SSL certificate to JCEKS keystore
  community.general.java_cert:
    pkcs12_path: "/tmp/importkeystore.p12"
    pkcs12_alias: default
    pkcs12_password: somepass
    cert_alias: default
    keystore_path: /opt/someapp/security/keystore.jceks
    keystore_type: "JCEKS"
    keystore_pass: changeit
    keystore_create: true
    state: present
a  
msg:
  description: Output from stdout of keytool command after execution of given command.
  returned: success
  type: str
  sample: "Module require existing keystore at keystore_path '/tmp/test/cacerts'"

rc:
  description: Keytool command execution return value.
  returned: success
  type: int
  sample: "0"

cmd:
  description: Executed command to get action done.
  returned: success
  type: str
  sample: "keytool -importcert -noprompt -keystore"
N)AnsibleModule)urlparse)
getproxiesc                     | rd| gS g S )z7 Check that custom keystore is presented in parameters 
-storetype )keystore_types    o/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/modules/java_cert.py%_get_keystore_type_keytool_parametersr      s    m,,I    c                 t    |dd|d|dg}|t        |      z  }| j                  ||d      \  }}}	|dk(  rd|fS y	)
zY Check if certificate with alias is present in keystore
        located at keystore_path -list	-keystore-alias-rfcFdatacheck_rcr   T)F )r   run_command)
module
executablekeystore_pathkeystore_passaliasr   test_cmdr   stdoutdummys
             r   _check_cert_presentr"      se     	H 5mDDH & 2 28-Z_ 2 `Xvu1}f~r   c                     t        | |||      }t        |d      5 }|j                  |       d d d        y # 1 sw Y   y xY w)Nw)_download_cert_urlopenwrite)r   r   urlportpem_certificate_outputremote_cert_pem_chainfs          r   _get_certificate_from_urlr-     sB    .vz3M	$c	* 'a	%&' ' 's   6?c                     |dd|d|g}| j                  |d      \  }}}|dk7  r:|ddgz  }| j                  |d      \  }}}|dk7  r| j                  d	|z  ||
       |S )zQ Read a X509 certificate chain file and output the first certificate in the list x509z-inz-outFr   r   z-informderz>Internal module failure, cannot extract certificate, error: %smsgrccmd)r   	fail_json)r   pem_certificate_filer*   openssl_binextract_cmd
extract_rcr!   extract_stderrs           r   %_get_first_certificate_from_x509_filer<     s     	K +1*<*<[SX*<*Y'ZQ	5)).4.@.@W\.@.]+UN?!adr!r *  = r   c                 
   t        j                         \  }}| j                  |       t        | |||       |ddd|g}| j	                  |d      \  }}}|dk7  r| j                  d|z  ||       |j                  d	      d   S )
zE Read a X509 certificate file and output sha256 digest using openssl dgstz-rz-sha256Fr0   r   zIInternal module failure, cannot compute digest for certificate, error: %sr2    )tempfilemkstempadd_cleanup_filer<   r   r6   split)	r   r7   r8   r!   tmp_certificatedgst_cmddgst_rcdgst_stdoutdgst_stderrs	            r   _get_digest_from_x509_filerI      s      (//1UO
O,)&2FYdeH +1*<*<XPU*<*V'Wk;!|hkvv# 	 	3 S!!$$r   c                    |ddd|dddg}|r|j                  d|g       | j                  ||d	      \  }}}	|d
k7  r| j                  d|z  |	|       t        |d      5 }
|
j	                  |       ddd       y# 1 sw Y   yxY w)zX Runs keytools to extract the public cert from a PKCS12 archive and write it to a file. r   	-nopromptr   r
   pkcs12r   r   Fr   r   zSInternal module failure, cannot extract public certificate from PKCS12, message: %s)r3   stderrr4   r$   N)extendr   r6   r&   r'   )r   r   	pkcs_filer   passworddest
export_cmd	export_rcexport_stdout
export_errr,   s              r   _export_public_cert_from_pkcs12rV   6  s     		J 8U+,-3-?-?
QYdi-?-j*YzA~r  vC  C *% 	 	' 
dC A	  s    A;;Bc                     t               j                  | d      }|syt        |      }|j                  r"|j                  j                  d      \  }}||fS |j                  j                  d      \  }}||fS )zZ Returns a tuple containing (proxy_host, proxy_port). (False, False) if no proxy is found r   )FF:)r   getr   schemenetlocrC   path)rZ   	proxy_url
parsed_url
proxy_host
proxy_ports        r   get_proxy_settingsra   P  s}      ,Ii(
'1'8'8'>'>s'C$Z J'' (2'<'<S'A$ZJ''r   c                     t               \  } }t        j                  d      }g }| rY|j                  d| z  d|z  g       |>|j	                  dd      }t        j                  dd|      }|j                  d|z  g       |S )	z1 Returns list of valid proxy options for keytool no_proxyz-J-Dhttps.proxyHost=%sz-J-Dhttps.proxyPort=%s,|z(^|\|)\.z\1*.z-J-Dhttp.nonProxyHosts=%s)ra   osgetenvrN   replaceresub)r_   r`   rc   
proxy_optsnon_proxy_hostss        r   build_proxy_optionsrm   ^  s    13Zyy$HJ3j@BZ]gBghi '..sC8O ff['?KO :_LMNr   c                 `    | j                  | j                  |      }| j                  |d      S )z/ Updates keystore file attributes as necessary )r\   F)load_file_common_argumentsparamsset_fs_attributes_if_different)r   r   	file_argss      r   _update_permissionsrs   s  s.    11&--m1TI00EBBr   c                     t               }|dddg|z   d||fz  gz   }| j                  |d      \  }}}|dk7  r| j                  d|z  ||	       |S )
zz Fetches the certificate from the remote URL using `keytool -printcert...`
          The PEM formatted string is returned z
-printcertr   z
-sslserverz%s:%dFr0   r   z?Internal module failure, cannot download certificate, error: %sr2   )rm   r   r6   )	r   r   r(   r)   rk   	fetch_cmdfetch_rc	fetch_out	fetch_errs	            r   r%   r%   y  s     %&J\6<@:MQX\_ae[fQfPggI (.'9'9)e'9'T$Xy)1}^ajj$) 	 	5 r   c	           	         ||d}	|ddddd|d|g	}
|	j                         D ]  \  }}|s	|
j                  ||g        |
t        |      z  }
|d|}t        j                  j                  |      s|d|}| j                  |
|d	
      \  }}}dd|z  d}|dk7  st        j                  j                  |      s| j                  |||
|       t        d|||
|||      S )zQ Import pkcs12 from path into keystore located on
        keystore_path as alias )z
-destaliasz	-srcaliasz-importkeystorerK   z-srcstoretyperL   z-srckeystorez-destkeystore
Fr   %s
beforeafterr   r3   r4   r5   errorTchangedr3   r4   r5   r    r   diff)	itemsrN   r   rf   r\   existsr   r6   dict)r   r   pkcs12_pathpkcs12_passpkcs12_aliasr   r   keystore_aliasr   optional_aliases
import_cmdflagvaluesecret_data	import_rc
import_out
import_errr   s                     r   import_pkcs12_pathr     s   
 %!
 	
J (--/ -etUm,- 7FFJ+[9K77>>-("/= +1*<*<Zkdi*<*j'Y
JVn%<=DA~RWW^^M:ZI:ZX**Z t- -r   c           	          |ddd|d|d|g	}|t        |      z  }|r|j                  dg       | j                  ||d|d	      \  }	}
}dd
|z  d}|	dk7  r| j                  |
|	||       t	        d|
|	||
||      S )zV Import certificate from path into keystore located on
        keystore_path as alias z-importcertrK   r   z-filer   z-trustcacertsrz   Fr   r{   r|   r   r   Tr   )r   rN   r   r6   r   )r   r   r\   r   r   r   r   trust_cacertr   r   r   r   r   s                r   import_cert_pathr     s     	
J 7FFJ?+, +1*<*<ZN[]jBkFK += +M'Y
J Ve^4DA~ZI:ZX**Z t- -r   c           	          |ddd|d|g}|t        |      z  }| j                  ||d      \  }}}	d|z  dd	}
|d
k7  r| j                  ||||	       t        d|||||	|
      S )zI Delete certificate identified with alias from keystore on keystore_path z-deleterK   r   r   Tr   r{   Nr|   r   r   r   )r   r   r6   r   )r   r   r   r   r   r   del_cmddel_rcdel_outdel_errr   s              r   delete_certr     s     	G 4]CCG "(!3!3G-Z^!3!_VWgunt4D{WWGL'f'gD: :r   c                 ,    | j                  |gd       y)z/ Test if keytool is actually executable or not Tr0   N)r   )r   r   s     r   test_keytoolr     s    

|d3r   c                     |d}t         j                  j                  |      s7t         j                  j                  |      s| j	                  dd|z         yyy)z0 Check if we can access keystore as file or not Nr   Fz6Module require existing keystore at keystore_path '%s'r   r3   )rf   r\   r   isfiler6   )r   r   s     r   test_keystorer     sO    77>>-(1N,dgt,tu 2O(r   c                  	   t        t        d      t        d      t        d      t        d      t        dd      t        d      t        d      t        dd      t        d      t        ddd	      t        d
d      t        d
d      t        d      t        dd      t        ddddg            } t        | g dg dgddggg dgdd      }|j                  j                  d      }|j                  j                  d      }|j                  j                  d      }|j                  j                  d      }|j                  j                  d      }|j                  j                  dd      }|j                  j                  dd      }|j                  j                  d       xs |}	|j                  j                  d!      }
|j                  j                  d      }|j                  j                  d      }|j                  j                  d"      }|j                  j                  d#      }|j                  j                  d$      }|j                  j                  d%      }|j	                  d&d      }|r|	s|j                  dd'|z  (       t        ||       |st        ||       t        |||||	|      \  }}t        j                         \  }}t        j                         \  }}|j                  |       |j                  |       t               }|dk(  r0|r.|j                  r|j                  d)       t        |||||	|      }|dk(  r|r4t        |d*      5 }|j!                  |       d d d        t#        |||      }nd}|rt%        ||||||       n?|r|}n:|r't        |d*      5 }|j!                  |       d d d        n|rt'        |||||       t#        |||      }||k7  rX|j                  r|j                  d)       |rt        |||||	|       |rt)        ||||||||	|	      }nt+        ||||||	||
      }t,        j.                  j1                  |      r%t3        ||      }|j                  d+d      xs ||d+<    |j                  d,i | y # 1 sw Y   -xY w# 1 sw Y   xY w)-Nstr)typer\   T)r   no_loginti  )r   default)r   requiredr   boolFkeytoolpresentabsent)r   r   choices)cert_url	cert_pathcert_contentr   pkcs12_passwordr   
cert_alias	cert_portr   r   r   keystore_creater   r   state)r   r   )r   r   r   r   T)r   r   )r   r   Tr   r   )r   r   r   r   )argument_specrequired_ifrequired_togethermutually_exclusivesupports_check_modeadd_file_common_argsr   r   r   r   r   r   r   r   1r   r   r   r   r   r   opensslz8Using local path import from %s requires alias argument.r   )r   r$   r   r   )r   r   rp   rY   get_bin_pathr6   r   r   r"   r@   rA   rB   
check_mode	exit_jsonr   r&   r'   rI   rV   r-   r   r   rf   r\   r   rs   )r   r   r(   r\   contentr)   r   r   r   r   r   r   r   r   r   r   r   r8   alias_existsalias_exists_outputr!   new_certificateold_certificateresultr,   keystore_cert_digestnew_cert_digestchanged_permissionss                               r   mainr     s   5!F#u%f%%5u%U#E3/'TBvu5&%8&UI6y8Y:OPM$ #iJL+_=>D
 !!
F --

J
'C==[)Dmm/G==[)D--##M2K--##$5r:K==$$^S9L""<07CJ==$$^4LMM%%o6MMM%%o6Mmm''(9:OMM%%o6M""<0JMMg&E %%i6KJW,- 	 	. $fm,(;
M=*m)U%L%  (//1UO'//1UO
O,
O,VF\T* VZz[hi 	 os+ -q+,-#=foWb#c  $& +FJ\[fhwx #Oos+ !q ! !  &fj#t_U4V_kZ?2     . FJ}jZgh+FJ[Zf,9=*Vce *&*o}*7]T`b 
ww~~m$1&-H"JJy%8O<OyFva- -"! !s   /R,?R9,R69S__main__)https)#
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNrf   r@   ri   ansible.module_utils.basicr   +ansible.module_utils.six.moves.urllib.parser   -ansible.module_utils.six.moves.urllib.requestr   r   r"   r-   r<   rI   rV   ra   rm   rs   r%   r   r   r   r   r   r   __name__r   r   r   <module>r      s    A @tlDL
( 
  	 5 @ D('2%,4(*C (-V-B:24
vEP zF r   