o
    =WbhM                     @   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-hmaclibgcrypt20libgcrypt20-hmacc                	       s@  e Zd ZdZdZdZdZdZg dZe	dd Z
				d)d
ee dededd	f fddZ	d*de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d*dedd	f fd'd(Z  ZS ),FIPSCommonEntitlementi  zubuntu-advantage-fips.gpgz/proc/sys/crypto/fips_enabledTz/https://ubuntu.com/security/certifications#fips)zfips-initramfsr   r    r   r   r   r   z
linux-fipsr   r   r   r   r   r   r   r!   r"   zfips-initramfs-genericc                 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_packageso   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/   r1   c                 S   s   |  ddS )Nz-hmacr%   )replace)pkg_namer,   r,   r-   <lambda>       z8FIPSCommonEntitlement.install_packages.<locals>.<lambda>)key)r/   r0   r1   )servicepkgN)eventinfoformatr4   packagessuperinstall_packagesr   get_installed_packagesr   sortedr.   r   ZUserFacingErrorr	   ZFIPS_PACKAGE_NOT_AVAILABLE)r+   r/   r0   r1   Zmandatory_packagesZdesired_packagesinstalled_packagesZ
pkg_groupsr6   Zpkg_listr;   	__class__r,   r-   rA      s:   
z&FIPSCommonEntitlement.install_packagesF	operationsilentc                 C   sp   t  }t| |r4|sttjj|d |dkr&| j	dtj
j dS |dkr6| 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.
        @param silent: Boolean set True to silence print/log of messages
        )rG   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+   rG   rH   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gceTrS   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_truerK   boolr@   r?   )r+   r$   rQ   rE   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)awsrR   rS   r%   r$   )r$   cloudc                      s     S N)rX   r,   rQ   r+   r$   r,   r-   r7     r8   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)r   r   r&   r'   r	   ZFIPS_BLOCK_ON_CLOUDr>   r4   )r+   Zcloud_titles_Zblocked_messager,   r\   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_overriderT   r$   rU   Nr%   z^(?P<cloud>(azure|aws|gce)).*rZ   )rR   rY   rS   rS   Zgcpzubuntu-{}-fipsc                    s   g | ]
}|d kr
 n|qS )zubuntu-fipsr,   ).0r;   Zcloud_metapkgr,   r-   
<listcomp>/  s    zPFIPSCommonEntitlement._replace_metapackage_on_cloud_instance.<locals>.<listcomp>)
r   rV   rK   r&   r'   r   rematchgroupr>   )r+   r?   Z%cfg_disable_fips_metapackage_overrider$   rQ   r]   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 r[   )r   r(   r@   r?   re   )r+   r?   rE   r,   r-   r?   3  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(   rJ   rK   remove_noticer	   rM   rN   ospathexistsFIPS_PROC_FILEZ	load_filestripr
   ZNOTICE_FIPS_MANUAL_DISABLE_URLrO   rL   ApplicationStatusZDISABLEDZFIPS_PROC_FILE_ERRORr>   ENABLEDZFIPS_REBOOT_REQUIRED)r+   Zsuper_statusZ	super_msgrE   r,   r-   rh   :  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-yesr3   )envN)setr   rB   r?   
differencer.   intersectionrun_apt_commandlistr	   ZDISABLE_FAILED_TMPLr>   r4   )r+   rD   Zfips_metapackageremove_packagesrr   Zapt_optionsr,   r,   r-   rx   c  s(   


z%FIPSCommonEntitlement.remove_packagesc                    s&   t  j|dr| jdtj dS dS )NrH   r%   TF)r@   _perform_enablerK   ri   r
   Z&NOTICE_WRONG_FIPS_METAPACKAGE_ON_CLOUD)r+   rH   rE   r,   r-   rz   |  s   z%FIPSCommonEntitlement._perform_enablec                    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unholdry   N)r   rv   join
splitlinesfips_pro_package_holdsappendr@   setup_apt_config)r+   rH   cmdZholdsZunholdsZholdZ
unhold_cmdrE   r,   r-   r     s   

z&FIPSCommonEntitlement.setup_apt_config)NTTF)r2   N) __name__
__module____qualname__Zrepo_pin_priorityZrepo_key_filerm   Zapt_noninteractiveZhelp_doc_urlr~   propertyr.   r   strrW   rA   rP   rX   r   r   r^   re   r?   r
   ro   r   r	   ZNamedMessagerh   rx   rz   r   __classcell__r,   r,   rE   r-   r#   M   sf    
2
,
)
) 	r#   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 fd	d
ZedefddZddedef fddZ  ZS )FIPSEntitlementfipsZFIPSzNIST-certified core packagesZ
UbuntuFIPSr2   .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   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 r[   r,   r,   )is_fips_update_enabledr,   r-   r7         z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      r   r[   r,   r,   )fips_updates_once_enabledr,   r-   r7     r   )r@   r^   r   rK   r
   ro   rp   rW   rh   
read_cacher'   namer	   Z$FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDr>   r4   Z)FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)r+   r^   Zfips_updateZenabled_statusservices_once_enabledrE   )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 Nr3   )rN   
assume_yes)Z
pre_enablepost_enableZpre_disable)r   r(   r
    PROMPT_FIPS_CONTAINER_PRE_ENABLEr>   r4   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.messagingFrH   c                    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.ry   r%   TF)r   r   ZCLOUD_ID_ERRORloggingZwarningr@   rz   rK   ri   r	   ZFIPS_INSTALL_OUT_OF_DATE)r+   rH   Z
cloud_typeerrorrE   r,   r-   rz     s   
zFIPSEntitlement._perform_enabler   )r   r   r   r   r4   descriptionoriginr   r   r   r   r   r^   r   r   rW   rz   r   r,   r,   rE   r-   r     s    ! r   c                       sd   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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 updatesr2   .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   r,   r,   r-   r     s   z,FIPSUpdatesEntitlement.incompatible_servicesc                 C   r   r   )r   r(   r
   r   r>   r4   r	   r   ZPROMPT_FIPS_UPDATES_PRE_ENABLEr   r   r   r   r,   r,   r-   r     r   z FIPSUpdatesEntitlement.messagingFrH   c                    sF   t  j|dr!| jdpi }|| jdi | jjd|d dS dS )Nry   r   T)r9   ZcontentF)r@   rz   rK   r   updater   Zwrite_cache)r+   rH   r   rE   r,   r-   rz   4  s   z&FIPSUpdatesEntitlement._perform_enabler   )r   r   r   r   r4   r   r   r   r   r   r   r   r   rW   rz   r   r,   r,   rE   r-   r     s     r   )(r   rj   rb   	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>   sZ       Pf