
    x[h                         S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	J
r
  SSKJr  \R                  " \5      rSr " S S5      rg)	z0gpg.py - Collection of gpg key related functions    N)TemporaryDirectory)DictOptional)subp	GNUPGHOMEc                       \ rS rSrS rS r\S\\\4   4S j5       r	S r
SS jrS	\S\\   4S
 jrS	\S\4S jrSS\S\4S jjrSS	\S\SS4S jjrS	\SS4S jr SS\S\S\\   4S jjrSS jrSrg)GPG   c                 >    SU l         0 U l        [        5       U l        g )NF)gpg_started_envr   temp_dirselfs    //usr/lib/python3/dist-packages/cloudinit/gpg.py__init__GPG.__init__   s     	*,    c                     U $ N r   s    r   	__enter__GPG.__enter__   s    r   returnc                     U R                   (       a  U R                   $ SU l        [        U R                  R                  0U l         U R                   $ )zwhen this env property gets invoked, set up our temporary
directory, and also set gpg_started to tell the cleanup()
method whether or not

why put this here and not in __init__? pytest seems unhappy
and it's not obvious how to work around it
T)r   r   HOMEr   namer   s    r   envGPG.env"   s=     99994==--.	yyr   c                 $    U R                  5         g r   )cleanup)r   exc_typ	exc_value	tracebacks       r   __exit__GPG.__exit__1   s    r   Nc                     U R                  5         U R                  (       aT  [        R                  R	                  U R                  R
                  5      (       a  U R                  R                  5         ggg)z0cleanup the gpg temporary directory and kill gpgN)kill_gpgr   ospathisdirr   r!   r   s    r   r!   GPG.cleanup4   sE    ==RWW]]4==+=+=>>MM!!# ?=r   keyc                      [         R                   " SSSU/SU R                  S9R                  $ ! [         R                   a   n[        R                  SX5         SnAgSnAff = f)z*Export gpg key, armoured key gets returnedgpgz--exportz--armourTcapture
update_env&Failed to export armoured key "%s": %sN)r   r   stdoutProcessExecutionErrorLOGdebugr   r-   errors      r   export_armourGPG.export_armour:   se    	L99
J488 f	
 )) 	LII>KK	Ls   -0 A$AA$c                 \    [         R                   " SS/USU R                  S9R                  $ )zvDearmor gpg key, dearmored key gets returned

note: man gpg(1) makes no mention of an --armour spelling, only --armor
r/   z	--dearmorF)datadecoder2   )r   r   r4   )r   r-   s     r   dearmorGPG.dearmorG   s,    
 yyK s5TXX

&	r   key_filec                     / SQnU(       d  UR                  S5        UR                  U5        [        R                  " X0R                  SS9u  pEU(       a  [        R	                  SX5        U$ )zList keys from a keyring with fingerprints. Default to a
stable machine parseable format.

@param key_file: a string containing a filepath to a key
@param human_output: return output intended for human parsing
)r/   z--no-optionsz--with-fingerprintz--no-default-keyringz--list-keysz	--keyringz--with-colonsT)r2   r1   r3   )appendr   r   r6   warning)r   rA   human_outputcmdr4   stderrs         r   	list_keysGPG.list_keysP   sW    
 JJ'

8388TJKK8( r   	keyserverc                    [         R                  SX5        SnSn[        U=(       d    / 5      n US-  n [        R                  " SSSU-  S	U/SU R                  S
9  [         R                  SUUU5        g! [        R
                   a  nUn SnAOSnAff = f [        U5      n[         R                  SUR                  U5        [        R                  " U5        O#! [         a  n[        SXXE4-  5      UeSnAff = fM  )a  Receive gpg key from the specified keyserver.

Retries are done by default because keyservers can be unreliable.
Additionally, there is no way to determine the difference between
a non-existent key and a failure.  In both cases gpg (at least 2.2.4)
exits with status 2 and stderr: "keyserver receive failed: No data"
It is assumed that a key provided to cloud-init exists on the keyserver
so re-trying makes better sense than failing.

@param key: a string key fingerprint (as passed to gpg --recv-keys).
@param keyserver: the keyserver to request keys from.
@param retries: an iterable of sleep lengths for retries.
Use None to indicate no retries.z&Importing key '%s' from keyserver '%s'r   NT   r/   z--no-ttyz--keyserver=%sz--recv-keysr0   z/Imported key '%s' from keyserver '%s' on try %dz6Import failed with exit code %d, will try again in %ssz@Failed to import key '%s' from keyserver '%s' after %d tries: %s)r6   r7   iterr   r   r5   next	exit_codetimesleepStopIteration
ValueError)	r   r-   rJ   retriestrynumr9   sleepsenaplens	            r   recv_keyGPG.recv_keyj   s    			:CKgm$aKF		"(94% !#xx
 		E	 -- f		LOO
 

6"   ),/F+JK ? s1   A A7 7BBBAC 
C>(C99C>c                      [         R                   " SSSSU/SU R                  S9  g! [         R                   a   n[        R	                  SX5         SnAgSnAff = f)	z0Delete the specified key from the local gpg ringr/   z--batchz--yesz--delete-keysTr0   zFailed delete key "%s": %sN)r   r   r5   r6   rD   r8   s      r   
delete_keyGPG.delete_key   sX    	BII	7OSA88
 )) 	BKK4cAA	Bs   %( AAAkeyidc                    U R                  U5      nU(       d5   U R                  XS9  U R                  U5      n U R                  U5        U$ U$ ! [         a    [        R	                  SU5        e f = f! U R                  U5        f = f)zget gpg keyid from keyserver)rJ   zFailed to obtain gpg key %s)r:   rY   rS   r6   	exceptionr\   )r   r^   rJ   armours       r   
getkeybyidGPG.getkeybyid   s     ##E*	'e9++E2 &v  ;UC &s    A "A22A5 5Bc                     U R                   (       d  g[        R                  " S5      (       a-  [        R                  " / SQSU R                  S9R                  ng[        R                  " / SQSSS/S	9R                  n[
        R                  " S
U5      nU Vs/ s H  o3S   S:X  d  M  [        US   5      PM     nnU(       a  [        R                  SU5        U H(  n[        R                  " U[        R                  5        M*     gs  snf ! [        R                   a   n[        R                  SU5         SnAgSnAff = f)zkilling with gpgconf is best practice, but when it isn't available
failover is possible

GH: 4344 - stop gpg-agent/dirmgr daemons spawned by gpg
key imports. Daemons spawned by cloud-config.service on systemd
v253 report (running)
Ngpgconf)re   z--killallTr0   )	psz-ozppid,pid-Ckeyboxdrh   dirmngrrh   z	gpg-agentr   rL   )r1   rcsz(?P<ppid>\d+)\s+(?P<pid>\d+)1z&Killing gpg-agent and dirmngr pids: %sz"Failed to clean up gpg process: %s)r   r   whichr   r4   refindallintr6   r7   r)   killsignalSIGKILLr5   rD   )r   gpg_process_outgpg_pidspidroot_gpg_pidsgpg_pidrW   s          r   r(   GPG.kill_gpg   s   &	A##zz)$$"&))0 #xx# &	   #'))
 !A# &   ::3_ ,4!+3C1v}KCAK8  ! !II@-  -GGGGV^^4  -! )) 	AKK<a@@	As<   D AD ?D D+D=AD D E$D??E)r   r   r   )r   N)F))rL   rL   )zkeyserver.ubuntu.com)__name__
__module____qualname____firstlineno__r   r   propertyr   strr   r%   r!   r   r:   r?   rH   rY   r\   rb   r(   __static_attributes__r   r   r   r	   r	      s    -
 T#s(^  $ # 3 3 # c 45C 5C 5D 5n	Bc 	Bd 	B ,B%(	#$.Ar   r	   )__doc__loggingr)   rn   rr   rP   tempfiler   typingr   r   	cloudinitr   	getLoggerrz   r6   r   r	   r   r   r   <module>r      sE    7  	 	   ' ! !SA SAr   