o
    =Wbp4                  	   @   s$  d dl Z d dl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 d dlmZmZ d dlmZ d dlmZ ddgZd	Zd
ZdddZdZe
 Z	ddedeee  ddfddZ 			d dee dee deee  ddfddZ!dedee fddZ"G dd deZ#dd Z$dS )!    N)AnyDictListOptionalTuple)aptevent_logger
exceptionsmessagessnapstatusutil)IncompatibleServiceUAEntitlement)ApplicationStatus)StaticAffordanceg      ?g      ?z
http-proxyzhttps-proxyz)Invalid Auth-Token provided to livepatch.z2Your running kernel is not supported by Livepatch.)zUnknown Auth-Tokenzunsupported kernelz/snap/bin/canonical-livepatchprotocol_typeretry_sleepsreturnc                 C   s,   t tsdS t jtdd| g|d dS )a  
    Unset livepatch configuration settings for http and https proxies.

    :param protocol_type: String either http or https
    :param retry_sleeps: Optional list of sleep lengths to apply between
        retries. Specifying a list of [0.5, 1] tells subp to retry twice
        on failure; sleeping half a second before the first retry and 1 second
        before the second retry.
    Nconfigz	{}-proxy=r   )r   whichLIVEPATCH_CMDsubpformat)r   r    r   A/usr/lib/python3/dist-packages/uaclient/entitlements/livepatch.pyunconfigure_livepatch_proxy    s   

r   
http_proxyhttps_proxyc                 C   sb   | s|rt tjjtjd | rtjt	dd| g|d |r/tjt	dd|g|d dS dS )a  
    Configure livepatch to use http and https proxies.

    :param http_proxy: http proxy to be used by livepatch. If None, it will
                       not be configured
    :param https_proxy: https proxy to be used by livepatch. If None, it will
                        not be configured
    :@param retry_sleeps: Optional list of sleep lengths to apply between
                               snap calls
    )servicer   zhttp-proxy={}r   zhttps-proxy={}N)
eventinfor
   ZSETTING_SERVICE_PROXYr   LivepatchEntitlementtitler   r   r   r   r   r   r   r   r   configure_livepatch_proxy4   s"   
r&   keyc                 C   s\   t tdg\}}td| |tj}|r|dnd}|r&tdd|}|r,|	 S dS )z
    Gets the config value from livepatch.
    :param protocol: can be any valid livepatch config option
    :return: the value of the livepatch config option, or None if not set
    r   z
^{}: (.*)$   Nz\"(.*)\"z\g<1>)
r   r   r   researchr   	MULTILINEgroupsubstrip)r'   out_matchvaluer   r   r   get_config_option_valueW   s   r3   c                	       s   e Zd ZdZdZdZdZedee	df fddZ
edeedf fd	d
ZddedefddZ	ddededefddZdddZdeeeej f fddZ	ddeeef deeef dedef fddZ  ZS )r#   z%https://ubuntu.com/security/livepatchZ	livepatchZ	LivepatchzCanonical Livepatch servicer   .c                 C   s0   ddl m} ddlm} t|tjt|tjfS )Nr   FIPSEntitlement)RealtimeKernelEntitlement)uaclient.entitlements.fipsr5   Zuaclient.entitlements.realtimer6   r   r
   ZLIVEPATCH_INVALIDATES_FIPSZREALTIME_LIVEPATCH_INCOMPATIBLE)selfr5   r6   r   r   r   incompatible_servicesm   s   z*LivepatchEntitlement.incompatible_servicesc                    sP   ddl m} || j}t| d tjk tjdd dftj	 fdddffS )Nr   r4   c                   S   s   t  S N)r   Zis_containerr   r   r   r   <lambda>   s    z9LivepatchEntitlement.static_affordances.<locals>.<lambda>Fc                      s    S r:   r   r   Zis_fips_enabledr   r   r;      s    )
r7   r5   cfgboolapplication_statusr   ENABLEDr
   Z$LIVEPATCH_ERROR_INSTALL_ON_CONTAINERZ!LIVEPATCH_ERROR_WHEN_FIPS_ENABLED)r8   r5   Zfips_entr   r<   r   static_affordances|   s   

z'LivepatchEntitlement.static_affordancesFsilentc              
   C   s  t tjs?td ttj zt	  W n t
jy2 } ztdt| W Y d}~nd}~ww t jg ddtjd ndt vrNt
jtj| jdzt jtjd	d
dgdd W n% t
jy } ztdt| rvttj n W Y d}~nd}~ww t d| jjt j}t d| jjt j}tj ||tj!d t t"std zt jtjddgdtj!d W n t
jy } zt
j#t|dd}~ww t$|| | j%dddS )zYEnable specific entitlement.

        @return: True on success, False otherwise.
        zInstalling snapdz<Trying to install snapd. Ignoring apt-get update failure: %sN)zapt-getinstallz--assume-yessnapdT)capturer   rD   )Zsnap_cmdr    waitsystemzseed.loadedrE   zunknown command .*waitZhttpZhttpsr%   z#Installing canonical-livepatch snaprC   zcanonical-livepatch)Z	error_msgprocess_directivesprocess_token)&r   r   r   ZSNAP_CMDr!   r"   r
   ZAPT_UPDATING_LISTSr   Zrun_apt_update_commandr	   ZUserFacingErrorloggingdebugstrr   ZAPT_RETRIESZget_installed_packagesZSnapdNotProperlyInstalledErrorr$   ProcessExecutionErrorr)   r*   lowerZwarningZSNAPD_DOES_NOT_HAVE_WAIT_CMDZvalidate_proxyr=   r   ZPROXY_VALIDATION_SNAP_HTTP_URLr   ZPROXY_VALIDATION_SNAP_HTTPS_URLZconfigure_snap_proxyZSNAP_INSTALL_RETRIESr   ZErrorInstallingLivepatchr&   setup_livepatch_config)r8   rB   er   r   r   r   r   _perform_enable   sv   






z$LivepatchEntitlement._perform_enableTrJ   rK   c              
   C   s  | j j| j}|r5zt| W n$ tjy4 } zdt| }t	| t
| W Y d}~dS d}~ww |r|d}|sKt
d| j | j jd }|  \}}|tjjkrt
	d| j z	ttdg W n tjy } zt
t| W Y d}~dS d}~ww ztjtd	|gd
d W n: tjy } z-d}t D ]\}	}
|	t|v r||
7 } nq|dkr|t|7 }t	| W Y d}~dS d}~ww t	d d
S )a  Processs configuration setup for livepatch directives.

        :param process_directives: Boolean set True when directives should be
            processsed.
        :param process_token: Boolean set True when token should be
            processsed.
        zUnable to configure Livepatch: NFresourceTokenzHNo specific resourceToken present. Using machine token as %s credentialsZmachineTokenz.Disabling %s prior to re-attach with new tokendisableenableTrH   zUnable to enable Livepatch: zCanonical livepatch enabled.)r=   Zentitlementsgetnameprocess_config_directivesr	   rO   rN   r!   r"   rL   errorrM   r$   Zmachine_tokenr?   r   r   DISABLEDr   r   r   ERROR_MSG_MAPitems)r8   rJ   rK   Zentitlement_cfgrR   msgZlivepatch_tokenr?   Z_detailsZerror_messageZprint_messager   r   r   rQ      sf   








z+LivepatchEntitlement.setup_livepatch_configc                 C   s$   t tsdS t jtdgdd dS )zYDisable specific entitlement

        @return: True on success, False otherwise.
        TrU   rH   )r   r   r   r   )r8   rB   r   r   r   _perform_disable  s   
z%LivepatchEntitlement._perform_disablec              
   C   s   t jd f}ttst jtjfS ztjtdgt	d W |S  t
jyC } ztdt| t jtjdt|dfW  Y d }~S d }~ww )Nr   r   zLivepatch not enabled. %s )rX   r^   )r   r@   r   r   r   r[   r
   ZLIVEPATCH_NOT_ENABLEDr   LIVEPATCH_RETRIESr	   rO   rL   rM   rN   NamedMessage)r8   r   rR   r   r   r   r?     s   


z'LivepatchEntitlement.application_statusorig_accessdeltasallow_enablec                    s   t  |||r
dS |di }|di dd}|r$|  \}}|S |  \}}|tjjkr2dS |di }	tddg}
t	|

|	}t	|d	d}t||gratd
| j | j||dS dS )a1  Process any contract access deltas for this entitlement.

        :param orig_access: Dictionary containing the original
            resourceEntitlement access details.
        :param deltas: Dictionary which contains only the changed access keys
        and values.
        :param allow_enable: Boolean set True if allowed to perform the enable
            operation. When False, a message will be logged to inform the user
            about the recommended enabled service.

        :return: True when delta operations are processed; False when noop.
        TentitlementZobligationsZenabledByDefaultF
directivescaCertsremoteServerrT   z$Updating '%s' on changed directives.rI   )superprocess_contract_deltasrW   rV   r?   r   r   r[   setr>   intersectionanyrL   r"   rX   rQ   )r8   rc   rd   re   Zdelta_entitlementZprocess_enable_defaultZenable_successr0   r?   Zdelta_directivesZsupported_deltasrJ   rK   	__class__r   r   rk   ,  s2   z,LivepatchEntitlement.process_contract_deltas)F)TT)__name__
__module____qualname__Zhelp_doc_urlrX   r$   descriptionpropertyr   r   r9   r   rA   r>   rS   rQ   r_   r   r   r
   rb   r?   r   rN   r   rk   __classcell__r   r   ro   r   r#   f   s@    B

8



r#   c                 C   s   | sdS |  di  di }| d}|r"tjtdd|gdd | d	d
}|dr3|dd }|rDtjtdd|gdd dS dS )a  Process livepatch configuration directives.

    We process caCerts before remoteServer because changing remote-server
    in the canonical-livepatch CLI performs a PUT against the new server name.
    If new caCerts were required for the new remoteServer, this
    canonical-livepatch client PUT could fail on unmatched old caCerts.

    @raises: ProcessExecutionError if unable to configure livepatch.
    Nrf   rg   rh   r   zca-certs={}TrH   ri   r`   /zremote-server={})rW   r   r   r   r   endswith)r=   rg   Zca_certsZremote_serverr   r   r   rY   \  s*   



rY   r:   )NNN)%rL   r)   typingr   r   r   r   r   Zuaclientr   r   r	   r
   r   r   r   Zuaclient.entitlements.baser   r   Zuaclient.statusr   Zuaclient.typesr   ra   ZHTTP_PROXY_OPTIONZHTTPS_PROXY_OPTIONr\   r   Zget_event_loggerr!   rN   floatr   r&   r3   r#   rY   r   r   r   r   <module>   sN    $	



# w