o
    K&bI                     @   s.  d dl Z 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mZmZ e Zg d	Zd
dgZee ee edZg dZ g dZ!g dZ"ee e  ee e! ee" dZ#G dd dej$Z%G dd de%Z&G dd de%Z'dS )    N)groupby)ListOptionalTuple)aptevent_logger
exceptionsmessagesstatusutil)NoCloudTypeReasonget_cloud_type)repo)IncompatibleService)MessagingOperationsMessagingOperationsDictStaticAffordance)
strongswanstrongswan-hmacopenssh-clientopenssh-serveropenssh-client-hmacopenssh-server-hmac)xenialbionicfocal)openssllibssl1.0.0libssl1.0.0-hmac)r   	libssl1.1libssl1.1-hmacZlibgcrypt20zlibgcrypt20-hmacc                	       s  e Zd ZdZdZdZdZdZedd Z				d&d	e
e d
ededdf fddZdeddfddZdededef fddZedeedf fddZde
e de
e fddZede
e f fddZdeejeej f f fddZd'd d!Zd(d#edef fd$d%Z  ZS ))FIPSCommonEntitlementi  zubuntu-advantage-fips.gpgz/proc/sys/crypto/fips_enabledTz/https://ubuntu.com/security/certifications#fipsc                 C   s0   t  dd}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.
        series )r   get_platform_infogetis_container#FIPS_CONTAINER_CONDITIONAL_PACKAGESFIPS_CONDITIONAL_PACKAGES)selfr"    r*   </usr/lib/python3/dist-packages/uaclient/entitlements/fips.pyconditional_packagesZ   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 ]\}}	||v r6||	7 }q*|D ]$}
zt j|
gddd W q9 tjy]   t tjj| j|
d	 Y q9w d
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)r-   r/   c                 S   s   |  ddS )Nz-hmacr#   )replace)pkg_namer*   r*   r+   <lambda>       z8FIPSCommonEntitlement.install_packages.<locals>.<lambda>)key)r-   r.   r/   )servicepkgN)eventinfoformatr2   packagessuperinstall_packagesr   get_installed_packagesr   sortedr,   r   ZUserFacingErrorr	   ZFIPS_PACKAGE_NOT_AVAILABLE)r)   r-   r.   r/   Zmandatory_packagesZdesired_packagesinstalled_packagesZ
pkg_groupsr4   Zpkg_listr9   	__class__r*   r+   r?   m   s:   
z&FIPSCommonEntitlement.install_packages	operationc                 C   sl   t  }t| |r2ttjj|d |dkr$| j	dtj
j dS |dkr4| j	dtj dS dS dS )zCheck if user should be alerted that a reboot must be performed.

        @param operation: The operation being executed.
        )rE   installr#   zdisable operationN)r   should_rebootr:   Zneeds_rebootr;   r	   ZENABLE_REBOOT_REQUIRED_TMPLr<   cfg
add_noticeFIPS_SYSTEM_REBOOT_REQUIREDmsgFIPS_DISABLE_REBOOT_REQUIRED)r)   rE   Zreboot_requiredr*   r*   r+   _check_for_reboot_msg   s    

z+FIPSCommonEntitlement._check_for_reboot_msgr"   cloud_idc                    sl   |dvrdS |dkr#t j| jjddrdS |dv rdS tdt jv S |dkr4t j| jjd	dr2dS d
S dS )a`  Return False when FIPS is allowed on this cloud and series.

        On Xenial Azure and 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.
        )azuregceTrP   z.features.allow_default_fips_metapackage_on_gcpZconfigZpath_to_valuer   r   zubuntu-gcp-fipsr   z#features.allow_xenial_fips_on_cloudF)r   is_config_value_truerH   boolr>   r=   )r)   r"   rN   rC   r*   r+   _allow_fips_on_cloud_instance   s&   z3FIPSCommonEntitlement._allow_fips_on_cloud_instance.c                    sd   dddd}t  \ } d u rd t ddtjj | d}| fdd	d
ffS )Nzan AWSzan Azureza GCP)awsrO   rP   r#   r"   )r"   cloudc                      s     S N)rU   r*   rN   r)   r"   r*   r+   r5      r6   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)r   r   r$   r%   r	   ZFIPS_BLOCK_ON_CLOUDr<   r2   )r)   Zcloud_titles_Zblocked_messager*   rY   r+   static_affordances   s   
z(FIPSCommonEntitlement.static_affordancesr=   c                    s   t j| jjdd}|r|S t  d}|dvr|S t \}}|du r%d}td|}|r2|dnd}|d	vr:|S |d
kr@dn|}d	|  fdd|D S )a  
        Identify correct metapackage to be used if in a cloud instance.

        Currently, the contract backend is not delivering the right
        metapackage on a Bionic Azure or AWS cloud instance. For those
        clouds, we have cloud specific fips metapackages and we should
        use them. We are now performing that correction here, but this
        is a temporary fix.
        z*features.disable_fips_metapackage_overriderQ   r"   rR   Nr#   z^(?P<cloud>(azure|aws|gce)).*rW   )rO   rV   rP   rP   Zgcpzubuntu-{}-fipsc                    s   g | ]
}|d kr
 n|qS )zubuntu-fipsr*   ).0r9   Zcloud_metapkgr*   r+   
<listcomp>  s    zPFIPSCommonEntitlement._replace_metapackage_on_cloud_instance.<locals>.<listcomp>)
r   rS   rH   r$   r%   r   rematchgroupr<   )r)   r=   Z%cfg_disable_fips_metapackage_overrider"   rN   rZ   Zcloud_matchr*   r]   r+   &_replace_metapackage_on_cloud_instance   s*   


z<FIPSCommonEntitlement._replace_metapackage_on_cloud_instancec                    s   t  rg S t j}| |S rX   )r   r&   r>   r=   rb   )r)   r=   rC   r*   r+   r=     s   
zFIPSCommonEntitlement.packagesc                    s   t   \}}t rt s| jdtjj	 ||fS t
j| jr^| jdtjj	 t| j dkrB| jdtj ||fS | jdtj | jdtj tjjtjj| jdfS | jdtj |tjjkrp||fS tjjtjfS )Nr#   1)	file_name)r>   application_statusr   r&   rG   rH   remove_noticer	   rJ   rK   ospathexistsFIPS_PROC_FILEZ	load_filestripr
   ZNOTICE_FIPS_MANUAL_DISABLE_URLrL   rI   ApplicationStatusZDISABLEDZFIPS_PROC_FILE_ERRORr<   ENABLEDZFIPS_REBOOT_REQUIRED)r)   Zsuper_statusZ	super_msgrC   r*   r+   re   !  s<   z(FIPSCommonEntitlement.application_statusc                 C   st   t t }t | jt | j}||}|r8ddi}ddg}tjg d| t| t	j
j| jd|d dS 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.
        ZDEBIAN_FRONTENDZnoninteractivez$-o Dpkg::Options::="--force-confdef"z$-o Dpkg::Options::="--force-confold")zapt-getremovez--assume-yesr1   )envN)setr   r@   r=   
differencer,   intersectionrun_apt_commandlistr	   ZDISABLE_FAILED_TMPLr<   r2   )r)   rB   Zfips_metapackageremove_packagesro   Zapt_optionsr*   r*   r+   ru   J  s(   


z%FIPSCommonEntitlement.remove_packagesFsilentc                    s&   t  j|dr| jdtj dS dS )Nrv   r#   TF)r>   _perform_enablerH   rf   r
   Z&NOTICE_WRONG_FIPS_METAPACKAGE_ON_CLOUD)r)   rv   rC   r*   r+   rx   c  s   z%FIPSCommonEntitlement._perform_enable)NTT)r0   NF)__name__
__module____qualname__Zrepo_pin_priorityZrepo_key_filerj   Zapt_noninteractiveZhelp_doc_urlpropertyr,   r   strrT   r?   rM   rU   r   r   r[   rb   r=   r
   rl   r   r	   ZNamedMessagere   ru   rx   __classcell__r*   r*   rC   r+   r!   M   sT    
1,
)
) r!   c                       s   e Zd ZdZdZdZdZg dZede	e
df fdd	Zede	edf f fd
dZedefddZddeddf fddZddedef fddZ  ZS )FIPSEntitlementfipsZFIPSzNIST-certified core packagesZ
UbuntuFIPS)zfips-initramfsr   r    r   r   r   r   z
linux-fipsr   r   r   r   r   r   r   r0   .c                 C   s$   ddl m} t|tjtttjfS )Nr   )LivepatchEntitlement)Zuaclient.entitlements.livepatchr   r   r	   ZLIVEPATCH_INVALIDATES_FIPSFIPSUpdatesEntitlementZFIPS_UPDATES_INVALIDATES_FIPS)r)   r   r*   r*   r+   incompatible_services  s   z%FIPSEntitlement.incompatible_servicesc                    s   t  j}t| j}tjj}t| d |k| j	dpi }|
|j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   services-once-enabledF)r   Zfips_updatesc                          S rX   r*   r*   )is_fips_update_enabledr*   r+   r5         z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      r   rX   r*   r*   )fips_updates_once_enabledr*   r+   r5     r   )r>   r[   r   rH   r
   rl   rm   rT   re   
read_cacher%   namer	   Z$FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDr<   r2   Z)FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)r)   r[   Zfips_updateZenabled_statusservices_once_enabledrC   )r   r   r+   r[     s2   


z"FIPSEntitlement.static_affordancesc                 C   Z   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 Nr1   )rK   
assume_yes)Z
pre_enablepost_enableZpre_disable)r   r&   r
    PROMPT_FIPS_CONTAINER_PRE_ENABLEr<   r2   r	   FIPS_RUN_APT_UPGRADEZPROMPT_FIPS_PRE_ENABLEprompt_for_confirmationr   PROMPT_FIPS_PRE_DISABLEr)   r   Zpre_enable_promptr*   r*   r+   	messaging  &   

zFIPSEntitlement.messagingFrv   Nc                    s|   ddg}t |d|d }g }| D ]}|| jv r!|| q|r5d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unholdrw   N)r   rs   join
splitlinesfips_pro_package_holdsappendr>   setup_apt_config)r)   rv   cmdZholdsZunholdsZholdZ
unhold_cmdrC   r*   r+   r     s   

z FIPSEntitlement.setup_apt_configc                    sL   t  \}}|d u r|tjkrtd t j|dr$| jdt	j
 dS dS )Nz>Could not determine cloud, defaulting to generic FIPS package.rw   r#   TF)r   r   ZCLOUD_ID_ERRORloggingZwarningr>   rx   rH   rf   r	   ZFIPS_INSTALL_OUT_OF_DATE)r)   rv   Z
cloud_typeerrorrC   r*   r+   rx     s   
zFIPSEntitlement._perform_enablery   )rz   r{   r|   r   r2   descriptionoriginr   r}   r   r   r   r   r[   r   r   rT   r   rx   r   r*   r*   rC   r+   r   m  s    ! r   c                       sJ   e Zd ZdZdZdZdZedefddZ	dd	e
de
f fd
dZ  ZS )r   zfips-updateszFIPS UpdatesZUbuntuFIPSUpdatesz;NIST-certified core packages with priority security updatesr0   c                 C   r   r   )r   r&   r
   r   r<   r2   r	   r   ZPROMPT_FIPS_UPDATES_PRE_ENABLEr   r   r   r   r*   r*   r+   r     r   z FIPSUpdatesEntitlement.messagingFrv   c                    sF   t  j|dr!| jdpi }|| jdi | jjd|d dS dS )Nrw   r   T)r7   ZcontentF)r>   rx   rH   r   updater   Zwrite_cache)r)   rv   r   rC   r*   r+   rx     s   z&FIPSUpdatesEntitlement._perform_enablery   )rz   r{   r|   r   r2   r   r   r}   r   r   rT   rx   r   r*   r*   rC   r+   r     s     r   )(r   rg   r_   	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.typesr   r   r   Zget_event_loggerr:   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   r*   r*   r*   r+   <module>   s\       " 
