o
    x[h‡¡  ã                   @   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;d2e1d3e1d4e1de8fd5d6„Z<G d7d8„ d8ƒZ=G d9d:„ d:e>ƒZ?G d;d<„ d<ƒZ@G d=d>„ d>ƒZAG d?d@„ d@ƒZBG dAdB„ dBƒZCe.		dSdCe1dDejDdEeee1  dFee1 fdGdH„ƒZEe.dCe1dIdJfdKdL„ƒZFdMdN„ ZGG dOdP„ dPe>ƒZHG dQdR„ dRƒZIdS )Té    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}|r˜d|v r˜| d¡d	 }|sžt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   é   é   )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 )zØReadurl 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†   )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ÚdisableSshPwdc                 C   s$   t  d¡}|j| ||d�}| d¡S )Na.          <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>
              <ns1:UserName>{username}</ns1:UserName>
              <ns1:DisableSshPasswordAuthentication>{disableSshPwd}
              </ns1:DisableSshPasswordAuthentication>
              <ns1:HostName>{hostname}</ns1:HostName>
            </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>
        )r�   r�   r‘   úutf-8)ÚtextwrapÚdedentÚformatÚencode)r�   r�   r‘   ÚOVF_ENV_TEMPLATEÚretr'   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__D  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(   ÚgetJ  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(   ÚpostQ  s
   

zAzureEndpointHttpClient.post)F©NN)r"   Ú
__module__Ú__qualname__r…   r    r   ÚUrlResponser¤   r	   Úbytesr¦   r'   r'   r'   r(   rš   >  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¬   [  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Œ|rŽtjd
dtd�� | j j|dd�j| _| jdu rztdƒ‚W d  ƒ dS 1 s…w   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    `  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®   _  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Ÿ   Ú Ú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 )z‘Decrypt 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   r•   rÓ   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 )z€Given 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    F  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_signal[  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_signalo  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 )zÙGets 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 )
zŠFetches 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,  2  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#  T  s   


ÿz"WALinuxAgentShim._get_user_pubkeysr/  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   )r/  r$  r÷   Úpubkeyrø   r'   r'   r(   r.  ~  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ü   Údictr.  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   
ÿr6  r  zerrors.ReportableErrorc                 C   s8   t | d�}| ¡ }z|j|d� W | ¡  d S | ¡  w )Nr4  r)  )r  Úas_encoded_reportr*  rË   )r  r  r5  r   r'   r'   r(   Úreport_failure_to_fabric³  s
   
r8  c                 C   s(   t d|  tjd� t d| tjd� d S )Nzdhclient output stream: %srV   zdhclient error stream: %s)r^   r5   r6   )rE   Úerrr'   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_dataÚdisable_ssh_password_authÚpublic_keysÚpreprovisioned_vmÚpreprovisioned_vm_typeÚprovision_guest_proxy_agentr�   r@  r�   rA  rB  rC  rD  rE  rF  r   c       	   
      C   s>   || _ || _|| _|| _|| _|pg | _|| _|| _|	| _d S rw   r?  )
rž   r�   r@  r�   rA  rB  rC  rD  rE  rF  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 )z×Parser 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)ÚclsrJ  r·   rD   Úinstancer'   r'   r(   Ú
parse_textê  s   €ÿÿ

zOvfEnvXml.parse_textr>  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<  rM  r5   r6   r   Ú!ReportableErrorOvfInvalidMetadataÚlen)rž   Únoder   rS  rT  Ú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:rU  r1   rV  r   rÑ   )rW  r<  rM  r5   r6   r   rX  rY  r¿   rd   Ú	b64decoderæ   r:   r   Útranslate_bool)
rž   rZ  r   rS  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©rS  Ú!LinuxProvisioningConfigurationSetÚ
CustomDataF)r]  rS  ÚUserNameÚUserPasswordÚHostNameÚ DisableSshPasswordAuthentication)r^  rS  )r\  rb  rA  r�   r@  r�   rB  Ú_parse_ssh_section)rž   r·   Úprovisioning_sectionÚ
config_setr'   r'   r(   rN  @  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ÚPlatformSettingsSectionTrd  ÚPlatformSettingsÚPreprovisionedVmF)r^  ra  rS  ÚPreprovisionedVMTypeÚProvisionGuestProxyAgent)r\  rb  rD  rE  rF  )rž   r·   Úplatform_settings_sectionÚplatform_settingsr'   r'   r(   rO  b  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ÚSSHFrd  Ú
PublicKeysz./wa:PublicKeyÚFingerprintÚPathÚValuerÑ   )ra  rS  )rø   r{   rÍ   )rC  r\  rW  r<  rM  rb  ró   )	rž   rm  Ússh_sectionÚpublic_keys_sectionÚ
public_keyrø   r{   rÍ   râ   r'   r'   r(   rk  ~  s2   ÿÿÿÿýñzOvfEnvXml._parse_ssh_section)r>  )FFN)r"   r¨   r©   rM  r	   r‹   r«   rÂ   r   r3  r    rI  ÚclassmethodrR  r\  rb  rN  rO  rk  r'   r'   r'   r(   r<  Ê  sx    þõýüûúù
ø	÷
öõ
ôûýü
ûùýüû
ú%"r<  r§   )Jrd   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   r3  r«   Úintrª   rŽ   r™   rš   rr   r¬   r®   rÃ   rý   r  r1  r6  r8  r:  r;  r<  r'   r'   r'   r(   Ú<module>   sÀ    
ý"
U
ÿÿ
þ

	úÿýüûúù6ÿÿÿ
þ"?   füÿþ
ýü		