a -@=j’ã @s–ddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z ddl m Z ddlmZmZmZmZmZmZmZmZmZmZddlmmmZddlmZmZm Z mZm!Z!m"Z"m#Z#m$Z$m%Z%m&Z&ddl'm(Z(m)Z)ddl*m+Z+dd l,m-Z-dd l.m/Z/dd l0m1Z1dd l2m3Z3dd l4m5Z5m6Z6m7Z7ddl8m9Z9ddl:m;Z;ddldgdgdgddgddgddgdgdggd¢gd¢dgd d!gd"œ Z?e @eA¡ZBe Cd#¡ZDgd$¢ZEejFejGd%ZHeeeIeeeeeIeeeIeeIfeeeIeeIeffZJGd&d'„d'eKƒZLGd(d)„d)e!jMejNd*�ZOeIePd+œd,d-„ZQeId.œd/d0„ZRde&jSfd1d2„ZTd3d4„ZUeIeeOd5œd6d7„ZVd>d:d;„ZWd/usr/lib/python3.9/site-packages/cloudinit/distros/__init__.pyr3�sr3c@s\eZdZUdZdZdZdZdZdZdZ dZ d d gZ d Z d Z d gZeeed<iZeeeeeffed<dZeZeeed<ddddœZejZeeed<dZ dZ!dZ"eed<dZ#e$eed<dZ%e$eed<dd„Z&e'ddœd d!„Z(d"d#„Z)e*e+e,ee-e.fe.fd$œd%d&„Z/e*d'œd(d)„Z0e1e2j3d*œd+d,„ƒZ4e1ee5j6d*œd-d.„ƒZ7e1e8d*œd/d0„ƒZ9e8d1œd2d3„Z:d4d5„Z;d²d6d7„Ze?dd?„ƒZCdd@œdAdB„ZDdCdD„ZEd¶dEdF„ZFd·dGdH„ZGdIdJ„ZHd¸eId*œdKdL„ZJeAjBd¹dMdN„ƒZKeAjBdOdP„ƒZLdQdR„ZMdSdT„ZNeAjBdºdUdV„ƒZOeAjBdWdX„ƒZPeAjBdYdZ„ƒZQd[d\„ZRd]d^„ZSe?d_d`„ƒZTdadb„ZUdcdd„ZVe1dedf„ƒZWdgdh„ZXeId*œdidj„ZYdkdl„ZZeId*œdmdn„Z[dodp„Z\dqdr„Z]edsœdtdu„Z^dvdw„Z_d»dxdy„Z`eaeIdzœd{d|„Zbd}d~„Zcd¼dd€„Zdd½d‚dƒ„Zed¾d„d…„Zfd¿d†d‡„Zgehdˆd‰„ƒZiehdÀdŠd‹„ƒZjehddŒœeeed�œdŽd�„ƒZkeeeed�œd‘d’„Zled*œd“d”„ZmdÁeaeed–œd—d˜„Zne?eeeeeead™œdšd›„ƒZoe1dœd�„ƒZpepjqdžd�„ƒZpe?e'e$e'dŸœd d¡„ƒZre?e'e$e'dŸœd¢d£„ƒZse?e'e'e$e'd¤œd¥d¦„ƒZte?edd§œd¨d©„ƒZue?ee$edªœd«d¬„ƒZve?eewd­œd®d¯„ƒZxdd*œd°d±„ZydS)ÂÚDistroz python3-pipz/usr/libz /etc/hostsz/etc/doas.confz"/etc/sudoers.d/90-cloud-init-usersz /etc/hostnamez /etc/shadowz/var/lib/extrausers/shadowz ^{username}::z^{username}:!:z/usr/share/zoneinfoz root:rootÚserviceÚinit_cmdÚrenderer_configsNÚnetworking_clsz-Hz-Pz-r)ZhaltZpoweroffZrebootÚnet_opséFz/etc/resolv.confZosfamilyÚdhclient_lease_directoryÚdhclient_lease_file_regexcCsT||_||_||_| ¡|_tj|_tj |_ t   |¡|_ g|_d|_d|_d|_dS)NT)Z_pathsÚ_cfgÚnamer=Ú networkingr!ÚALL_DHCP_CLIENTSÚdhcp_client_priorityÚiproute2ÚIproute2r>rZRunnersÚ_runnerÚpackage_managersÚ _dhcp_clientÚ_fallback_interfaceÚis_linux)ÚselfrCZcfgÚpathsr7r7r8Ú__init__©s  zDistro.__init__)Úci_pkl_versionÚreturncCsPd|jvs|jjs| ¡|_t|dƒs,d|_t|dƒs\} } | j dd„|jDƒvrÆq¦|  |  |j|j¡j | d�¡q¦|röt||ƒ‚dS)NzcFailed to install the following packages: %s. See associated package manager logs for more details.z"Package manager '%s' not availablecSsg|] }|j‘qSr7©rC)Ú.0Úpr7r7r8Ú óz+Distro.install_packages..rj)rir`rJÚgetÚ __class__Údifference_updateÚ availablereÚdebugrCÚupdateÚinstall_packagesÚinforbZ from_configrIrBr3) rNr_Z error_messagergrhZ total_failedÚmanagerZmanager_packagesZto_tryZfailedZ manager_typeZpackagesr7r7r8rvïsHÿ ý ÿ     ÿþÿzDistro.install_packages)rRc CsÖ|jr |jS|j}t |jdg¡}|rxg}t d|¡|D]4}tjD]}||j krD|  |¡q:qDt  d|¡q:|rx|}|D]L}z"|ƒ|_t d|j ¡|jWStj fyÆt d|j ¡Yq|0q|t  ¡‚dS)aaccess the distro's preferred dhcp client if no client has been selected yet select one - uses self.dhcp_client_priority, which may be overridden in each distro's object to eliminate checking for clients which will not be provided by the distro )ÚnetworkrFz.Using configured dhcp client priority list: %sz4Configured dhcp client %s is not supported, skippingzDHCP client selected: %szDHCP client not found: %sN) rKrFrÚget_cfg_by_pathrBrertr!rEZ client_nameÚappendÚwarningZNoDHCPLeaseMissingDhclientError)rNrFZconfig_priorityZ found_clientsZclient_configuredZ client_classZclientr7r7r8Ú dhcp_client$s> ÿþ   þ  zDistro.dhcp_clientcCst |jdd¡}tj|d�S)z»Return the configured network activator for this environment. :returns: The network activator class to use :raises: NoActivatorException if no activator is found )ryr N©Úpriority)rrzrBr Zselect_activator)rNrr7r7r8Únetwork_activator`sÿzDistro.network_activatorcCsDt |jdd¡}tj|d�\}}t d||¡||j |¡d�}|S)N)ryr"r~z-Selected renderer '%s' from priority list: %s)Zconfig) rrzrBr"Zselectrertr<rp)rNrrCZ render_clsÚrendererr7r7r8Únetwork_rendererlsÿÿzDistro.network_renderer©r�cCs| |¡dS©N)Zrender_network_state)rNÚ network_stater�r7r7r8Ú_write_network_stateyszDistro._write_network_statecCs4tj |jt|ƒ¡}tj |¡s0td||fƒ‚|S)Nz(Invalid timezone %s, no file found at %s)ÚosÚpathÚjoinÚ tz_zone_dirrXÚisfileÚIOError)rNÚtzÚtz_filer7r7r8Ú _find_tz_file|s   ÿzDistro._find_tz_filecCs|j ||¡Sr„)rBrp)rNÚopt_nameÚdefaultr7r7r8Ú get_option„szDistro.get_optioncCs||j|<dSr„)rB)rNr�Úvaluer7r7r8Ú set_option‡szDistro.set_optioncCs(| ||¡}| ||j¡| |¡dSr„)Ú_select_hostnameÚ_write_hostnameÚhostname_conf_fnÚ_apply_hostname)rNÚhostnameÚfqdnZwriteable_hostnamer7r7r8Ú set_hostnameŠs zDistro.set_hostnamecCstƒS)z?Wrapper to report whether this distro uses systemd or sysvinit.)Ú uses_systemdr7r7r7r8rœ�szDistro.uses_systemdcCs tƒ‚dSr„©ÚNotImplementedError)rNÚcommandÚargsZpkgsr7r7r8Úpackage_command”szDistro.package_command©Úforcec Csn|jD]b}| ¡s"t d|j¡qz|j|d�Wqtyf}zt d|j|¡WYd}~qd}~00qdS)Nz8Skipping update for package manager '%s': not available.r¢z%Failed to update package using %s: %s)rJrsrertrCÚupdate_package_sourcesÚ Exceptionrf)rNr£rxÚer7r7r8r¤›s þÿzDistro.update_package_sourcescCst ¡d}|dvrdS|S)Né)Úi386Zi486Zi586Zi686r¨)r‡Úuname)rNr)r7r7r8Úget_primary_archªs zDistro.get_primary_archcCs"| dg¡}|s| ¡}t||ƒS)NÚpackage_mirrors)r’rªÚ_get_arch_package_mirror_info)rNr)Ú mirror_infor7r7r8r¬°s z$Distro._get_arch_package_mirror_infocCs| |¡}t||d�S)N)Ú data_sourcer­)r¬Ú_get_package_mirror_info)rNr)r®Z arch_infor7r7r8Úget_package_mirror_info¶s ÿzDistro.get_package_mirror_infocCst ¡Sr„)rÚgenerate_fallback_config©rNr7r7r8r±¾szDistro.generate_fallback_configcCsr|j}t||d�}| ||¡|rdt d¡z |j}Wn tjyVt d¡YdS0|  |¡n t d¡dS)aApply the network config. If bring_up is True, attempt to bring up the passed in devices. If devices is None, attempt to bring up devices returned by _write_network_config. Returns True if any devices failed to come up, otherwise False. rƒz/Bringing up newly configured network interfacesz>No network activator found, not bringing up network interfacesTz3Not bringing up newly configured network interfacesF) r‚r$r†rertr€r ZNoActivatorExceptionr|Zbring_up_all_interfaces)rNZ netconfigZbring_upr�r…r€r7r7r8Úapply_network_configÁs     ÿ  zDistro.apply_network_configcCs tƒ‚dSr„r�)rNÚlocaleZout_fnr7r7r8Ú apply_localeÞszDistro.apply_localecCs tƒ‚dSr„r�)rNr�r7r7r8Ú set_timezoneâszDistro.set_timezonecCsdS)Nz 127.0.0.1r7r²r7r7r8Ú_get_localhost_ipæszDistro._get_localhost_ipcCs tƒ‚dSr„r�r²r7r7r8Ú get_localeészDistro.get_localecCs tƒ‚dSr„r�)rNÚfilenamer‘r7r7r8Ú_read_hostnameìszDistro._read_hostnamecCs tƒ‚dSr„r�)rNr™r¹r7r7r8r–ðszDistro._write_hostnamecCs tƒ‚dSr„r�r²r7r7r8Ú_read_system_hostnameôszDistro._read_system_hostnamecCsFt d|¡zt d|g¡Wn"tjy@t td|¡Yn0dS)Nz2Non-persistently setting the system hostname to %sr™z;Failed to non-persistently adjust the system hostname to %s)rertrÚProcessExecutionErrorrÚlogexc)rNr™r7r7r8r˜øsÿýzDistro._apply_hostnamecCs&t |jd|j¡r|r|S|s"|S|S)NZprefer_fqdn_over_hostname)rZget_cfg_option_boolrBÚ prefer_fqdn)rNr™ršr7r7r8r• s ÿÿüzDistro._select_hostnamecCs6g}|D](}|tvr"td |¡ƒ‚| t|¡q|S)Nz&No distributions found for osfamily {})Ú OSFAMILIESr\ÚformatÚextend)Z family_listZdistrosZfamilyr7r7r8Úexpand_osfamilysÿzDistro.expand_osfamilyc Cs|}| ||¡}|r,tj |¡r,| |¡}nd}| ¡\}}g}|rL||krV| |¡|rj||krt||krt| |¡|r–|r–||kr–t d||¡dSt dd„|Dƒƒ}t  d|t |ƒ¡|D]8} z|  || ¡Wq¾t yôt td|| ¡Yq¾0q¾||v�r | |¡dS)Nz6%s differs from %s, assuming user maintained hostname.cSsg|] }|r|‘qSr7r7)rlÚfr7r7r8rnOroz*Distro.update_hostname..z/Attempting to update hostname to %s in %s filesz!Failed to write hostname %s to %s)r•r‡rˆÚexistsrºr»r{rerwr`rtr[r–rŒrr½r˜) rNr™ršZprev_hostname_fnZapplying_hostnameZ prev_hostnameZsys_fnZ sys_hostnameZ update_filesÚfnr7r7r8Úupdate_hostname"sJ     ÿÿ ýý ÿ  zDistro.update_hostnamec Cs~d}tj |j¡r&t t |j¡¡}nt d¡}tjdd�}|  ¡}|  |¡}d}|sj|  |||¡d}nÌd}|D]T}d} g} t |ƒdkr’|d} t |ƒdkrª|dd…} | durr| |krr|| vrrd}qr|�r6t |ƒ} |  ||g¡| |¡| D]B}t |ƒdk�r|  ||d¡qòt |ƒdkrò|j |g|¢RŽqò|�rztƒ} |�rV|  d |¡|  d |¡tj|j|  ¡d d �dS) NÚÚadded©ÚbaseFTr?rrVz%s i¤©Úmode)r‡rˆrÄÚhosts_fnrZ HostsConfrÚload_text_fileÚ make_headerr·Z get_entryZ add_entryr[rYr{Z del_entriesrÚwriteÚ write_fileÚgetvalue) rNr™ršÚheaderZehZlocal_ipZ prev_infoZ need_changer]Z entry_fqdnZ entry_aliasesZ new_entriesÚcontentsr7r7r8Úupdate_etc_hostscsJ        zDistro.update_etc_hostscCs|jsttƒ|_|jS)z7Allow distro to determine the preferred ntp client list)Ú_preferred_ntp_clientsrYÚPREFERRED_NTP_CLIENTSr²r7r7r8Úpreferred_ntp_clientsŽs zDistro.preferred_ntp_clientscCs | d¡S)NZ default_user)r’r²r7r7r8Úget_default_user–szDistro.get_default_userc Ks¢t |¡rt d|¡dSd|vr.| d¡}nd}d|g}d|g}t ¡r^| d¡| d¡ddd d d d d ddddœ }ddddœ}dg}| d¡} | �rt| t ƒr®|   d¡} t| t ƒrÐt j d|›d�ddd�dd„| Dƒ} d | ¡|d<| d ¡} | �r|  | ¡|�rB| �rB| D]*} t | ¡�s| | ¡t d!| |¡�qd"| ¡v�r`t |d"ƒ|d"<t| ¡ƒD]–\} } | |v�rÔ| �rÔt| t ƒ�rÔ| || | g¡| |v�rÀ| || d#g¡n| || | g¡n,| |v�rl| �rl| || ¡| || ¡�ql| d$¡�s| d%¡�r2| d&¡| d&¡n| d'¡| d'¡t d(|¡ztj||d)�Wn8t�yœ}zt td*|¡|‚WYd+}~n d+}~00dS),zé Add a user to the system using standard GNU tools This should be overridden on distros where useradd is not desirable or not available. Returns False if user already exists, otherwise True. z!User %s already exists, skipping.FÚ create_groupsTZuseraddú --extrausersz --commentz--homez--gidz--uidz--groupsú --passwordz--shellz --expiredatez --inactivez--selinux-user) ZgecosÚhomedirÚ primary_groupÚuidÚgroupsÚpasswdÚshellZ expiredateZinactiveZ selinux_userz--no-user-groupz--systemz --no-log-init)Z no_user_groupÚsystemZ no_log_initráràú,z The user z) has a 'groups' config value of type dictz22.3z=Use a comma-delimited string or array instead: group1,group2.©Z deprecatedZdeprecated_versionZ extra_messagecSsg|] }| ¡‘qSr7©Ústrip)rlÚgr7r7r8rnÝroz#Distro.add_user..rÞz created group '%s' for user '%s'rßZREDACTEDZno_create_homerãz-Mz-mzAdding user %s)Ú logstringzFailed to create user %sN)rÚis_userrerwÚpopÚsystem_is_snappyr{rprWrXÚsplitrarÚ deprecater‰Úis_groupÚ create_grouprtÚkeysÚsortedrbrÁrr¥r½)rNrCÚkwargsrÚZ useradd_cmdZlog_useradd_cmdZ useradd_optsZ useradd_flagsZ redact_optsràrÞÚgroupÚkeyÚvalr¦r7r7r8Úadd_user™sŒ     öý     ü            zDistro.add_userc Ksº| d¡}| dd¡}gd¢}|r,| d¡| |¡t d|¡z.ú^ú:zUser %s not found in %sz0User %s found in %s. Checking for empty passwordTF)rrìÚshadow_extrausers_fnÚ shadow_fnr‰Ú#shadow_empty_locked_passwd_patternsr‡rˆrÄrÎÚreÚfindallÚ MULTILINErert)rNrûZ shadow_filesZshadow_empty_passwd_reZ shadow_fileZshadow_contentr7rr8Ú$_shadow_file_has_empty_user_password-s2 þÿ  ýÿz+Distro._shadow_file_has_empty_user_passwordc KsÒd|vr|j|fi|¤ŽS|j|fi|¤Ž }d}d}d}d}d|vrld}d}|drh| ||d¡nd}d|vržd}d}|drš|j||ddd�nd}|rÔ|sðd|vrÆd}ttd tjd |d �| |¡ }nd|vrðd}d}|dsðd}| d d¡�r |  |¡n\|�s|�r6|�r*t  d ||¡|  |¡n0|�rRttd tjd|d �nttd tjd|d �d|v�rŠ|d�rŠ|  ||d¡d|v�rÖ|d�r°|  ||d¡n&|ddu�rÖtjd|›d�ddd�d|v�rd|d}t|tƒ�rü|g}nt|tƒ�rt| ¡ƒ}|du�rTt|tttfƒ�sFt dt|ƒ¡g}nt|ƒ�pRg}t t|ƒ|¡d|v�rÎ| dg¡} | �s”t d||d¡n:|d} tj} |  d| ¡} |  d|¡} tjt| ƒ|| d�dS)a� Creates or partially updates the ``name`` user in the system. This defers the actual user creation to ``self.add_user`` or ``self.add_snap_user``, and most of the keys in ``kwargs`` will be processed there if and only if the user does not already exist. Once the existence of the ``name`` user has been ensured, this method then processes these keys (for both just-created and pre-existing users): * ``plain_text_passwd`` * ``hashed_passwd`` * ``lock_passwd`` * ``doas`` * ``sudo`` * ``ssh_authorized_keys`` * ``ssh_redirect_user`` røFNZplain_text_passwdTZ hashed_passwd)Úhashedráz24.3z5'passwd' in user-data is ignored for existing user %s)ÚloggerÚversionZrequested_levelÚmsgr Ú lock_passwdzIAllowing unlocking empty password for %s based on empty '%s' in user-datazºNot unlocking blank password for existing user %s. 'lock_passwd: false' present in user-data but no existing password set and no 'plain_text_passwd'/'hashed_passwd' provided in user-dataz—Not unlocking password for user %s. 'lock_passwd: false' present in user-data but no 'passwd'/'plain_text_passwd'/'hashed_passwd' provided in user-dataZdoasZsudozThe value of 'false' in user z's 'sudo' configz22.2zUse 'null' instead.råZssh_authorized_keyszZInvalid type '%s' detected for 'ssh_authorized_keys', expected list, string, dict, or set.Zssh_redirect_userZcloud_public_ssh_keysz^Unable to disable SSH logins for %s given ssh_redirect_user: %s. No cloud public-keys present.z$USERz $DISABLE_USER)Úoptions)rþr÷Ú set_passwdrreÚloggingZWARNINGr rprrtÚ unlock_passwdÚwrite_doas_rulesÚwrite_sudo_rulesrrîrWrXrarYÚvaluesrZr`r|ÚtyperZsetup_user_keysZDISABLE_USER_OPTSÚreplace) rNrCróZpre_existing_userZhas_existing_passwordZud_blank_password_specifiedZud_password_specifiedZ password_keyrñZ cloud_keysZ redirect_userZdisable_optionr7r7r8Ú create_userOsÒú ÿ  ü ø ù     ü     ü  ü   ÿzDistro.create_userc Cs¶dd|gdd|gf}ztdd„|Dƒƒ}Wn@tyj}z(td|dd „|Dƒfƒ|‚WYd }~n d }~00zt |¡Wn6ty°}zt td |¡|‚WYd }~n d }~00d S) zL Lock the password of a user, i.e., disable password logins ráz-lÚusermodz--lockcss |]}t |d¡r|VqdS©rN©rÚwhich©rlZtoolr7r7r8Ú roz%Distro.lock_passwd..zBUnable to lock user account '%s'. No tools available. Tried: %s.cSsg|] }|d‘qS©rr7©rlÚcr7r7r8rn roz&Distro.lock_passwd..Nz&Failed to disable password for user %s©ÚnextÚ StopIterationÚ RuntimeErrorrr¥rr½re)rNrCZ lock_toolsÚcmdr¦r7r7r8rs ÿÿýzDistro.lock_passwdrkc Cs€dd|gdd|gf}ztdd„|Dƒƒ}Wn@tyj}z(td|dd „|Dƒfƒ|‚WYd }~n d }~00ztj|d d gd �\}}Wn6ty¼}zt td|¡|‚WYd }~n d }~00|�r|dd|gddd|gf}ztdd„|Dƒƒ}WnBt�y2}z(td|dd „|Dƒfƒ|‚WYd }~n d }~00zt |¡Wn8t�yz}zt td|¡|‚WYd }~n d }~00d S)zM Unlock the password of a user, i.e., enable password logins ráz-urz--unlockcss |]}t |d¡r|VqdSrrrr7r7r8rroz'Distro.unlock_passwd..zDUnable to unlock user account '%s'. No tools available. Tried: %s.cSsg|] }|d‘qSr r7r!r7r7r8rn roz(Distro.unlock_passwd..Nré©Úrcsz%Failed to enable password for user %sz-drÜz''css |]}t |d¡r|VqdSrrrr7r7r8r0szTUnable to set blank password for user account '%s'. No tools available. Tried: %s.cSsg|] }|d‘qSr r7r!r7r7r8rn7roz(Failed to set blank password for user %sr#)rNrCZ unlock_toolsr'r¦Ú_rýZpasswd_set_toolsr7r7r8rsNÿÿý þÿ þÿüÿzDistro.unlock_passwdc CsPzt dd|g¡Wn6tyJ}zt td|¡|‚WYd}~n d}~00dS)Nráz--expirezFailed to set 'expire' for %s)rr¥rr½re)rNÚuserr¦r7r7r8Ú expire_passwdAs zDistro.expire_passwdc Cstd||f}dg}|r | d¡ztj||d|d�Wn6tyn}zt td|¡|‚WYd}~n d}~00dS)Nz%s:%sÚchpasswdú-ezchpasswd for %s)ÚdatarézFailed to set password for %sT)r{rr¥rr½re)rNr,rár Z pass_stringr'r¦r7r7r8rHs   ÿ zDistro.set_passwd)Úplist_inr cCs>d dd„|Dƒ¡d}dg|r&dgng}tj||d�dS)NÚ css |]\}}d ||g¡VqdS)rN©r‰)rlrCÚpasswordr7r7r8r_roz"Distro.chpasswd..r.r/)r0)r‰r)rNr1r Zpayloadr'r7r7r8r.\s ÿýÿ zDistro.chpasswdcCszd}t d||¡t ||¡}|rht d| d¡¡| d¡|krPt d¡dSt d| d¡¡dSnt d ¡dSdS) Nz²^(?:permit|deny)(?:\s+(?:nolog|nopass|persist|keepenv|setenv \{[^}]+\})+)*\s+([a-zA-Z0-9_]+)+(?:\s+as\s+[a-zA-Z0-9_]+)*(?:\s+cmd\s+[^\s]+(?:\s+args\s+[^\s]+(?:\s*[^\s]+)*)*)*\s*$z3Checking if user '%s' is referenced in doas rule %rz!User '%s' referenced in doas ruler?z'Correct user is referenced in doas ruleTz.Incorrect user '%s' is referenced in doas ruleFz/doas rule does not appear to reference any user)rertrÚsearchrô)rNr,ÚruleZ rule_patternZ valid_matchr7r7r8Úis_doas_rule_validis(ÿ ÿ  ÿ þ zDistro.is_doas_rule_validc Cs<|s |j}|D],}| ||¡sd||f}t |¡dSqdd|g}|D]}| d|¡qLd |¡}|d7}tj |¡sÞt   ¡|g}zt j |d |¡dd�Wn6t yÚ} zt   td|¡| ‚WYd} ~ n d} ~ 00nZ|t  |¡v�r8zt  ||¡Wn8t �y6} zt   td |¡| ‚WYd} ~ n d} ~ 00dS) NzHInvalid doas rule %r for user '%s', not writing any doas rules for user!rÇz# cloud-init User rules for %sú%sr2é rËzFailed to write doas file %sz Failed to append to doas file %s)Údoas_fnr7rerfr{r‰r‡rˆrÄrrÏrÑrŒr½rÎÚ append_file) rNr,ÚrulesZ doas_filer6rÚlinesÚcontentrÔr¦r7r7r8r‰s< ÿÿ     ÿzDistro.write_doas_rulesú /etc/sudoersc Csvd}d}d}tj |¡r(t |¡}d}ntj |¡r>t |¡}d}| ¡D]N}| ¡}t d|¡}|shqJ|  d¡ ¡} | s|qJtj  | ¡} | |krJd}qšqJ|�sfzŒ|sîddtj dd �d |dg} |rÐt   d |¡|d  | ¡7}t ||d ¡n.dtj dd �d |dg} d  | ¡}t ||¡t  d||¡Wn8t�yd} zt t d|¡| ‚WYd} ~ n d} ~ 00t |d¡dS)NrÇFz/usr/etc/sudoersTz^[#|@]includedir\s+(.*)$r?z?# See sudoers(5) for more information on "#include" directives:rÈrÉz#includedir %szUsing content from '%s'r2r9zAdded '#includedir %s' to %szFailed to write %siè)r‡rˆrÄrrÎÚ splitlinesrçrr5rôÚabspathrÏrerwr‰rÑr;rtrŒr½Z ensure_dir) rNrˆZ sudo_baseZsudoers_contentsZ base_existsZsystem_sudo_baseZ found_includeÚlineZ include_matchZ included_dirr=r¦r7r7r8Úensure_sudo_dir­s\        ú  ü  zDistro.ensure_sudo_dirc Csf|s |j}dd|g}t|ttfƒrB|D]}| d||f¡q(n4t|tƒr`| d||f¡nd}t|t |¡ƒ‚d  |¡}|d7}|  t j   |¡¡t j  |¡�st ¡|g}zt |d  |¡d¡Wn8t�y} zt td|¡| ‚WYd} ~ n d} ~ 00nZ|t |¡v�rbzt ||¡Wn8t�y`} zt td|¡| ‚WYd} ~ n d} ~ 00dS) NrÇz# User rules for %sz%s %sz1Can not create sudoers rule addition with type %rr2r9zFailed to write sudoers file %sz#Failed to append to sudoers file %s)Ú ci_sudoers_fnrWrYrZr{rXÚ TypeErrorrZobj_namer‰rCr‡rˆÚdirnamerÄrrÏrÑrŒr½rerÎr;) rNr,r<Z sudo_filer=r6rr>rÔr¦r7r7r8rãs@þ  þÿzDistro.write_sudo_rulescCsÌd|g}t ¡r| d¡|s"g}t |¡r:t d|¡n|rd|›d�nd}tjdd|d|dd |¡gfi|¤ŽS) a` Perform a command as the requested user. Behaves like subp() Note: We pass `PATH` to the user env by using `env`. This could be probably simplified after bionic EOL by using `su --whitelist-environment=PATH ...`, more info on: https://lore.kernel.org/all/20180815110445.4qefy5zx5gfgbqly@ws.net.home/T/ zcd z && rÇZsur2z-czenv PATH=$PATH ú )rr‰)rNrŸr,raróZ directoryr7r7r8Údo_as‚s ûÿøz Distro.do_as)rˆÚ lease_fileÚpid_fileÚ interfaceÚ config_filerRc Cs*|ddd|d|ddg |r"d||gn|gS)Nz-1z-vz-lfz-pfz-sfz /bin/truez-cfr7)rˆrdrerfrgr7r7r8Úbuild_dhclient_cmd—s ÷ özDistro.build_dhclient_cmdcCs.|jdur(t ¡|_|js(t d|j¡|jS)zADetermine the network interface used during local network config.Nz0Did not find a fallback interface on distro: %s.)rLrZfind_fallback_nicrer|rCr²r7r7r8Úfallback_interface«s  þzDistro.fallback_interfacecCs ||_dSr„)rL)rNr“r7r7r8ri·s)ÚpidrRcCsVt |d¡}|durRttƒ�t|ƒWdƒS1s:0Yt d||¡dS)ú=Return the parent pid of a process by parsing /proc/$pid/statr§Nz&/proc/%s/stat has an invalid ppid [%s]©r9Ú_get_proc_stat_by_indexrr\rJrer|©rjÚmatchr7r7r8Ú get_proc_ppid»s   &zDistro.get_proc_ppidcCsVt |d¡}|durRttƒ�t|ƒWdƒS1s:0Yt d||¡dS)rkéNz&/proc/%s/stat has an invalid pgid [%s]rlrnr7r7r8Ú get_proc_pgidÅs   &zDistro.get_proc_pgid)rjÚfieldrRc Cs¤zJtjd|dd� ¡}t d|¡}|sror¦r7r7r8rmÏs0ÿ ÿÿ" û zDistro._get_proc_stat_by_index)ÚdevicerRcCsLd}t d¡rd|g}n&t d¡r.dd|g}ntjdddd�‚t |¡dS)NZejectz/lib/udev/cdrom_idz --eject-mediaZeject_media_cmdzeject command not foundz.neither eject nor /lib/udev/cdrom_id are found)r'Ú descriptionÚreason)rrr¼)rvr'r7r7r8Ú eject_mediaðs    ýzDistro.eject_media)ÚblockdevrRcCs,tj |¡}| d¡r(t d||¡|SdS)aReturns underlying block device for a mapped device. If it is mapped, blockdev will usually take the form of /dev/mapper/some_name If blockdev is a symlink pointing to a /dev/dm-* device, return the device pointed to. Otherwise, return None. z/dev/dm-z$%s is a mapped device pointing to %sN)r‡rˆÚrealpathÚ startswithrert)rzr{r7r7r8Úget_mapped_deviceÿs  ÿzDistro.get_mapped_device)ÚdevpathrRc Cs¸tj |¡}tj |¡}d|}tj |¡sr#Z_ci_pkl_versionr¾Zresolve_conf_fnr@r rArPrJrUr^Ú PackageListr rrr rirvÚpropertyr!Z DhcpClientr}r ZNetworkActivatorr€r%r‚r†r�r’r”r›Ú staticmethodrœÚabcÚabstractmethodr¡r¤rªr¬r°r±Úboolr³rµr¶r·r¸rºr–r»r˜r•rÂrÆrÕrØrÙr÷rþr rrrr-rrYr.r7rrCrrðÚ classmethodrMrPrZr^r`rcrhriÚsetterrprrrmryr}rZrƒr„r7r7r7r8r9…sø    þ 5;               A+ y"4,   $ 6 )   ÿÿ$ú     #r9)Ú metaclass©ÚurlÚtransformationscCsŠztj |¡}Wnty$YdS0|j}|dur8dS|D]}||ƒ}|dur<|Sq<|}|jdurvd ||j¡}tj |j|d�¡S)aŸ Apply transformations to a URL's hostname, return transformed URL. This is a separate function because unwrapping and rewrapping only the hostname portion of a URL is complex. :param url: The URL to operate on. :param transformations: A list of ``(str) -> Optional[str]`` functions, which will be applied in order to the hostname portion of the URL. If any function (regardless of ordering) returns None, ``url`` will be returned without any modification. :return: A string whose value is ``url`` with the hostname ``transformations`` applied, or ``None`` if ``url`` is unparsable. Nz{}:{})Únetloc) ÚurllibÚparseÚurlsplitr\r™ÚportrÀÚ urlunsplitÚ_replace)r�r‘ÚpartsZ new_hostnameZtransformationZ new_netlocr7r7r8Ú&_apply_hostname_transformations_to_urlCs   rš)r�cs2td‰dd„dd„‡fdd„dd„g}t||ƒS)aH Given a mirror URL, replace or remove any invalid URI characters. This performs the following actions on the URL's hostname: * Checks if it is an IP address, returning the URL immediately if it is * Converts it to its IDN form (see below for details) * Replaces any non-Letters/Digits/Hyphen (LDH) characters in it with hyphens * Removes any leading/trailing hyphens from each domain name label Before we replace any invalid domain name characters, we first need to ensure that any valid non-ASCII characters in the hostname will not be replaced, by ensuring the hostname is in its Internationalized domain name (IDN) representation (see RFC 5890). This conversion has to be applied to the whole hostname (rather than just the substitution variables), because the Punycode algorithm used by IDNA transcodes each part of the hostname as a whole string (rather than encoding individual characters). It cannot be applied to the whole URL, because (a) the Punycode algorithm expects to operate on domain names so doesn't output a valid URL, and (b) non-ASCII characters in non-hostname parts of the URL aren't encoded via Punycode. To put this in RFC 5890's terminology: before we remove or replace any characters from our domain name (which we do to ensure that each label is a valid LDH Label), we first ensure each label is in its A-label form. (Note that Python's builtin idna encoding is actually IDNA2003, not IDNA2008. This changes the specifics of how some characters are encoded to ASCII, but doesn't affect the logic here.) :param url: The URL to operate on. :return: A sanitized version of the URL, which will have been IDNA encoded if necessary, or ``None`` if the generated string is not a parseable URL. Ú.cSst |¡rdS|Sr„)rZ is_ip_address©r™r7r7r8Ú˜roz&_sanitize_mirror_url..cSs| d¡ d¡S)NZidnaÚascii)ÚencodeÚdecoderœr7r7r8r�›rocsd ‡fdd„|Dƒ¡S)NrÇc3s|]}|ˆvr|ndVqdS©r2Nr7r!©Zacceptable_charsr7r8r�sú9_sanitize_mirror_url....r3rœr¢r7r8r��sÿcSsd dd„| d¡Dƒ¡S)Nr›css|]}| d¡VqdSr¡ræ)rlÚpartr7r7r8r¡sr£)r‰rírœr7r7r8r�¡s ÿ)ÚLDH_ASCII_CHARSršr�r7r¢r8Ú_sanitize_mirror_urlns& ôr¦c Cs&|si}i}|rb|jrb|j|d<t |j¡rb|jdd…}trLd||d<n|jdkrbd||d<|rv|jrv|j|d<i}| di¡ ¡D]\}}|||<qŠ| d i¡ ¡D]h\}}g} |D]B} z | |}WntyâYq¼Yn0t |ƒ}|dur¼|   |¡q¼|| ƒ} | r¬| ||<q¬t   d |¡|S) NÚavailability_zoneréÿÿÿÿr8Ú ec2_regionZec2ÚregionZfailsafer5zfiltered distro mirror info: %s) r§Ú _EC2_AZ_RErorZ platform_typerªrprbrdr¦r{rert) r­r®Z mirror_filterÚsubstr©ÚresultsrCZmirrorZ searchlistZmirrorsZtmplÚfoundr7r7r8r¯©s>              r¯cCs8d}|D]*}| d¡}||vr&|Sd|vr|}q|S)NÚarchesr‘)rp)r«r)r‘Úitemr¯r7r7r8r¬Üs r¬)rCrRcCsHt |dtgdg¡\}}|s,td||fƒ‚t |d¡}t|dƒ}|S)NrÇr9z1No distribution found for distro %s (searched %s)r)rÚ find_moduler4Ú ImportErrorÚ import_moduleÚgetattr)rCZlocsZ looked_locsÚmodrKr7r7r8Úfetchèsÿÿ r¶ú /etc/timezoneú/etc/localtimecCsht |t|ƒ ¡d¡|rd|rdtj |¡}|s sŒ   0 0          Ü'   üÿ I+<ÿ 3  ÿ