o
    iɢ                     @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlmZ d dl	m	Z	m
Z
 d dlmZmZ d dlmZmZmZmZmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZ d d	lm Z  d d
l!m"Z" e#e$Z%dZ&dZ'dZ(dZ)dZ*e j+ddddZ,edZ-dede-f dede-f fddZ.e.dd Z/e.dd Z0ddde1de j2fd d!Z3d"d# Z4e.d$d% Z5ed&d' Z6e.dd(d)d*d+e1d,e7d-ee8 d.e9d/e9dej:fd0d1Z;d2ee1 d3ee1 d4ee< de8fd5d6Z=G d7d8 d8Z>G d9d: d:e?Z@G d;d< d<ZAG d=d> d>ZBG d?d@ d@ZCG dAdB dBZDe.		dUdCe1dDejEdEeee1  dFee1 fdGdHZFe.dCe1dIe1fdJdKZGdLe1dMe1dNe1ddfdOdPZHG dQdR dRe?ZIG dSdT dTZJdS )V    N)contextmanager)datetimetimezone)sleeptime)CallableListOptionalTypeVarUnion)ElementTree)escape)distrossubp
temp_utils
url_helperutilversion)events)errorsz168.63.129.16boot-telemetryzsystem-info
diagnostic
compressedzazure-dsz initialize reporter for azure dsT)namedescriptionreporting_enabledTfunc.returnc                    s    fdd}|S )Nc                     sF   t j j jtd  | i |W  d    S 1 sw   Y  d S )Nr   r   parent)r   ReportEventStack__name__azure_ds_reporter)argskwargsr    A/usr/lib/python3/dist-packages/cloudinit/sources/helpers/azure.pyimpl*   s   $z)azure_ds_telemetry_reporter.<locals>.implr'   )r   r)   r'   r&   r(   azure_ds_telemetry_reporter)   s   r*   c                  C   s  t  stdtd ztt tt  } W n t	y+ } ztd|d}~ww z*t
j
g ddd\}}d}|rGd|v rG|dd	 }|sMtd
| t|d  }W n& t
jyj } ztd| |d}~w t	y| } ztd| |d}~ww z*t
j
g ddd\}}d}|rd|v r|dd	 }|std| t|d  }W n& t
jy } ztd| |d}~w t	y } ztd| |d}~ww ttddt| tj t|tj t|tj f tj}t| |S )z[Report timestamps related to kernel initialization and systemd
    activation of cloud-initz1distro not using systemd, skipping boot telemetryzCollecting boot telemetryz*Failed to determine kernel start timestampN)	systemctlshow-pUserspaceTimestampMonotonicT)capture=   z8Failed to parse UserspaceTimestampMonotonic from systemdi@B z-Failed to get UserspaceTimestampMonotonic: %sz<Failed to parse UserspaceTimestampMonotonic from systemd: %s)r+   r,   zcloud-init-localr-   InactiveExitTimestampMonotonicz;Failed to parse InactiveExitTimestampMonotonic from systemdz0Failed to get InactiveExitTimestampMonotonic: %sz?Failed to parse InactiveExitTimestampMonotonic from systemd: %sr   z5kernel_start=%s user_start=%s cloudinit_activation=%s)r   uses_systemdRuntimeErrorLOGdebugfloatr   r   uptime
ValueErrorr   splitProcessExecutionErrorr   ReportingEventBOOT_EVENT_TYPEr   fromtimestampr   utc	isoformatDEFAULT_EVENT_ORIGINreport_event)kernel_starteout_tsm
user_startcloudinit_activationevtr'   r'   r(   get_boot_telemetry5   s   





rK   c                  C   sb   t  } ttddt | d | d | d d | d d | d d | d	 f tj}t| |S )
z%Collect and report system informationzsystem informationztcloudinit_version=%s, kernel_version=%s, variant=%s, distro_name=%s, distro_version=%s, flavor=%s, python_version=%sreleasevariantdistr   r1      python)	r   system_infor   r<   SYSTEMINFO_EVENT_TYPEr   version_stringrA   rB   )inforJ   r'   r'   r(   get_system_info   s$   



rU   logger_funcmsgc                C   s6   t |r||  ttd| tj}tj|dhd |S )zReport a diagnostic eventzdiagnostic messagelogexcluded_handler_types)callabler   r<   DIAGNOSTIC_EVENT_TYPErA   rB   )rX   rW   rJ   r'   r'   r(   report_diagnostic_event   s   r^   c                 C   sN   t t|}d|dd}tt| t	|tj
}tj|h dd |S )zReport a compressed eventzgz+b64ascii)encodingdata>   rY   printwebhookrZ   )base64encodebyteszlibcompressdecoder   r<   COMPRESSED_EVENT_TYPEjsondumpsrA   rB   )
event_nameevent_contentcompressed_data
event_datarJ   r'   r'   r(   report_compressed_event   s   rp   c               
   C   sn   t d ztjdgddd\} }td|  W dS  ty6 } ztdt| t jd W Y d}~dS d}~ww )	zReport dmesg to KVP.zDumping dmesg log to KVPdmesgFT)rh   r/   z$Exception when dumping dmesg log: %srV   N)r5   r6   r   rp   	Exceptionr^   reprwarning)rE   rF   exr'   r'   r(   report_dmesg_to_kvp   s   

rv   c              	   c   s@    t  }t t j|  zd V  W t | d S t | w N)osgetcwdchdirpath
expanduser)newdirprevdirr'   r'   r(   cd   s   r   r1      )ra   retry_sleeptimeout_minutesurlheadersra   r   r   c          	   
   C   s   |d t   }d}d}|sT|d7 }ztj| ||dd}W n7 tjyM } z$td| |||j|jf tjd t  | |ksBd	t	|v rC W Y d}~nd}~ww t
| |rtd
| |f tjd |S )zReadurl wrapper for querying wireserver.

    :param retry_sleep: Time to sleep before retrying.
    :param timeout_minutes: Retry up to specified number of minutes.
    :raises UrlError: on error fetching data.
    <   r   Nr1   )   r   )r   ra   timeoutzdFailed HTTP request with Azure endpoint %s during attempt %d with exception: %s (code=%r headers=%r)rV   zNetwork is unreachablez@Successful HTTP request with Azure endpoint %s after %d attempts)r   r   readurlUrlErrorr^   coder   r5   r6   strr   )	r   r   ra   r   r   r   attemptresponserD   r'   r'   r(   http_with_retries   s@   r   usernamehostnamedisable_ssh_password_authc              	   C   sh   | r	d|  d}nd}|d u rd}n
dt |  d}d| d}td| d	| d	| d
dS )Nz<ns1:UserName>z</ns1:UserName> z&<ns1:DisableSshPasswordAuthentication>z'</ns1:DisableSshPasswordAuthentication>z<ns1:HostName>z</ns1:HostName>a          <ns0:Environment xmlns:ns0="http://schemas.dmtf.org/ovf/environment/1"
         xmlns:ns1="http://schemas.microsoft.com/windowsazure"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <ns1:ProvisioningSection>
            <ns1:Version>1.0</ns1:Version>
            <ns1:LinuxProvisioningConfigurationSet>
              <ns1:ConfigurationSetType>LinuxProvisioningConfiguration
              </ns1:ConfigurationSetType>
              z
              a  
            </ns1:LinuxProvisioningConfigurationSet>
          </ns1:ProvisioningSection>
          <ns1:PlatformSettingsSection>
            <ns1:Version>1.0</ns1:Version>
            <ns1:PlatformSettings>
              <ns1:ProvisionGuestAgent>true</ns1:ProvisionGuestAgent>
            </ns1:PlatformSettings>
          </ns1:PlatformSettingsSection>
        </ns0:Environment>
        utf-8)r   lowertextwrapdedentencode)r   r   r   ns_usernamens_disable_ssh_password_authns_hostnamer'   r'   r(   build_minimal_ovf  s*   
	
r   c                   @   sL   e Zd ZdddZdd Zddejfdd	Z	
ddee	 dejfddZ
d
S )AzureEndpointHttpClientWALinuxAgentz
2012-11-30)zx-ms-agent-namezx-ms-versionc                 C   s   d|d| _ d S )NDES_EDE3_CBC)zx-ms-cipher-namez!x-ms-guest-agent-public-x509-cert)extra_secure_headers)selfcertificater'   r'   r(   __init__R  s   z AzureEndpointHttpClient.__init__Fr   c                 C   s,   | j }|r| j  }|| j t||dS )N)r   )r   copyupdater   r   )r   r   securer   r'   r'   r(   getX  s
   
zAzureEndpointHttpClient.getNra   c                 C   s0   | j }|d ur| j  }|| t|||dS )N)ra   r   )r   r   r   r   )r   r   ra   extra_headersr   r'   r'   r(   post_  s
   

zAzureEndpointHttpClient.post)FNN)r"   
__module____qualname__r   r   r   UrlResponser   r	   bytesr   r'   r'   r'   r(   r   L  s    r   c                   @   s   e Zd ZdZdS )InvalidGoalStateXMLExceptionz9Raised when GoalState XML is invalid or has missing data.N)r"   r   r   __doc__r'   r'   r'   r(   r   i  s    r   c                	   @   s:   e Zd Z	ddeeef dededdfddZd	d
 Z	dS )	GoalStateTunparsed_xmlazure_endpoint_clientneed_certificater   Nc              
   C   s   || _ zt|| _W n tjy" } z
td| tjd  d}~ww | d| _	| d| _
| d| _dD ]}t| |du rOd| }t|tjd t|q7d| _| d	}|dur|rtjd
dtd | j j|ddj| _| jdu rztdW d   dS 1 sw   Y  dS dS dS )ah  Parses a GoalState XML string and returns a GoalState object.

        @param unparsed_xml: string representing a GoalState XML.
        @param azure_endpoint_client: instance of AzureEndpointHttpClient.
        @param need_certificate: switch to know if certificates is needed.
        @return: GoalState object representing the GoalState XML string.
        z!Failed to parse GoalState XML: %srV   Nz./Container/ContainerIdz4./Container/RoleInstanceList/RoleInstance/InstanceIdz./Incarnation)container_idinstance_idincarnationzMissing %s in GoalState XMLzD./Container/RoleInstanceList/RoleInstance/Configuration/Certificateszget-certificates-xmlzget certificates xmlr   T)r   z/Azure endpoint returned empty certificates xml.)r   ET
fromstringroot
ParseErrorr^   r5   rt   _text_from_xpathr   r   r   getattrr   certificates_xmlr   r!   r#   r   contents)r   r   r   r   rD   attrrX   r   r'   r'   r(   r   n  sX   
"zGoalState.__init__c                 C   s   | j |}|d ur|jS d S rw   )r   findtext)r   xpathelementr'   r'   r(   r     s   zGoalState._text_from_xpath)T)
r"   r   r   r   r   r   r   boolr   r   r'   r'   r'   r(   r   m  s    

7r   c                   @   s   e Zd ZdddZdd Zdd Zedd	 Zejd
d	 Ze	dd Z
ee	dd Ze	dd Ze	dd Ze	dd Ze	dd ZdS )OpenSSLManagerzTransportPrivate.pemzTransportCert.pem)private_keyr   c                 C   s   t  | _d | _|   d S rw   )r   mkdtemptmpdir_certificategenerate_certificater   r'   r'   r(   r     s   
zOpenSSLManager.__init__c                 C   s   t | j d S rw   )r   del_dirr   r   r'   r'   r(   clean_up  s   zOpenSSLManager.clean_upc                 C   s   | j S rw   r   r   r'   r'   r(   r     s   zOpenSSLManager.certificatec                 C   s
   || _ d S rw   r   )r   valuer'   r'   r(   r     s   
c                 C   s   t d | jd urt d d S t| j= tddddddd	d
ddd| jd d| jd g d}t| jd 	 D ]}d|vrH||
 7 }q<|| _W d    n1 sVw   Y  t d d S )Nz7Generating certificate for communication with fabric...zCertificate already generated.opensslreqz-x509z-nodesz-subjz/CN=LinuxTransportz-days32768z-newkeyzrsa:3072z-keyoutr   z-outr   r   CERTIFICATEzNew certificate generated.)r5   r6   r   r   r   r   certificate_namesr   load_text_file
splitlinesrstrip)r   r   liner'   r'   r(   r     sD   


z#OpenSSLManager.generate_certificatec                 C   s"   ddd| g}t j ||d\}}|S )Nr   x509z-nooutra   )r   )actioncertcmdresultrF   r'   r'   r(   _run_x509_action  s   zOpenSSLManager._run_x509_actionc                 C   s*   |  d|}g d}tj||d\}}|S )Nz-pubkey)z
ssh-keygenz-iz-mPKCS8z-fz
/dev/stdinr   )r   r   )r   r   pub_key
keygen_cmdssh_keyrF   r'   r'   r(   _get_ssh_key_from_cert  s   z%OpenSSLManager._get_ssh_key_from_certc                 C   s6   |  d|}|d}||d d d}d|S )a  openssl x509 formats fingerprints as so:
        'SHA1 Fingerprint=07:3E:19:D1:4D:1C:79:92:24:C6:A0:FD:8D:DA:\
        B6:A8:BF:27:D4:73\n'

        Azure control plane passes that fingerprint as so:
        '073E19D14D1C799224C6A0FD8DDAB6A8BF27D473'
        z-fingerprintr0   r1   :r   )r   r   r:   join)r   r   raw_fpeqoctetsr'   r'   r(   _get_fingerprint_from_cert  s   	

z)OpenSSLManager._get_fingerprint_from_certc                 C   s   t |d}|j}ddddd|dg}t| j tjdjdi | j	d	d

|d\}}W d   |S 1 s;w   Y  |S )zDecrypt the certificates XML document using the our private key;
        return the list of certs and private keys contained in the doc.
        z.//Datas   MIME-Version: 1.0s<   Content-Disposition: attachment; filename="Certificates.p7m"s?   Content-Type: application/x-pkcs7-mime; name="Certificates.p7m"s!   Content-Transfer-Encoding: base64    r   zuopenssl cms -decrypt -in /dev/stdin -inkey {private_key} -recip {certificate} | openssl pkcs12 -nodes -password pass:T   
)shellra   Nr'   )r   r   r   r   r   r   r   r   formatr   r   )r   r   tagcertificates_contentlinesrE   rF   r'   r'   r(   _decrypt_certs_from_xml   s.   
z&OpenSSLManager._decrypt_certs_from_xmlc           	      C   sv   |  |}g }i }| D ]+}|| td|rg }qtd|r8d|}| |}| |}|||< g }q|S )zGiven the Certificates XML document, return a dictionary of
        fingerprints and associated SSH keys derived from the certs.z[-]+END .*?KEY[-]+$z[-]+END .*?CERTIFICATE[-]+$
)r   r   appendrematchr   r   r   )	r   r   rE   currentkeysr   r   r   fingerprintr'   r'   r(   parse_certificates  s   




z!OpenSSLManager.parse_certificatesN)r"   r   r   r   r   r   propertyr   setterr*   r   staticmethodr   r   r   r   r   r'   r'   r'   r(   r     s.    


!


r   c                   @   s   e Zd ZedZedZdZdZdZ	dZ
deded	ed
dfddZedddZeded
dfddZ		ddedededed
ef
ddZeded
dfddZdS )GoalStateHealthReportera          <?xml version="1.0" encoding="utf-8"?>
        <Health xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <GoalStateIncarnation>{incarnation}</GoalStateIncarnation>
          <Container>
            <ContainerId>{container_id}</ContainerId>
            <RoleInstanceList>
              <Role>
                <InstanceId>{instance_id}</InstanceId>
                <Health>
                  <State>{health_status}</State>
                  {health_detail_subsection}
                </Health>
              </Role>
            </RoleInstanceList>
          </Container>
        </Health>
        z        <Details>
          <SubStatus>{health_substatus}</SubStatus>
          <Description>{health_description}</Description>
        </Details>
        ReadyNotReadyProvisioningFailedi   
goal_stater   endpointr   Nc                 C   s   || _ || _|| _dS )a?  Creates instance that will report provisioning status to an endpoint

        @param goal_state: An instance of class GoalState that contains
            goal state info such as incarnation, container id, and instance id.
            These 3 values are needed when reporting the provisioning status
            to Azure
        @param azure_endpoint_client: Instance of class AzureEndpointHttpClient
        @param endpoint: Endpoint (string) where the provisioning status report
            will be sent to
        @return: Instance of class GoalStateHealthReporter
        N)_goal_state_azure_endpoint_client	_endpoint)r   r  r   r  r'   r'   r(   r   T  s   
z GoalStateHealthReporter.__init__c              
   C   sv   | j | jj| jj| jj| jd}td z| j|d W n t	y3 } z
t
d| tjd  d }~ww td d S )N)r   r   r   statusz Reporting ready to Azure fabric.documentz#exception while reporting ready: %srV   zReported ready to Azure fabric.)build_reportr  r   r   r   PROVISIONING_SUCCESS_STATUSr5   r6   _post_health_reportrr   r^   errorrT   )r   r
  rD   r'   r'   r(   send_ready_signali  s$   
z)GoalStateHealthReporter.send_ready_signalr   c              
   C   sv   | j | jj| jj| jj| j| j|d}z| j|d W n ty3 } zd| }t	|t
jd  d }~ww t
d d S )N)r   r   r   r  	substatusr   r	  z%exception while reporting failure: %srV   z!Reported failure to Azure fabric.)r  r  r   r   r   PROVISIONING_NOT_READY_STATUSPROVISIONING_FAILURE_SUBSTATUSr  rr   r^   r5   r  rt   )r   r   r
  rD   rX   r'   r'   r(   send_failure_signal}  s"   z+GoalStateHealthReporter.send_failure_signalr   r   r   r  c           	      C   sb   d}|d ur| j jt|t|d | j d}| jjtt|t|t|t||d}|dS )Nr   )health_substatushealth_description)r   r   r   health_statushealth_detail_subsectionr   )%HEALTH_DETAIL_SUBSECTION_XML_TEMPLATEr   r   "HEALTH_REPORT_DESCRIPTION_TRIM_LENHEALTH_REPORT_XML_TEMPLATEr   r   )	r   r   r   r   r  r  r   health_detailhealth_reportr'   r'   r(   r    s    	

z$GoalStateHealthReporter.build_reportr
  c                 C   sB   t d td d| j}| jj||ddid td d S )Nr   z&Sending health report to Azure fabric.zhttp://{}/machine?comp=healthzContent-Typeztext/xml; charset=utf-8)ra   r   z/Successfully sent health report to Azure fabric)r   r5   r6   r   r  r  r   )r   r
  r   r'   r'   r(   r    s   
z+GoalStateHealthReporter._post_health_report)r   Nr   )r"   r   r   r   r   r  r  r  r  r  r  r   r   r   r   r*   r  r  r   r  r  r'   r'   r'   r(   r   .  sN    	

r   c                   @   s   e Zd ZdefddZdd Zedejddfd	d
Z	e	ddejde
ee  fddZededdfddZededefddZedefddZedeeef dedefddZedededefddZedededefddZdS ) WALinuxAgentShimr  c                 C   s   || _ d | _d | _d S rw   )r  openssl_managerr   )r   r  r'   r'   r(   r     s   
zWALinuxAgentShim.__init__c                 C   s   | j d ur| j   d S d S rw   )r  r   r   r'   r'   r(   r     s   
zWALinuxAgentShim.clean_updistror   Nc              
   C   sT   t d z|| W d S  ty) } ztd| t jd W Y d }~d S d }~ww )NzEjecting the provisioning isoz(Failed ejecting the provisioning iso: %srV   )r5   r6   eject_mediarr   r^   r  )r   iso_devr  rD   r'   r'   r(   	eject_iso  s   
zWALinuxAgentShim.eject_isoc                 C   s   d}| j du r|durt | _ | j j}| jdu rt|| _| j|dud}d}|dur1| ||}t|| j| j}|durD| j	||d |
  |S )a  Gets the VM's GoalState from Azure, uses the GoalState information
        to report ready/send the ready signal/provisioning complete signal to
        Azure, and then uses pubkey_info to filter and obtain the user's
        pubkeys from the GoalState.

        @param pubkey_info: List of pubkey values and fingerprints which are
            used to filter and obtain the user's pubkey values from the
            GoalState.
        @return: The list of user's authorized pubkey values.
        Nr   )r  )r  r   r   r   r   _fetch_goal_state_from_azure_get_user_pubkeysr   r  r"  r  )r   r  pubkey_infor!  http_client_certificater  ssh_keyshealth_reporterr'   r'   r(   "register_with_azure_and_fetch_data  s*   

z3WALinuxAgentShim.register_with_azure_and_fetch_datar   c                 C   s@   | j du r
td| _ | jdd}t|| j | j}|j|d dS )zGets the VM's GoalState from Azure, uses the GoalState information
        to report failure/send provisioning failure signal to Azure.

        @param: user visible error description of provisioning failure.
        NFr#  r   )r   r   r$  r   r  r  )r   r   r  r)  r'   r'   r(   &register_with_azure_and_report_failure  s   


z7WALinuxAgentShim.register_with_azure_and_report_failurer   c                 C   s   |   }| ||S )a   Fetches the GoalState XML from the Azure endpoint, parses the XML,
        and returns a GoalState object.

        @param need_certificate: switch to know if certificates is needed.
        @return: GoalState object representing the GoalState XML
        )"_get_raw_goal_state_xml_from_azure_parse_raw_goal_state_xml)r   r   unparsed_goal_state_xmlr'   r'   r(   r$    s   
z-WALinuxAgentShim._fetch_goal_state_from_azurec              
   C   s   t d d| j}z tjddtd | j|}W d   n1 s%w   Y  W n t	yA } z
t
d| t jd  d}~ww t d	 |jS )
zFetches the GoalState XML from the Azure endpoint and returns
        the XML as a string.

        @return: GoalState XML string
        zRegistering with Azure...z!http://{}/machine/?comp=goalstatezgoalstate-retrievalzretrieve goalstater   Nz9failed to register with Azure and fetch GoalState XML: %srV   z#Successfully fetched GoalState XML.)r5   rT   r   r  r   r!   r#   r   r   rr   r^   rt   r6   r   )r   r   r   rD   r'   r'   r(   r-  %  s.   

z3WALinuxAgentShim._get_raw_goal_state_xml_from_azurer/  c              
   C   st   z	t || j|}W n ty } z
td| tjd  d}~ww dd|j d|j d|j	 g}t|tj
d |S )a  Parses a GoalState XML string and returns a GoalState object.

        @param unparsed_goal_state_xml: GoalState XML string
        @param need_certificate: switch to know if certificates is needed.
        @return: GoalState object representing the GoalState XML
        z"Error processing GoalState XML: %srV   Nz, zGoalState XML container id: %szGoalState XML instance id: %szGoalState XML incarnation: %s)r   r   rr   r^   r5   rt   r   r   r   r   r6   )r   r/  r   r  rD   rX   r'   r'   r(   r.  @  s,   z*WALinuxAgentShim._parse_raw_goal_state_xmlr  r&  c                 C   sH   g }|j dur"|dur"| jdur"td | j|j }| ||}|S )a  Gets and filters the VM admin user's authorized pubkeys.

        The admin user in this case is the username specified as "admin"
        when deploying VMs on Azure.
        See https://docs.microsoft.com/en-us/cli/azure/vm#az-vm-create.
        cloud-init expects a straightforward array of keys to be dropped
        into the admin user's authorized_keys file. Azure control plane exposes
        multiple public keys to the VM via wireserver. Select just the
        admin user's key(s) and return them, ignoring any other certs.

        @param goal_state: GoalState object. The GoalState object contains
            a certificate XML, which contains both the VM user's authorized
            pubkeys and other non-user pubkeys, which are used for
            MSI and protected extension handling.
        @param pubkey_info: List of VM user pubkey dicts that were previously
            obtained from provisioning data.
            Each pubkey dict in this list can either have the format
            pubkey['value'] or pubkey['fingerprint'].
            Each pubkey['fingerprint'] in the list is used to filter
            and obtain the actual pubkey value from the GoalState
            certificates XML.
            Each pubkey['value'] requires no further processing and is
            immediately added to the return list.
        @return: A list of the VM user's authorized pubkey values.
        Nz/Certificate XML found; parsing out public keys.)r   r  r5   r6   r   _filter_pubkeys)r   r  r&  r(  keys_by_fingerprintr'   r'   r(   r%  b  s   


z"WALinuxAgentShim._get_user_pubkeysr1  c                 C   s|   g }|D ]7}d|v r|d r| |d  qd|v r5|d r5|d }|| v r.| | |  qtd| qtd| q|S )a8  Filter and return only the user's actual pubkeys.

        @param keys_by_fingerprint: pubkey fingerprint -> pubkey value dict
            that was obtained from GoalState Certificates XML. May contain
            non-user pubkeys.
        @param pubkey_info: List of VM user pubkeys. Pubkey values are added
            to the return list without further processing. Pubkey fingerprints
            are used to filter and obtain the actual pubkey values from
            keys_by_fingerprint.
        @return: A list of the VM user's authorized pubkey values.
        r   r   zIovf-env.xml specified PublicKey fingerprint %s not found in goalstate XMLzFovf-env.xml specified PublicKey with neither value nor fingerprint: %s)r   r5   rt   )r1  r&  r   pubkeyr   r'   r'   r(   r0    s"   z WALinuxAgentShim._filter_pubkeysr   )r"   r   r   r   r   r   r*   r   Distror"  r	   r   r*  r,  r   r   r$  r   r-  r   r.  listr%  r   dictr0  r'   r'   r'   r(   r    sP    

%
!)r  r  r  r&  r!  c                 C   s0   t | d}z|j|||dW |  S |  w )Nr  )r  r&  r!  )r  r*  r   )r  r  r&  r!  shimr'   r'   r(   get_metadata_from_fabric  s   
r8  encoded_reportc                C   s0   t | d}z|j|d W |  d S |  w )Nr6  r+  )r  r,  r   )r  r9  r7  r'   r'   r(   report_failure_to_fabric  s   
r:  	interfacerE   errc                 C   s8   t d|  d| tjd t d|  d| tjd d S )Nz!dhcp client stdout for interface=z: rV   z!dhcp client stderr for interface=)r^   r5   r6   )r;  rE   r<  r'   r'   r(   dhcp_log_cb  s   
r=  c                   @   s   e Zd ZdS )NonAzureDataSourceN)r"   r   r   r'   r'   r'   r(   r>    s    r>  c                   @   s   e Zd ZdddZdddddddddd	dee dee d	ee d
ee dee deee	  dedee deddfddZ
defddZededd fddZ	d(dededefddZ			d)dedededefd d!Zd"d# Zd$d% Zd&d' ZdS )*	OvfEnvXmlz)http://schemas.dmtf.org/ovf/environment/1z)http://schemas.microsoft.com/windowsazure)ovfwaNF	r   passwordr   custom_datar   public_keyspreprovisioned_vmpreprovisioned_vm_typeprovision_guest_proxy_agentr   rC  r   rD  r   rE  rF  rG  rH  r   c       	   
      C   s>   || _ || _|| _|| _|| _|pg | _|| _|| _|	| _d S rw   rB  )
r   r   rC  r   rD  r   rE  rF  rG  rH  r'   r'   r(   r     s   

zOvfEnvXml.__init__c                 C   s   | j |j kS rw   )__dict__)r   otherr'   r'   r(   __eq__  s   zOvfEnvXml.__eq__ovf_env_xmlc              
   C   sp   zt |}W n t jy } ztj|d|d}~ww |d| jdu r)tdt }|	| |
| |S )zParser for ovf-env.xml data.

        :raises NonAzureDataSource: if XML is not in Azure's format.
        :raises errors.ReportableErrorOvfParsingException: if XML is
                unparsable or invalid.
        )	exceptionNz./wa:ProvisioningSectionz=Ignoring non-Azure ovf-env.xml: ProvisioningSection not found)r   r   r   r   "ReportableErrorOvfParsingExceptionr   
NAMESPACESr>  r?  &_parse_linux_configuration_set_section _parse_platform_settings_section)clsrL  r   rD   instancer'   r'   r(   
parse_text  s   

zOvfEnvXml.parse_textrA  r   required	namespacec                 C   sh   | d||f tj}|sd| }t| |rt|d S t|dkr0td|t|f |d S )Nz./%s:%smissing configuration for %rr1   *multiple configuration matches for %r (%d)r   )findallr?  rO  r5   r6   r   !ReportableErrorOvfInvalidMetadatalen)r   noder   rU  rV  matchesrX   r'   r'   r(   _find  s    


zOvfEnvXml._finddecode_base64
parse_boolc           
      C   s   | d| tj}|sd| }t| |rt||S t|dkr.td|t|f |d j}	|	d u r9|}	|rI|	d urIt	
d|	 }	|rPt|	}	|	S )Nz./wa:rW  r1   rX  r   r   )rY  r?  rO  r5   r6   r   rZ  r[  r   rd   	b64decoder   r:   r   translate_bool)
r   r\  r   rU  r_  r`  defaultr]  rX   r   r'   r'   r(   _parse_property*  s*   	




zOvfEnvXml._parse_propertyc                 C   s   | j |ddd}| j |ddd}| j|dddd| _| j|ddd| _| j|d	dd| _| j|d
dd| _| j|dddd| _| | d S )NProvisioningSectionTrU  !LinuxProvisioningConfigurationSet
CustomDataF)r_  rU  UserNameUserPasswordHostName DisableSshPasswordAuthentication)r`  rU  )r^  rd  rD  r   rC  r   r   _parse_ssh_section)r   r   provisioning_section
config_setr'   r'   r(   rP  O  s<   z0OvfEnvXml._parse_linux_configuration_set_sectionc                 C   sb   | j |ddd}| j |ddd}| j|ddddd| _| j|ddd| _| j|d	dddd| _d S )
NPlatformSettingsSectionTrf  PlatformSettingsPreprovisionedVmF)r`  rc  rU  PreprovisionedVMTypeProvisionGuestProxyAgent)r^  rd  rF  rG  rH  )r   r   platform_settings_sectionplatform_settingsr'   r'   r(   rQ  q  s2   z*OvfEnvXml._parse_platform_settings_sectionc           	      C   s   g | _ | j|ddd}|d u rd S | j|ddd}|d u rd S |dtjD ]'}| j|ddd}| j|ddd}| j|dd	dd
}|||d}| j | q&d S )NSSHFrf  
PublicKeysz./wa:PublicKeyFingerprintPathValuer   )rc  rU  )r   r{   r   )rE  r^  rY  r?  rO  rd  r   )	r   ro  ssh_sectionpublic_keys_section
public_keyr   r{   r   r   r'   r'   r(   rm    s2   zOvfEnvXml._parse_ssh_section)rA  )FFN)r"   r   r   rO  r	   r   r   r   r   r5  r   rK  classmethodrT  r^  rd  rP  rQ  rm  r'   r'   r'   r(   r?    sx    
	



%"r?  r   )Krd   rj   loggingrx   r   r   rf   
contextlibr   r   r   r   r   typingr   r   r	   r
   r   	xml.etreer   r   xml.sax.saxutilsr   	cloudinitr   r   r   r   r   r   cloudinit.reportingr   cloudinit.sources.azurer   	getLoggerr"   r5   DEFAULT_WIRESERVER_ENDPOINTr=   rR   r]   ri   r!   r#   r   r*   rK   rU   r   r<   r^   rp   rv   r   r5  r   intr   r   r   r   r   rr   r   r   r   r   r  r3  r8  r:  r=  r>  r?  r'   r'   r'   r(   <module>   s    
"
U



	6
0?   f
