o
    ÙKÕiùg  ã                   @   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*g d¢Z+ddgZ,e+e, e+e, e+dœZ-g d¢Z.g d¢Z/g d¢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)r#   ú	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g d¢Zedefdd„ƒZed	d
„ ƒZdedefdd„Zdejfdd„Zdefdd„Zdejfdd„Z		d6dejdeee  deddf‡ fdd„Zdefdd„Z	d7d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#edee f‡ fd(d)„ƒZ$de!e%eej& f f‡ fd*d+„Z'd8d,d-„Z(dejdef‡ fd.d/„Z)dejdef‡ fd0d1„Z*d2d3„ Z+dejddf‡ fd4d5„Z,‡  Z-S )9ÚFIPSCommonEntitlementié  zubuntu-pro-fips.gpgz/proc/sys/crypto/fips_enabledT)zfips-initramfszfips-initramfs-genericr(   r)   Úlibgmp10Úlibgnutls30Úlibhogweed6Ú
libnettle8r$   r%   r$   r%   r&   r'   Úlibssl3z
linux-fipsr   r   r   r   r#   úopenssl-fips-module-3r   r   r   úubuntu-fipszubuntu-aws-fipszubuntu-azure-fipsúubuntu-gcp-fipsÚreturnc                 C   s0  d }d }| j s't ¡ rtjj| jd�}|  ¡ stjg}n| j	}t
jd|ifg}d }| js=| j s=t
jdtjj| jd�ifg}| j sF| ji fgnd }||||dœ}t| jƒdkr–| jd }t d|¡}|ri| d¡}	nd}	t ¡ j}
|	|
kr–| d¡pzg }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]+)-fipsÚgenericr7   Úunknown)ÚvariantÚserviceÚbase_flavorÚcurrent_flavor)Úaccess_onlyr   Úis_containerr
   Ú PROMPT_FIPS_CONTAINER_PRE_ENABLEÚformatr5   Úauto_upgrade_all_on_enableÚFIPS_RUN_APT_UPGRADEÚpre_enable_msgr   Úprompt_for_confirmationÚpurgeÚPROMPT_FIPS_PRE_DISABLEÚprompt_if_kernel_downgradeÚlenÚpackagesÚreÚmatchÚgroupÚget_kernel_infoÚflavorÚgetÚ#KERNEL_FLAVOR_CHANGE_WARNING_PROMPTÚnameÚappend)Úselfr7   r9   Úpre_enable_promptr:   r8   Ú	messagingÚubuntu_fips_package_nameÚ ubuntu_fips_package_flavor_matchÚubuntu_fips_package_flavorrA   r6   © r^   ú</usr/lib/python3/dist-packages/uaclient/entitlements/fips.pyrZ   „   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ÚseriesrC   Ú#FIPS_CONTAINER_CONDITIONAL_PACKAGESrT   ÚFIPS_CONDITIONAL_PACKAGES)rX   ra   r^   r^   r_   Úconditional_packagesÙ   s   
z*FIPSCommonEntitlement.conditional_packagesÚ
assume_yesc                C   sÎ   t  ¡ j}|du rt d¡ dS t d|¡}d}t| jƒdkr$| jd }t	 
| dd	¡¡}|dur^|dur^| d
¡}t d||¡ t	 ||¡dk r\t tjj||d�¡ tjtj|d�S dS 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+)r1   r;   r   ÚubuntuÚlinuxÚkernel_versionz*Kernel information: cur='%s' and fips='%s')Úcurrent_versionÚnew_version)r6   re   z2Cannot gather kernel information for '%s' and '%s'T)r   rR   Úproc_version_signature_versionÚLOGÚwarningrO   ÚsearchrM   rN   r   Úget_pkg_candidate_versionÚreplacerQ   ÚdebugÚversion_compareÚeventÚinfor
   ÚKERNEL_DOWNGRADE_WARNINGrE   r   rI   ÚPROMPT_YES_NO)rX   re   Úour_full_kernel_strÚour_mÚfips_packageÚfips_kernel_version_strÚour_kernel_version_strr^   r^   r_   rL   ì   sT   ÿ
ÿ

ÿ
ýÿýþÿÿ	ûýz0FIPSCommonEntitlement.prompt_if_kernel_downgradeÚprogressc                 C   sš   g }t  ¡ }tt| jƒdd„ d�}|D ]\}}||v r||7 }q|D ](}zt j|gddig d¢d� W q" tjyJ   | dt	j
j| j|d	�¡ Y q"w d S )
Nc                 S   s   |   dd¡S )Nz-hmacÚ )rp   )Úpkg_namer^   r^   r_   Ú<lambda>-  ó    zNFIPSCommonEntitlement.hardcoded_install_conditional_packages.<locals>.<lambda>)ÚkeyÚDEBIAN_FRONTENDÚnoninteractive©z--allow-downgradesz$-o Dpkg::Options::="--force-confdef"z$-o Dpkg::Options::="--force-confold"©rN   Úoverride_env_varsÚapt_optionsrt   )r?   Úpkg)r   Úget_installed_packages_namesr   Úsortedrd   Úrun_apt_install_commandr	   ÚUbuntuProErrorÚemitr
   ÚFIPS_PACKAGE_NOT_AVAILABLErE   r5   )rX   r|   Údesired_packagesÚinstalled_packagesÚ
pkg_groupsr~   Úpkg_listrˆ   r^   r^   r_   Ú&hardcoded_install_conditional_packages$  s4   þ€
ý	ÿþÿõz<FIPSCommonEntitlement.hardcoded_install_conditional_packagesc                 C   s*   t j| jjdd�}t ¡ jdv }|p| S )Nzfeatures.fips_auto_upgrade_all©ÚconfigÚpath_to_value>   r"   r!   r    )r   Úis_config_value_trueÚcfgr   r`   ra   )rX   Úinstall_all_updates_overrideÚhardcoded_releaser^   r^   r_   rF   G  s
   ÿ
z0FIPSCommonEntitlement.auto_upgrade_all_on_enablec                 C   s°   dd„ t  | j¡D ƒ}t ¡ jdkr| d¡ | ¡  t|ƒdkrVz"| 	dt
jjd |¡d�¡ |  |¡ t j|d	d
ig d¢d� W d S  tjyU   | 	dt
j¡ Y d S w d S )Nc                 S   s   g | ]}|j ‘qS r^   )rV   )Ú.0Úpackager^   r^   r_   Ú
<listcomp>V  s    ÿÿzMFIPSCommonEntitlement.install_all_available_fips_upgrades.<locals>.<listcomp>Újammyr0   r   rt   ú )rN   r‚   rƒ   r„   r…   )r   Ú;get_installed_packages_with_uninstalled_candidate_in_originÚoriginr   r`   ra   rW   ÚsortrM   r�   r
   ÚINSTALLING_PACKAGESrE   ÚjoinÚunhold_packagesr‹   r	   rŒ   ÚFIPS_PACKAGES_UPGRADE_FAILURE)rX   r|   Ú
to_upgrader^   r^   r_   Ú#install_all_available_fips_upgradesS  s4   ÿþ
ÿþ
ý	ÿîz9FIPSCommonEntitlement.install_all_available_fips_upgradesNÚpackage_listÚcleanup_on_failurec                    sl   | j }|rtƒ j||d� n| tjj| jd�¡ |  ¡ r#|  	|¡ n|  
|¡ |  ¡ r4t tj¡ dS dS )zï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.
        )r©   r4   N)rN   ÚsuperÚinstall_packagesr|   r
   ÚINSTALLING_SERVICE_PACKAGESrE   r5   rF   r¨   r“   Ú_check_for_rebootr   Úaddr   ÚFIPS_SYSTEM_REBOOT_REQUIRED)rX   r|   r©   rª   Úmandatory_packages©Ú	__class__r^   r_   r¬   w  s"   þÿ
ÿÿz&FIPSCommonEntitlement.install_packagesc                 C   s   t  ¡ S )z=Check if system needs to be rebooted because of this service.)r   Úshould_reboot©rX   r^   r^   r_   r®   �  s   z'FIPSCommonEntitlement._check_for_rebootFÚ	operationÚsilentc                 C   sN   |   ¡ }t |¡ |r#|st tjj|d�¡ |dkr%t t	j
¡ dS dS dS )zËCheck 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®   rs   Úneeds_rebootrt   r
   ÚENABLE_REBOOT_REQUIRED_TMPLrE   r   r¯   r   ÚFIPS_DISABLE_REBOOT_REQUIRED)rX   r¶   r·   Úreboot_requiredr^   r^   r_   Ú_check_for_reboot_msg¡  s   
ÿÿÿøz+FIPSCommonEntitlement._check_for_reboot_msgra   Úcloud_idc                    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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_gcpr”   T)r!   r"   r2   )r   r—   r˜   Úboolr«   rN   ©rX   ra   r½   r²   r^   r_   Ú_allow_fips_on_cloud_instance·  s   þz3FIPSCommonEntitlement._allow_fips_on_cloud_instance.c                    s^   ddddœ}t ƒ \‰ }ˆ d u rd‰ t ¡ j‰tjjˆ ¡ | ˆ ¡d�}|‡ ‡‡fdd„d	ffS )
Nzan AWSzan Azureza GCP)ÚawsÚazurer¾   r}   )ra   Úcloudc                      s   ˆ  ˆˆ ¡S ©N)rÁ   r^   ©r½   rX   ra   r^   r_   r   ä  r€   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)	r   r   r`   ra   r
   ÚFIPS_BLOCK_ON_CLOUDrE   r5   rT   )rX   Úcloud_titlesÚ_Úblocked_messager^   rÆ   r_   Ústatic_affordancesÖ  s   

ÿýÿz(FIPSCommonEntitlement.static_affordancesc                    s   t  ¡ rg S tƒ jS rÅ   )r   rC   r«   rN   rµ   r²   r^   r_   rN   é  s   zFIPSCommonEntitlement.packagesc                    s  t ƒ  ¡ \}}t ¡ rt ¡ st tj¡ ||fS t	j
 | j¡rSt t| jƒ¡s.t tj¡ t | j¡ ¡ dkrBt 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 ]}||vrp| |¡ qe|r‚tjtjjd |¡| jd�fS tjtj fS )NÚ1)Ú	file_namerŸ   )rN   r?   )!r«   Úapplication_statusr   rC   r´   r   Úremover   r°   ÚosÚpathÚexistsÚFIPS_PROC_FILEÚsetrN   Ú	load_fileÚstripÚFIPS_MANUAL_DISABLE_URLr¯   r   ÚDISABLEDr
   ÚFIPS_PROC_FILE_ERRORrE   ÚENABLEDr   r‰   rW   ÚWARNINGÚFIPS_PACKAGES_NOT_INSTALLEDr¤   rV   ÚFIPS_REBOOT_REQUIRED)rX   Úsuper_statusÚ	super_msgr�   Úmissingrœ   r²   r^   r_   rÎ   ï  sR   ÿÿÿÿÿþ


€ÿþþz(FIPSCommonEntitlement.application_statusc                 C   sT   t t ¡ ƒ}t | jƒ t | jƒ¡}| |¡}|r(t t|ƒt	j
j| jd�¡ dS dS )z¯Remove fips meta package to disable the service.

        FIPS meta-package will unset grub config options which will deactivate
        FIPS on any related packages.
        r4   N)rÔ   r   r‰   rN   Ú
differencerd   ÚintersectionÚremove_packagesÚlistr
   ÚDISABLE_FAILED_TMPLrE   r5   )rX   r�   Úfips_metapackagerã   r^   r^   r_   rã   *  s   
ÿ
þÿz%FIPSCommonEntitlement.remove_packagesc                    s8   t ƒ  |¡rt tj¡ t tj¡ t tj¡ dS dS ©NTF)r«   Ú_perform_enabler   rÏ   r   ÚWRONG_FIPS_METAPACKAGE_ON_CLOUDrÝ   rº   ©rX   r|   r²   r^   r_   rè   ;  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²   r^   r_   rë   F  s   ÿz&FIPSCommonEntitlement._perform_disablec                 C   s|   ddg}t  |tjjd |¡d�¡}g }| ¡ D ]}||v r#| |¡ q|r<ddg| }t  |tjjd |¡d�¡}d S d S )Nzapt-markÚ	showholdsrŸ   )ÚcommandÚunhold)r   Úrun_apt_commandr
   ÚEXECUTING_COMMAND_FAILEDrE   r¤   Ú
splitlinesrW   )rX   Úpackage_namesÚcmdÚholdsÚunholdsÚholdÚ
unhold_cmdr^   r^   r_   r¥   P  s&   þ
€ÿþþz%FIPSCommonEntitlement.unhold_packagesc                    s   |   | j¡ tƒ  |¡ dS )zÚSetup 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²   r^   r_   rù   c  s   z&FIPSCommonEntitlement.setup_apt_config©NT)F)r3   N).Ú__name__Ú
__module__Ú__qualname__Úrepo_pin_priorityÚrepo_key_filerÓ   r
   ÚPROMPT_FIPS_PRE_ENABLErH   Úsupports_access_onlyÚapt_noninteractiveÚurlsÚFIPS_HOME_PAGEÚhelp_doc_urlrø   Úpropertyr   rZ   rd   r¿   rL   r   ÚProgressWrapperr“   rF   r¨   r   r   Ústrr¬   r®   r¼   rÁ   r   r   rË   rN   r   ÚNamedMessagerÎ   rã   rè   rë   r¥   rù   Ú__classcell__r^   r^   r²   r_   r*   V   sx     T
8
ÿ#
ÿ'üþ
ýüû&ÿÿÿ
þÿÿþþ
;
 r*   c                       s€   e Zd ZdZejZejZej	Z
dZejZedeedf fdd„ƒZedeedf f‡ fdd„ƒZd	ejdef‡ fd
d„Z‡  ZS )ÚFIPSEntitlementÚfipsÚ
UbuntuFIPSr3   .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)
Úuaclient.entitlements.livepatchr  Úuaclient.entitlements.realtimer  r   r
   ÚLIVEPATCH_INVALIDATES_FIPSÚFIPSUpdatesEntitlementÚFIPS_UPDATES_INVALIDATES_FIPSÚREALTIME_FIPS_INCOMPATIBLE)rX   r  r  r^   r^   r_   Úincompatible_servicesw  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)r˜   r   F)r  Úfips_updatesc                      ó   ˆ S rÅ   r^   r^   )Úis_fips_updates_enabledr^   r_   r   ž  ó    z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      r  rÅ   r^   r^   )Úfips_updates_once_enabledr^   r_   r   ¥  r  )r«   rË   r  r˜   r   rØ   r¿   rÎ   r   Úreadr  r
   Ú$FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDrE   r5   Ú)FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)rX   rË   r  Údisabled_statusÚservices_once_enabled_objr²   )r  r  r_   rË   ˆ  s2   ÿÿýÿ
ûÿ
ûøz"FIPSEntitlement.static_affordancesr|   c                    sR   t ƒ \}}|d u r|tjkrt d¡ t tj¡ t	ƒ  
|¡r't tj¡ dS dS )Nz>Could not determine cloud, defaulting to generic FIPS package.TF)r   r   ÚCLOUD_ID_ERRORrl   rm   rs   rt   r
   Ú.FIPS_COULD_NOT_DETERMINE_CLOUD_DEFAULT_PACKAGEr«   rè   r   rÏ   r   ÚFIPS_INSTALL_OUT_OF_DATE)rX   r|   Ú
cloud_typeÚerrorr²   r^   r_   rè   ª  s   
ÿÿzFIPSEntitlement._perform_enable)rû   rü   rý   rV   r
   Ú
FIPS_TITLEr5   ÚFIPS_DESCRIPTIONÚdescriptionÚFIPS_HELP_TEXTÚ	help_textr¡   r   rH   r  r   r   r  r   rË   r   r  r¿   rè   r
  r^   r^   r²   r_   r  o  s     !r  c                       sb   e Zd ZdZejZdZejZ	ej
ZejZedeedf fdd„ƒZdejdef‡ fdd	„Z‡  ZS )
r  zfips-updatesÚUbuntuFIPSUpdatesr3   .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_UPDATESÚ"REALTIME_FIPS_UPDATES_INCOMPATIBLE)rX   r  r^   r^   r_   r  Ã  s   ÿþüz,FIPSUpdatesEntitlement.incompatible_servicesr|   c                    s&   t ƒ j|d�rt tdd�¡ dS dS )N)r|   T)r  F)r«   rè   r   Úwriter   rê   r²   r^   r_   rè   Ñ  s   ÿz&FIPSUpdatesEntitlement._perform_enable)rû   rü   rý   rV   r
   ÚFIPS_UPDATES_TITLEr5   r¡   ÚFIPS_UPDATES_DESCRIPTIONr)  ÚFIPS_UPDATES_HELP_TEXTr+  ÚPROMPT_FIPS_UPDATES_PRE_ENABLErH   r  r   r   r  r   r  r¿   rè   r
  r^   r^   r²   r_   r  »  s     r  c                       sh   e Zd ZdZejZejZej	Z
dZejZdZedeedf f‡ fdd„ƒZded	edefd
d„Z‡  ZS )ÚFIPSPreviewEntitlementzfips-previewÚUbuntuFIPSPreviewzubuntu-pro-fips-preview.gpgr3   .c                    s   t ƒ jtttjƒf S rÅ   )r«   r  r   r  r
   r-  rµ   r²   r^   r_   r  ä  s
   ÿÿz,FIPSPreviewEntitlement.incompatible_servicesra   r½   c                 C   s   dS rú   r^   rÀ   r^   r^   r_   rÁ   ì  s   z4FIPSPreviewEntitlement._allow_fips_on_cloud_instance)rû   rü   rý   rV   r
   ÚFIPS_PREVIEW_TITLEr5   ÚFIPS_PREVIEW_DESCRIPTIONr)  ÚFIPS_PREVIEW_HELP_TEXTr+  r¡   ÚPROMPT_FIPS_PREVIEW_PRE_ENABLErH   rÿ   r  r   r   r  r  r¿   rÁ   r
  r^   r^   r²   r_   r4  Û  s"    ÿÿþr4  )7ÚloggingrÐ   rO   Ú	itertoolsr   Útypingr   r   r   Úuaclientr   r   r   r	   r
   r   r   Úuaclient.clouds.identityr   r   Úuaclient.entitlementsr   Úuaclient.entitlements.baser   Ú(uaclient.entitlements.entitlement_statusr   Úuaclient.filesr   Úuaclient.files.noticesr   Úuaclient.files.state_filesr   r   Úuaclient.typesr   r   r   Úget_event_loggerrs   Ú	getLoggerÚreplace_top_level_logger_namerû   rl   ÚCONDITIONAL_PACKAGES_EVERYWHEREÚ!CONDITIONAL_PACKAGES_OPENSSH_HMACrc   Ú&UBUNTU_FIPS_METAPACKAGE_DEPENDS_XENIALÚ&UBUNTU_FIPS_METAPACKAGE_DEPENDS_BIONICÚ%UBUNTU_FIPS_METAPACKAGE_DEPENDS_FOCALrb   ÚRepoEntitlementr*   r  r  r4  r^   r^   r^   r_   Ú<module>   sj    $þÿÿûÿþÿþÿù    L 