o
    (fa                     @   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	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'   libssl3
linux-fipsr   r   r   r   r#   zopenssl-fips-module-3r   r   r   zubuntu-fipszubuntu-aws-fipszubuntu-azure-fipsubuntu-gcp-fipsreturnc                 C   s  d }t  rtjj| jd}|  stjg}n| j}d }| j	s-t
jdtjj| jdifg}t
jd|ifg| ji fg||d}t| jdkr| jd }td|}|rX|d}nd}t  j}||kr|dpig }	tjj|| j||ptd	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genericr6   unknown)variantservicebase_flavorcurrent_flavor)r   is_containerr
    PROMPT_FIPS_CONTAINER_PRE_ENABLEformatr4   auto_upgrade_all_on_enableFIPS_RUN_APT_UPGRADEpre_enable_msgpurger   prompt_for_confirmation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)selfr8   pre_enable_promptr9   	messagingubuntu_fips_package_name ubuntu_fips_package_flavor_matchubuntu_fips_package_flavorr@   r6   r5    r\   </usr/lib/python3/dist-packages/uaclient/entitlements/fips.pyrX      sn   

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seriesrA   #FIPS_CONTAINER_CONDITIONAL_PACKAGESrR   FIPS_CONDITIONAL_PACKAGES)rV   r_   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|}td}|durL|durL|	d}t
d|| t||dk rJt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+)r0   kernel_versionz*Kernel information: cur='%s' and fips='%s'r   )current_versionnew_version)r5   rc   z2Cannot gather kernel information for '%s' and '%s'T)r   rP   proc_version_signature_versionLOGwarningrM   searchr   get_pkg_candidate_versionrO   debugversion_compareeventinfor
   KERNEL_DOWNGRADE_WARNINGrC   r   rH   PROMPT_YES_NO)rV   rc   our_full_kernel_strour_mfips_kernel_version_strour_kernel_version_strr\   r\   r]   rJ      sJ   


	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 )replace)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"rL   override_env_varsapt_optionsro   )r>   pkg)r   get_installed_packages_namesr   sortedrb   run_apt_install_commandr	   UbuntuProErroremitr
   FIPS_PACKAGE_NOT_AVAILABLErC   r4   )rV   rv   desired_packagesinstalled_packages
pkg_groupsry   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^   r_   )rV   install_all_updates_overridehardcoded_releaser\   r\   r]   rD   2  s
   
z0FIPSCommonEntitlement.auto_upgrade_all_on_enablec                 C   s   dd t | jD }|  t|dkrJz"|dtjjd	|d | 
| t j|ddig d	d
 W d S  tjyI   |dtj Y d S w d S )Nc                 S   s   g | ]}|j qS r\   )rT   ).0packager\   r\   r]   
<listcomp>A  s    zMFIPSCommonEntitlement.install_all_available_fips_upgrades.<locals>.<listcomp>r   ro    )rL   r}   r~   r   r   )r   ;get_installed_packages_with_uninstalled_candidate_in_originoriginsortrK   r   r
   INSTALLING_PACKAGESrC   joinunhold_packagesr   r	   r   FIPS_PACKAGES_UPGRADE_FAILURE)rV   rv   
to_upgrader\   r\   r]   #install_all_available_fips_upgrades>  s0   
	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 )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   r3   N)rL   superinstall_packagesrv   r
   INSTALLING_SERVICE_PACKAGESrC   r4   rD   r   r   _check_for_rebootr   addr   FIPS_SYSTEM_REBOOT_REQUIRED)rV   rv   r   r   mandatory_packages	__class__r\   r]   r   ^  s"   
z&FIPSCommonEntitlement.install_packagesc                 C   s   t  S )z=Check if system needs to be rebooted because of this service.)r   should_rebootrV   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 )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   rn   needs_rebootro   r
   ENABLE_REBOOT_REQUIRED_TMPLrC   r   r   r   FIPS_DISABLE_REBOOT_REQUIRED)rV   r   r   reboot_requiredr\   r\   r]   _check_for_reboot_msg  s   
z+FIPSCommonEntitlement._check_for_reboot_msgr_   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"   r1   )r   r   r   boolr   rL   rV   r_   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   rw   )r_   cloudc                      s     S N)r   r\   r   rV   r_   r\   r]   rz     r{   z:FIPSCommonEntitlement.static_affordances.<locals>.<lambda>T)	r   r   r^   r_   r
   FIPS_BLOCK_ON_CLOUDrC   r4   rR   )rV   cloud_titles_blocked_messager\   r   r]   static_affordances  s   

z(FIPSCommonEntitlement.static_affordancesc                    s   t  rg S t jS r   )r   rA   r   rL   r   r   r\   r]   rL     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jtjfS )N1)	file_name)r   application_statusr   rA   r   r   remover   r   ospathexistsFIPS_PROC_FILEsetrL   	load_filestripFIPS_MANUAL_DISABLE_URLr   r   DISABLEDr
   FIPS_PROC_FILE_ERRORrC   ENABLEDFIPS_REBOOT_REQUIRED)rV   super_status	super_msgr   r\   r]   r     s:   
z(FIPSCommonEntitlement.application_statusc                 C   sT   t t }t | jt | j}||}|r(tt|t	j
j| j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.
        r3   N)r   r   r   rL   
differencerb   intersectionremove_packageslistr
   DISABLE_FAILED_TMPLrC   r4   )rV   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   rV   rv   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     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_FAILEDrC   r   
splitlinesrU   )rV   package_namescmdholdsunholdshold
unhold_cmdr\   r\   r]   r   &  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   r\   r]   r   9  s   z&FIPSCommonEntitlement.setup_apt_configNT)F)r2   N)-__name__
__module____qualname__repo_pin_priorityrepo_key_filer   r
   PROMPT_FIPS_PRE_ENABLErF   apt_noninteractiveurlsFIPS_HOME_PAGEhelp_doc_urlr   propertyr   rX   rb   r   rJ   r   ProgressWrapperr   rD   r   r   r   strr   r   r   r   r   r   r   rL   r   NamedMessager   r   r   r   r   r   __classcell__r\   r\   r   r]   r*   V   sv     J
.
#
#
&

*
 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
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)
uaclient.entitlements.livepatchr  uaclient.entitlements.realtimer  r   r
   LIVEPATCH_INVALIDATES_FIPSFIPSUpdatesEntitlementFIPS_UPDATES_INVALIDATES_FIPSREALTIME_FIPS_INCOMPATIBLE)rV   r  r  r\   r\   r]   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)r   r   F)r  fips_updatesc                          S r   r\   r\   )is_fips_updates_enabledr\   r]   rz   t      z4FIPSEntitlement.static_affordances.<locals>.<lambda>c                      r  r   r\   r\   )fips_updates_once_enabledr\   r]   rz   {  r  )r   r   r
  r   r   r   r   r   r   readr  r
   $FIPS_ERROR_WHEN_FIPS_UPDATES_ENABLEDrC   r4   )FIPS_ERROR_WHEN_FIPS_UPDATES_ONCE_ENABLED)rV   r   r  enabled_statusservices_once_enabled_objr   )r  r  r]   r   ^  s2   

z"FIPSEntitlement.static_affordancesrv   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_ERRORrh   ri   rn   ro   r
   .FIPS_COULD_NOT_DETERMINE_CLOUD_DEFAULT_PACKAGEr   r   r   r   r   FIPS_INSTALL_OUT_OF_DATE)rV   rv   
cloud_typeerrorr   r\   r]   r     s   
zFIPSEntitlement._perform_enable)r   r   r   rT   r
   
FIPS_TITLEr4   FIPS_DESCRIPTIONdescriptionFIPS_HELP_TEXT	help_textr   r   rF   r   r   r   r  r   r   r   r   r   r   r   r\   r\   r   r]   r  E  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UbuntuFIPSUpdatesr2   .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)rV   r  r\   r\   r]   r    s   z,FIPSUpdatesEntitlement.incompatible_servicesrv   c                    s&   t  j|drttdd dS dS )N)rv   T)r  F)r   r   r   writer   r   r   r\   r]   r     s   z&FIPSUpdatesEntitlement._perform_enable)r   r   r   rT   r
   FIPS_UPDATES_TITLEr4   r   FIPS_UPDATES_DESCRIPTIONr  FIPS_UPDATES_HELP_TEXTr!  PROMPT_FIPS_UPDATES_PRE_ENABLErF   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.gpgr2   .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_servicesr_   r   c                 C   s   dS r   r\   r   r\   r\   r]   r     s   z4FIPSPreviewEntitlement._allow_fips_on_cloud_instance)r   r   r   rT   r
   FIPS_PREVIEW_TITLEr4   FIPS_PREVIEW_DESCRIPTIONr  FIPS_PREVIEW_HELP_TEXTr!  r   PROMPT_FIPS_PREVIEW_PRE_ENABLErF   r   r   r   r   r  r   r   r   r   r\   r\   r   r]   r*    s"    r*  )7loggingr   rM   	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_loggerrn   	getLoggerreplace_top_level_logger_namer   rh   CONDITIONAL_PACKAGES_EVERYWHERE!CONDITIONAL_PACKAGES_OPENSSH_HMACra   &UBUNTU_FIPS_METAPACKAGE_DEPENDS_XENIAL&UBUNTU_FIPS_METAPACKAGE_DEPENDS_BIONIC%UBUNTU_FIPS_METAPACKAGE_DEPENDS_FOCALr`   RepoEntitlementr*   r  r
  r*  r\   r\   r\   r]   <module>   sh    $   rL 