U
    2d	G                     @   s~  d dl Z d dlZd dlmZ d dlmZmZmZ d dl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lmZ d d	lmZ d d
lmZ d dlmZmZ d dlm Z m!Z!m"Z" e
# Z$e %e&e'Z(dddddgZ)ddgZ*e)e* e)e* e)dZ+dddgZ,dddddgZ-dddddgZ.e)e* e, e)e* e- e)e. dZ/G dd dej0Z1G dd de1Z2G d d! d!e1Z3dS )"    N)groupby)ListOptionalTuple)aptevent_logger
exceptionsmessagessystemutil)NoCloudTypeReasonget_cloud_type)repo)IncompatibleService)ApplicationStatus)notices)Notice)ServicesOnceEnabledDataservices_once_enabled_file)MessagingOperationsMessagingOperationsDictStaticAffordance
strongswanstrongswan-hmacopenssh-clientopenssh-servershim-signedopenssh-client-hmacopenssh-server-hmac)Zxenialbionicfocalopenssllibssl1.0.0libssl1.0.0-hmac	libssl1.1libssl1.1-hmaclibgcrypt20libgcrypt20-hmacc                       s4  e Zd ZdZdZdZdZdZdddd	d
d	d
ddddddddddddgZe	dd Z
d3eee  eedd fddZd4eedddd Zeeed! fd"d#Ze	eed$f d%d&d'Ze	ee d% fd(d)Zeeeej f d% fd*d+Zdd%d,d-Zd5eed. fd/d0Zd6edd. fd1d2Z  ZS )7FIPSCommonEntitlementi  zubuntu-pro-fips.gpgz/proc/sys/crypto/fips_enabledTz/https://ubuntu.com/security/certifications#fipszfips-initramfsr$   r%   r"   r#   z
linux-fipsr   r   r   r   r!   r   r   r&   r'   zfips-initramfs-genericr   c                 C   s*   t  j}t  rt|g S t|g S )a  
        Dictionary of conditional packages to be installed when
        enabling FIPS services. For example, if we are enabling
        FIPS services in a machine that has openssh-client installed,
        we will perform two actions:

        1. Upgrade the package to the FIPS version
        2. Install the corresponding hmac version of that package
           when available.
        )r
   get_release_infoseriesis_container#FIPS_CONTAINER_CONDITIONAL_PACKAGESgetFIPS_CONDITIONAL_PACKAGES)selfr*    r0   </usr/lib/python3/dist-packages/uaclient/entitlements/fips.pyconditional_packagesw   s    
z*FIPSCommonEntitlement.conditional_packagesN)package_listcleanup_on_failureverbosereturnc              
      s   |rt dj| jd | j}t j|dd g }t }t	t
| jdd d}|D ]\}}	||krT||	7 }qT|D ]L}
zt j|
gddd W qr tjk
r   t tjj| j|
d	 Y qrX qrd
S )a)  Install contract recommended packages for the entitlement.

        :param package_list: Optional package list to use instead of
            self.packages.
        :param cleanup_on_failure: Cleanup apt files if apt install fails.
        :param verbose: If true, print messages to stdout
        zInstalling {title} packagestitleF)r3   r5   c                 S   s   |  ddS )Nz-hmac )replace)pkg_namer0   r0   r1   <lambda>       z8FIPSCommonEntitlement.install_packages.<locals>.<lambda>)key)r3   r4   r5   )servicepkgN)eventinfoformatr8   packagessuperinstall_packagesr   get_installed_packages_namesr   sortedr2   r   ZUserFacingErrorr	   ZFIPS_PACKAGE_NOT_AVAILABLE)r/   r3   r4   r5   Zmandatory_packagesZdesired_packagesinstalled_packagesZ
pkg_groupsr;   Zpkg_listr@   	__class__r0   r1   rF      s<     
  
 z&FIPSCommonEntitlement.install_packagesF)	operationsilentr6   c                 C   s\   t  }t| |rX|s.ttjj|d |dkrDt	t
j n|dkrXt	t
j dS )zCheck if user should be alerted that a reboot must be performed.

        @param operation: The operation being executed.
        @param silent: Boolean set True to silence print/log of messages
        )rL   installzdisable operationN)r
   should_rebootrA   Zneeds_rebootrB   r	   ZENABLE_REBOOT_REQUIRED_TMPLrC   r   addr   FIPS_SYSTEM_REBOOT_REQUIREDFIPS_DISABLE_REBOOT_REQUIRED)r/   rL   rM   Zreboot_requiredr0   r0   r1   _check_for_reboot_msg   s"    
z+FIPSCommonEntitlement._check_for_reboot_msg)r*   cloud_idr6   c                    s>   |dkr:t j| jjddrdS |dkr*dS tdt jkS dS )aV  Return False when FIPS is allowed on this cloud and series.

        On Xenial GCP there will be no cloud-optimized kernel so
        block default ubuntu-fips enable. This can be overridden in
        config with features.allow_xenial_fips_on_cloud.

        GCP doesn't yet have a cloud-optimized kernel or metapackage so
        block enable of fips if the contract does not specify ubuntu-gcp-fips.
        This also can be overridden in config with
        features.allow_default_fips_metapackage_on_gcp.

        :return: False when this cloud, series or config override allows FIPS.
        gcez.features.allow_default_fips_metapackage_on_gcp)ZconfigZpath_to_valueT)r   r    zubuntu-gcp-fips)r   Zis_config_value_truecfgboolrE   rD   )r/   r*   rT   rJ   r0   r1   _allow_fips_on_cloud_instance   s    z3FIPSCommonEntitlement._allow_fips_on_cloud_instance.r6   c                    s^   dddd}t  \ } d kr"d t jtjj | d}| fddd	ffS )
Nzan AWSzan Azureza GCP)ZawsZazurerU   r9   )r*   Zcloudc                      s     S N)rX   r0   rT   r/   r*   r0   r1   r<     r=   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)	r   r
   r)   r*   r	   ZFIPS_BLOCK_ON_CLOUDrC   r8   r-   )r/   Zcloud_titles_Zblocked_messager0   r[   r1   static_affordances   s    

 z(FIPSCommonEntitlement.static_affordancesc                    s   t  rg S t jS rZ   )r
   r+   rE   rD   )r/   rJ   r0   r1   rD     s    zFIPSCommonEntitlement.packagesc                    s   t   \}}t r2t s2ttj ||fS t	j
| jrtt| js\ttj t| j dkrttj ||fS ttj tjtjj| jdfS |tjkr||fS tjtjfS )N1)	file_name)rE   application_statusr
   r+   rO   r   remover   rQ   ospathexistsFIPS_PROC_FILEsetrD   Z	load_filestripZFIPS_MANUAL_DISABLE_URLrP   r   ZDISABLEDr	   ZFIPS_PROC_FILE_ERRORrC   ENABLEDFIPS_REBOOT_REQUIRED)r/   Zsuper_statusZ	super_msgrJ   r0   r1   r`     s:    
z(FIPSCommonEntitlement.application_statusc                 C   sP   t t }t | jt | j}||}|rLtt|t	j
j| jd dS )zRemove fips meta package to disable the service.

        FIPS meta-package will unset grub config options which will deactivate
        FIPS on any related packages.
        r7   N)rf   r   rG   rD   
differencer2   intersectionremove_packageslistr	   ZDISABLE_FAILED_TMPLrC   r8   )r/   rI   Zfips_metapackagerl   r0   r0   r1   rl   7  s    

z%FIPSCommonEntitlement.remove_packagesrM   r6   c                    s:   t  j|dr6ttj ttj ttj dS dS )NrM   TF)rE   _perform_enabler   ra   r   ZWRONG_FIPS_METAPACKAGE_ON_CLOUDri   rR   )r/   rM   rJ   r0   r1   rp   H  s    z%FIPSCommonEntitlement._perform_enablec                    s|   ddg}t |d|d }g }| D ]}|| jkr*|| q*|rjddg| }t |d|d }t j|d dS )zSetup apt config based on the resourceToken and directives.

        FIPS-specifically handle apt-mark unhold

        :raise UserFacingError: on failure to setup any aspect of this apt
           configuration
        zapt-markZ	showholds z failed.Zunholdro   N)r   Zrun_apt_commandjoin
splitlinesfips_pro_package_holdsappendrE   setup_apt_config)r/   rM   cmdZholdsZunholdsZholdZ
unhold_cmdrJ   r0   r1   rv   S  s    
 z&FIPSCommonEntitlement.setup_apt_config)NTT)F)F)F)__name__
__module____qualname__Zrepo_pin_priorityZrepo_key_filere   Zapt_noninteractiveZhelp_doc_urlrt   propertyr2   r   r   strrW   rF   rS   rX   r   r   r]   rD   r   r	   ZNamedMessager`   rl   rp   rv   __classcell__r0   r0   rJ   r1   r(   U   sn   
   
2   *r(   c                       s   e Zd ZdZdZdZdZeee	df dddZ
eeedf d fd	d
ZeedddZdeed fddZ  ZS )FIPSEntitlementfipsZFIPSzNIST-certified core packagesZ
UbuntuFIPS.rY   c                 C   s:   ddl m} ddlm} t|tjtttjt|tj	fS )Nr   )LivepatchEntitlementRealtimeKernelEntitlement)
Zuaclient.entitlements.livepatchr   uaclient.entitlements.realtimer   r   r	   ZLIVEPATCH_INVALIDATES_FIPSFIPSUpdatesEntitlementZFIPS_UPDATES_INVALIDATES_FIPSZREALTIME_FIPS_INCOMPATIBLE)r/   r   r   r0   r0   r1   incompatible_serviceso  s       z%FIPSEntitlement.incompatible_servicesc                    s   t  j}t| j}tj}t| d |kt	 }|r>|j
nd |tjj| j|jdfdddftjj| j|jd fdddff S )Nr   F)r   fips_updatesc                      s    S rZ   r0   r0   )is_fips_updates_enabledr0   r1   r<     r=   z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      s    S rZ   r0   r0   )fips_updates_once_enabledr0   r1   r<     r=   )rE   r]   r   rV   r   rh   rW   r`   r   readr   r	   Z$FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDrC   r8   Z)FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)r/   r]   r   Zenabled_statusZservices_once_enabled_objrJ   )r   r   r1   r]     s6    
 
 
z"FIPSEntitlement.static_affordancesc                 C   sZ   d }t  r&tjj| jd}tjg}ntj}tj	|| j
dfg|tj	tj| j
dfgdS Nr7   )msg
assume_yes)Z
pre_enablepost_enableZpre_disable)r
   r+   r	    PROMPT_FIPS_CONTAINER_PRE_ENABLErC   r8   FIPS_RUN_APT_UPGRADEZPROMPT_FIPS_PRE_ENABLEr   prompt_for_confirmationr   PROMPT_FIPS_PRE_DISABLEr/   r   Zpre_enable_promptr0   r0   r1   	messaging  s(    

zFIPSEntitlement.messagingFrn   c                    sH   t  \}}|d kr&|tjkr&td t j|drDtt	j
 dS dS )Nz>Could not determine cloud, defaulting to generic FIPS package.ro   TF)r   r   ZCLOUD_ID_ERRORLOGZwarningrE   rp   r   ra   r   ZFIPS_INSTALL_OUT_OF_DATE)r/   rM   Z
cloud_typeerrorrJ   r0   r1   rp     s    
zFIPSEntitlement._perform_enable)F)rx   ry   rz   namer8   descriptionoriginr{   r   r   r   r   r]   r   r   rW   rp   r}   r0   r0   rJ   r1   r~   i  s   !r~   c                       sb   e Zd ZdZdZdZdZeee	df dddZ
eedd	d
Zdeed fddZ  ZS )r   zfips-updateszFIPS UpdatesZUbuntuFIPSUpdatesz;NIST-certified core packages with priority security updates.rY   c                 C   s$   ddl m} tttjt|tjfS )Nr   r   )r   r   r   r~   r	   ZFIPS_INVALIDATES_FIPS_UPDATESZ"REALTIME_FIPS_UPDATES_INCOMPATIBLE)r/   r   r0   r0   r1   r     s     z,FIPSUpdatesEntitlement.incompatible_servicesc                 C   sZ   d }t  r&tjj| jd}tjg}ntj}tj	|| j
dfg|tj	tj| j
dfgdS r   )r
   r+   r	   r   rC   r8   r   ZPROMPT_FIPS_UPDATES_PRE_ENABLEr   r   r   r   r   r0   r0   r1   r     s(    

z FIPSUpdatesEntitlement.messagingFrn   c                    sV   t  j|drR| jdpi }|| jdi | jjd|d tt	dd dS dS )Nro   zservices-once-enabledT)r>   Zcontent)r   F)
rE   rp   rV   Z
read_cacheupdater   Zwrite_cacher   writer   )r/   rM   Zservices_once_enabledrJ   r0   r1   rp     s     z&FIPSUpdatesEntitlement._perform_enable)F)rx   ry   rz   r   r8   r   r   r{   r   r   r   r   r   rW   rp   r}   r0   r0   rJ   r1   r     s   r   )4Zloggingrb   	itertoolsr   typingr   r   r   Zuaclientr   r   r   r	   r
   r   Zuaclient.clouds.identityr   r   Zuaclient.entitlementsr   Zuaclient.entitlements.baser   Z(uaclient.entitlements.entitlement_statusr   Zuaclient.filesr   Zuaclient.files.noticesr   Zuaclient.files.state_filesr   r   Zuaclient.typesr   r   r   Zget_event_loggerrA   Z	getLoggerZreplace_top_level_logger_namerx   r   ZCONDITIONAL_PACKAGES_EVERYWHEREZ!CONDITIONAL_PACKAGES_OPENSSH_HMACr.   Z&UBUNTU_FIPS_METAPACKAGE_DEPENDS_XENIALZ&UBUNTU_FIPS_METAPACKAGE_DEPENDS_BIONICZ%UBUNTU_FIPS_METAPACKAGE_DEPENDS_FOCALr,   ZRepoEntitlementr(   r~   r   r0   r0   r0   r1   <module>   s      i