U
    JhHf                     @   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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Z0e+e, e. e+e, e/ e+e0 dZ1G dd dej2Z3G dd de3Z4G d d! d!e3Z5G d"d# d#e4Z6dS )$    N)groupby)ListOptionalTuple)apiaptevent_logger
exceptionsmessagessystemutil)NoCloudTypeReasonget_cloud_type)repo)EntitlementWithMessage)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)xenialbionicfocalopenssllibssl1.0.0libssl1.0.0-hmac	libssl1.1libssl1.1-hmaclibgcrypt20libgcrypt20-hmacc                       s  e Zd ZdZdZdZejZdZ	dZ
ejjZddddd	d
dddddddddddddddddddddddgZeed d!d"Zed#d$ Zeed%d&d'Zejd(d)d*Zed d+d,Zejd(d-d.ZdNejeee  ed/d0 fd1d2Zed d3d4ZdOeed/d6d7d8Zeeed9 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dAdBZ'd/d dCdDZ(ejedE fdFdGZ)ejedE fdHdIZ*dJdK Z+ejd/dE fdLdMZ,  Z-S )PFIPSCommonEntitlementi  zubuntu-pro-fips.gpgz/proc/sys/crypto/fips_enabledTzfips-initramfszfips-initramfs-genericr(   r)   Zlibgmp10Zlibgnutls30Zlibhogweed6Z
libnettle8r$   r%   r&   r'   Zlibssl3
linux-fipsr   r   r   r   r#   openssl-fips-module-3r   r   r   zubuntu-fipszubuntu-aws-fipszubuntu-azure-fipsubuntu-gcp-fipsreturnc                 C   s6  d }d }| j sNt r8tjj| jd}|  s>tjg}n| j	}t
jd|ifg}d }| jsz| j szt
jdtjj| jdifg}| j s| ji fgnd }||||d}t| jdkr2| jd }td|}|r|d}	nd}	t j}
|	|
kr2|dpg }tjj|	| j|	|
pd	d
}|t
jd|if ||d< |S )Ntitlemsg)
pre_enablepre_installpost_enablepre_disable   r   zubuntu-([a-z]+)-fipsZgenericr3   unknown)ZvariantserviceZbase_flavorcurrent_flavor)Zaccess_onlyr   is_containerr
   Z PROMPT_FIPS_CONTAINER_PRE_ENABLEformatr1   auto_upgrade_all_on_enableZFIPS_RUN_APT_UPGRADEpre_enable_msgr   prompt_for_confirmationpurgeZPROMPT_FIPS_PRE_DISABLEprompt_if_kernel_downgradelenpackagesrematchgroupget_kernel_infoZflavorgetZ#KERNEL_FLAVOR_CHANGE_WARNING_PROMPTnameappend)selfr3   r5   Zpre_enable_promptr6   r4   	messagingZubuntu_fips_package_nameZ ubuntu_fips_package_flavor_matchZubuntu_fips_package_flavorr:   r2    rM   </usr/lib/python3/dist-packages/uaclient/entitlements/fips.pyrL      s    
 
 

zFIPSCommonEntitlement.messagingc                 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seriesr;   #FIPS_CONTAINER_CONDITIONAL_PACKAGESrH   FIPS_CONDITIONAL_PACKAGES)rK   rP   rM   rM   rN   conditional_packages   s    
z*FIPSCommonEntitlement.conditional_packages)
assume_yesr/   c                C   s   t  j}|dkr td dS td|}td}|dk	r|dk	r|	d}t
d|| t||dk rttjj||d	 tjtj|d
S ntd|| dS )ztCheck if installing a FIPS kernel will downgrade the kernel
        and prompt for confirmation if it will.
        Nz Cannot gather kernel informationFz!(?P<kernel_version>\d+\.\d+\.\d+)r+   Zkernel_versionz*Kernel information: cur='%s' and fips='%s'r   )Zcurrent_versionZnew_version)r2   rT   z2Cannot gather kernel information for '%s' and '%s'T)r   rG   Zproc_version_signature_versionLOGwarningrD   searchr   Zget_pkg_candidate_versionrF   debugZversion_compareeventinfor
   ZKERNEL_DOWNGRADE_WARNINGr<   r   r?   ZPROMPT_YES_NO)rK   rT   Zour_full_kernel_strZour_mZfips_kernel_version_strZour_kernel_version_strrM   rM   rN   rA      sP    
 

  z0FIPSCommonEntitlement.prompt_if_kernel_downgradeprogressc                 C   s   g }t  }tt| jdd d}|D ]\}}||kr&||7 }q&|D ]V}z t j|gddidddgd	 W qD tjk
r   |d
t	j
j| j|d Y qDX qDd S )Nc                 S   s   |  ddS )Nz-hmac )replace)pkg_namerM   rM   rN   <lambda>#      zNFIPSCommonEntitlement.hardcoded_install_conditional_packages.<locals>.<lambda>)keyDEBIAN_FRONTENDnoninteractive--allow-downgrades$-o Dpkg::Options::="--force-confdef"$-o Dpkg::Options::="--force-confold"rC   Zoverride_env_varsZapt_optionsrZ   )r9   pkg)r   get_installed_packages_namesr   sortedrS   run_apt_install_commandr	   UbuntuProErroremitr
   ZFIPS_PACKAGE_NOT_AVAILABLEr<   r1   )rK   r\   Zdesired_packagesinstalled_packagesZ
pkg_groupsr_   Zpkg_listri   rM   rM   rN   &hardcoded_install_conditional_packages  s6    

	 z<FIPSCommonEntitlement.hardcoded_install_conditional_packagesc                 C   s*   t j| jjdd}t jdk}|p(| S )Nzfeatures.fips_auto_upgrade_allZconfigZpath_to_value>   r!   r"   r    )r   is_config_value_truecfgr   rO   rP   )rK   Zinstall_all_updates_overrideZhardcoded_releaserM   rM   rN   r=   =  s     z0FIPSCommonEntitlement.auto_upgrade_all_on_enablec                 C   s   dd t | jD }t jdkr.|d |  t|dkrzD|	dt
jjd|d | | t j|d	d
idddgd W n$ tjk
r   |	dt
j Y nX d S )Nc                 S   s   g | ]
}|j qS rM   )rI   ).0packagerM   rM   rN   
<listcomp>L  s   zMFIPSCommonEntitlement.install_all_available_fips_upgrades.<locals>.<listcomp>Zjammyr,   r   rZ    )rC   rc   rd   re   rf   rg   rh   )r   Z;get_installed_packages_with_uninstalled_candidate_in_originoriginr   rO   rP   rJ   sortrB   rn   r
   ZINSTALLING_PACKAGESr<   joinunhold_packagesrl   r	   rm   ZFIPS_PACKAGES_UPGRADE_FAILURE)rK   r\   Z
to_upgraderM   rM   rN   #install_all_available_fips_upgradesI  s6    


	z9FIPSCommonEntitlement.install_all_available_fips_upgradesN)r\   package_listcleanup_on_failurer/   c                    sh   | j }|rt j||d n|tjj| jd |  rF| 	| n
| 
| |  rdttj dS )zInstall 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.
        )r}   r0   N)rC   superinstall_packagesr\   r
   ZINSTALLING_SERVICE_PACKAGESr<   r1   r=   r|   rp   _check_for_rebootr   addr   FIPS_SYSTEM_REBOOT_REQUIRED)rK   r\   r}   r~   Zmandatory_packages	__class__rM   rN   r   m  s     
z&FIPSCommonEntitlement.install_packagesc                 C   s   t  S )z=Check if system needs to be rebooted because of this service.)r   should_rebootrK   rM   rM   rN   r     s    z'FIPSCommonEntitlement._check_for_rebootF)	operationsilentr/   c                 C   sF   |   }t| |rB|s.ttjj|d |dkrBt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
        )r   zdisable operationN)r   rY   Zneeds_rebootrZ   r
   ZENABLE_REBOOT_REQUIRED_TMPLr<   r   r   r   FIPS_DISABLE_REBOOT_REQUIRED)rK   r   r   Zreboot_requiredrM   rM   rN   _check_for_reboot_msg  s    
z+FIPSCommonEntitlement._check_for_reboot_msgrP   cloud_idr/   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_gcprq   T)r!   r"   r-   )r   rr   rs   boolr   rC   rK   rP   r   r   rM   rN   _allow_fips_on_cloud_instance  s    z3FIPSCommonEntitlement._allow_fips_on_cloud_instance.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azurer   r]   )rP   Zcloudc                      s     S N)r   rM   r   rK   rP   rM   rN   r`     ra   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)	r   r   rO   rP   r
   ZFIPS_BLOCK_ON_CLOUDr<   r1   rH   )rK   Zcloud_titles_Zblocked_messagerM   r   rN   static_affordances  s    

 z(FIPSCommonEntitlement.static_affordancesc                    s   t  rg S t jS r   )r   r;   r   rC   r   r   rM   rN   rC     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 }g }| jD ]}||kr|| q|rtjtjjd|| jdfS tjtj fS )N1)	file_namerw   )rC   r9   )!r   application_statusr   r;   r   r   remover   r   ospathexistsFIPS_PROC_FILEsetrC   Z	load_filestripZFIPS_MANUAL_DISABLE_URLr   r   DISABLEDr
   ZFIPS_PROC_FILE_ERRORr<   ZENABLEDr   rj   rJ   ZWARNINGZFIPS_PACKAGES_NOT_INSTALLEDrz   rI   FIPS_REBOOT_REQUIRED)rK   Zsuper_statusZ	super_msgro   Zmissingru   r   rM   rN   r     sR    

 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.
        r0   N)r   r   rj   rC   
differencerS   intersectionremove_packageslistr
   ZDISABLE_FAILED_TMPLr<   r1   )rK   ro   Zfips_metapackager   rM   rM   rN   r      s    

z%FIPSCommonEntitlement.remove_packagesr\   r/   c                    s8   t  |r4ttj ttj ttj dS dS NTF)r   _perform_enabler   r   r   ZWRONG_FIPS_METAPACKAGE_ON_CLOUDr   r   rK   r\   r   rM   rN   r   1  s    z%FIPSCommonEntitlement._perform_enablec                    s(   t  |r$|  r ttj dS dS r   )r   _perform_disabler   r   r   r   r   r   r   rM   rN   r   <  s    z&FIPSCommonEntitlement._perform_disablec                 C   sx   ddg}t |tjjd|d}g }| D ]}||kr0|| q0|rtddg| }t |tjjd|d}d S )Nzapt-markZ	showholdsrw   )ZcommandZunhold)r   Zrun_apt_commandr
   ZEXECUTING_COMMAND_FAILEDr<   rz   
splitlinesrJ   )rK   Zpackage_namescmdZholdsZunholdsZholdZ
unhold_cmdrM   rM   rN   r{   F  s"    z%FIPSCommonEntitlement.unhold_packagesc                    s   |  | j t | dS )zSetup apt config based on the resourceToken and directives.

        FIPS-specifically handle apt-mark unhold

        :raise UbuntuProError: on failure to setup any aspect of this apt
           configuration
        N)r{   fips_pro_package_holdsr   setup_apt_configr   r   rM   rN   r   Y  s    z&FIPSCommonEntitlement.setup_apt_config)NT)F).__name__
__module____qualname__Zrepo_pin_priorityrepo_key_filer   r
   PROMPT_FIPS_PRE_ENABLEr>   Zsupports_access_onlyZapt_noninteractiveZurlsZFIPS_HOME_PAGEZhelp_doc_urlr   propertyr   rL   rS   r   rA   r   ProgressWrapperrp   r=   r|   r   r   strr   r   r   r   r   r   r   rC   r   ZNamedMessager   r   r   r   r{   r   __classcell__rM   rM   r   rN   r*   V   s    T
/#'  
&   ;
r*   c                       s~   e Zd ZdZejZejZej	Z
dZejZeeedf dddZeeedf d fddZejed	 fd
dZ  ZS )FIPSEntitlementfipsZ
UbuntuFIPS.r.   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)rK   r   r   rM   rM   rN   incompatible_servicesm  s       z%FIPSEntitlement.incompatible_servicesc                    s   t  j}t| jd}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 )N)rs   r   F)r   fips_updatesc                      s    S r   rM   rM   )is_fips_updates_enabledrM   rN   r`     ra   z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      s    S r   rM   rM   )fips_updates_once_enabledrM   rN   r`     ra   )r   r   r   rs   r   r   r   r   r   readr   r
   Z$FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDr<   r1   Z)FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)rK   r   r   Zdisabled_statusZservices_once_enabled_objr   )r   r   rN   r   ~  s6     
 
z"FIPSEntitlement.static_affordancesr   c                    sR   t  \}}|d kr2|tjkr2td ttj t	 
|rNttj dS dS )Nz>Could not determine cloud, defaulting to generic FIPS package.TF)r   r   ZCLOUD_ID_ERRORrU   rV   rY   rZ   r
   Z.FIPS_COULD_NOT_DETERMINE_CLOUD_DEFAULT_PACKAGEr   r   r   r   r   ZFIPS_INSTALL_OUT_OF_DATE)rK   r\   Z
cloud_typeerrorr   rM   rN   r     s    
zFIPSEntitlement._perform_enable)r   r   r   rI   r
   Z
FIPS_TITLEr1   ZFIPS_DESCRIPTIONdescriptionZFIPS_HELP_TEXT	help_textrx   r   r>   r   r   r   r   r   r   r   r   r   r   r   rM   rM   r   rN   r   e  s   !r   c                       s`   e Zd ZdZejZdZejZ	ej
ZejZeeedf dddZejed fdd	Z  ZS )
r   zfips-updatesZUbuntuFIPSUpdates.r.   c                 C   s$   ddl m} tttjt|tjfS )Nr   r   )r   r   r   r   r
   FIPS_INVALIDATES_FIPS_UPDATESZ"REALTIME_FIPS_UPDATES_INCOMPATIBLE)rK   r   rM   rM   rN   r     s     z,FIPSUpdatesEntitlement.incompatible_servicesr   c                    s&   t  j|dr"ttdd dS dS )Nr[   T)r   F)r   r   r   writer   r   r   rM   rN   r     s    z&FIPSUpdatesEntitlement._perform_enable)r   r   r   rI   r
   ZFIPS_UPDATES_TITLEr1   rx   ZFIPS_UPDATES_DESCRIPTIONr   ZFIPS_UPDATES_HELP_TEXTr   ZPROMPT_FIPS_UPDATES_PRE_ENABLEr>   r   r   r   r   r   r   r   r   r   rM   rM   r   rN   r     s   r   c                       sd   e Zd ZdZejZejZej	Z
dZejZdZeeedf d fddZeeedd	d
Z  ZS )FIPSPreviewEntitlementzfips-previewZUbuntuFIPSPreviewzubuntu-pro-fips-preview.gpg.r.   c                    s   t  jtttjf S r   )r   r   r   r   r
   r   r   r   rM   rN   r     s     z,FIPSPreviewEntitlement.incompatible_servicesr   c                 C   s   dS )NTrM   r   rM   rM   rN   r     s    z4FIPSPreviewEntitlement._allow_fips_on_cloud_instance)r   r   r   rI   r
   ZFIPS_PREVIEW_TITLEr1   ZFIPS_PREVIEW_DESCRIPTIONr   ZFIPS_PREVIEW_HELP_TEXTr   rx   ZPROMPT_FIPS_PREVIEW_PRE_ENABLEr>   r   r   r   r   r   r   r   r   r   rM   rM   r   rN   r     s    r   )7Zloggingr   rD   	itertoolsr   typingr   r   r   Zuaclientr   r   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_loggerrY   Z	getLoggerZreplace_top_level_logger_namer   rU   ZCONDITIONAL_PACKAGES_EVERYWHEREZ!CONDITIONAL_PACKAGES_OPENSSH_HMACrR   Z&UBUNTU_FIPS_METAPACKAGE_DEPENDS_XENIALZ&UBUNTU_FIPS_METAPACKAGE_DEPENDS_BIONICZ%UBUNTU_FIPS_METAPACKAGE_DEPENDS_FOCALrQ   ZRepoEntitlementr*   r   r   r   rM   rM   rM   rN   <module>   s   $    L 