3 گa5@sTdZddlZddlZddlmZddlmZddlmZddlmZddlm Z ddlm Z dd lm Z ddl Z dd l mZdd lmZdd lmZdd lmZddlmZddlmZddlmZddlmZddlmZddlmZejeZGdddej ej!ej"dZ#GdddZ$e%ddddZ&e%ddddZ'e%ee%ddd Z(dS)!z*Common code for DNS Authenticator Plugins.N)sleep)Callable)Iterable)List)Mapping)Optional)Type) challenges) achallenges) configuration)errors) interfaces) filesystem)os)ops)util)commoncseZdZdZejeddfdd Zed2e d3e ddd d Z e e jed d d ZeeeejdddZddddZedddZe e je ejdddZe e jddddZejddddZejeeeddddZejeeeddd d!Zeedd"d#d$Zd4eee e egdfdd%d&d'Z!d5eee e"eefe e d(gdfd(d)d*d+Z#e$eed,d-d.Z%e$d6ee e egdfed/d0d1Z&Z'S)7DNSAuthenticatorz!Base class for DNS AuthenticatorsN)confignamereturncstj||d|_dS)NF)super__init___attempt_cleanup)selfrr) __class__ /usr/lib/python3.6/dns_common.pyrszDNSAuthenticator.__init__ .)adddefault_propagation_secondsrcCs|d|tdddS)Nzpropagation-secondszjThe number of seconds to wait for DNS to propagate before asking the ACME server to verify the DNS record.)defaulttypehelp)int)clsrr rrradd_parser_arguments$sz%DNSAuthenticator.add_parser_arguments)failed_achallsrcCs(|jd}dj|j||dkr dnddS)z,See certbot.plugins.common.Plugin.auth_hint.zpropagation-secondszThe Certificate Authority failed to verify the DNS TXT records created by --{name}. Ensure the above domains are hosted by this DNS provider, or try increasing --{name}-propagation-seconds (currently {secs} second{suffix}).s)rZsecssuffix)confformatr)rr'Zdelayrrr auth_hint-s zDNSAuthenticator.auth_hint) unused_domainrcCstjgS)N)r ZDNS01)rr/rrrget_chall_pref7szDNSAuthenticator.get_chall_pref)rcCsdS)Nr)rrrrprepare:szDNSAuthenticator.preparecCs tdS)N)NotImplementedError)rrrr more_info=szDNSAuthenticator.more_info)achallsrcCs|jd|_g}xH|D]@}|j}|j|}|j|j}|j||||j|j|jqWt j d|j dt |j d|S)NTz/Waiting %d seconds for DNS changes to propagatezpropagation-seconds) _setup_credentialsrdomainvalidation_domain_name validation account_key_performappendresponse display_utilZnotifyr,r)rr4Z responsesachallr6r7r8rrrperform@s   zDNSAuthenticator.performcCsB|jr>x6|D].}|j}|j|}|j|j}|j|||q WdS)N)rr6r7r8r9_cleanup)rr4r>r6r7r8rrrcleanupXs    zDNSAuthenticator.cleanupcCs tdS)z@ Establish credentials, prompting if necessary. N)r2)rrrrr5asz#DNSAuthenticator._setup_credentials)r6validation_namer8rcCs tdS)aX Performs a dns-01 challenge by creating a DNS TXT record. :param str domain: The domain being validated. :param str validation_domain_name: The validation record domain name. :param str validation: The validation record content. :raises errors.PluginError: If the challenge cannot be performed N)r2)rr6rBr8rrrr:hs zDNSAuthenticator._performcCs tdS)aX Deletes the DNS TXT record which would have been created by `_perform_achall`. Fails gracefully if no such record exists. :param str domain: The domain being validated. :param str validation_domain_name: The validation record domain name. :param str validation: The validation record content. N)r2)rr6rBr8rrrr@us zDNSAuthenticator._cleanup)keylabelrcCs0|j|}|s,|j|}t|j|j||dS)a Ensure that a configuration value is available. If necessary, prompts the user and stores the result. :param str key: The configuration key. :param str label: The user-friendly label for this piece of information. N)r,_prompt_for_datasetattrrdest)rrCrDconfigured_value new_valuerrr _configures  zDNSAuthenticator._configure)rCrD validatorrcCsB|j|}|s>|j||}t|j|j|tjjtjj|dS)a  Ensure that a configuration value is available for a path. If necessary, prompts the user and stores the result. :param str key: The configuration key. :param str label: The user-friendly label for this piece of information. N) r,_prompt_for_filerFrrGrpathabspath expanduser)rrCrDrKrHrIrrr_configure_files  z DNSAuthenticator._configure_fileCredentialsConfiguration)rCrDrequired_variablesrKrcsVtddfdd }j|||tj|j}rF|jrR||S)a As `_configure_file`, but for a credential configuration file. If necessary, prompts the user and stores the result. Always stores absolute paths to avoid issues during renewal. :param str key: The configuration key. :param str label: The user-friendly label for this piece of information. :param dict required_variables: Map of variable which must be present to error to display. :param callable validator: A method which will be called to validate the `CredentialsConfiguration` resulting from the supplied input after it has been validated to contain the `required_variables`. Should throw a `~certbot.errors.PluginError` to indicate any issue. N)filenamercs*t|j}r|jr&|dS)N)rQrGrequire)rSZapplied_configuration)rRrrKrr __validators   z.__validator)strrPrQr,rGrT)rrCrDrRrK_DNSAuthenticator__validatorZcredentials_configurationr)rRrrKr_configure_credentialss  z'DNSAuthenticator._configure_credentials)rDrcsPtddfdd }tj|djdd\}}|tjkr<|StjdjdS) z Prompt the user for a piece of information. :param str label: The user-friendly label for this piece of information. :returns: The user's response (guaranteed non-empty). :rtype: str N)ircs|stjdjdS)NzPlease enter your {0}.)r PluginErrorr-)rY)rDrrrUsz6DNSAuthenticator._prompt_for_data..__validatorzInput your {0}T)force_interactivez{0} required to proceed.)rVrZvalidated_inputr-r=OKr rZ)rDrWcoder<r)rDrrEs   z!DNSAuthenticator._prompt_for_data)rDrKrcsRtddfdd }tj|djdd\}}|tjkr>|StjdjdS) a Prompt the user for a path. :param str label: The user-friendly label for the file. :param callable validator: A method which will be called to validate the supplied input after it has been validated to be a non-empty path to an existing file. Should throw a `~certbot.errors.PluginError` to indicate any issue. :returns: The user's response (guaranteed to exist). :rtype: str N)rSrcs8|stjdjtjj|}t|r4|dS)Nz&Please enter a valid path to your {0}.)r rZr-rrMrO validate_file)rS)rDrKrrrUs  z6DNSAuthenticator._prompt_for_file..__validatorzInput the path to your {0}T)r[z{0} required to proceed.)rVrZvalidated_directoryr-r=r\r rZ)rDrKrWr]r<r)rDrKrrLs    z!DNSAuthenticator._prompt_for_file)r).N)N)NN)N)(__name__ __module__ __qualname____doc__r ZNamespaceConfigrVr classmethodrr$r&rr ZAnnotatedChallenger.rrr Z Challenger0r1r3ZChallengeResponser?rAabcabstractmethodr5r:r@rJrrPrrX staticmethodrErL __classcell__rr)rrrs8    $$%r) metaclassc@s|eZdZdZddfeeegefddddZeeefddd d Zeed d d Z ee d ddZ eed ddZ dS)rQz>Represents a user-supplied filed which stores API credentials.cCs|S)Nr)xrrrsz!CredentialsConfiguration.N)rSmapperrcCsht|ytj||_WnDtjk r\}z&tjd|ddtjdj |WYdd}~XnX||_ dS)z :param str filename: A path to the configuration file. :param callable mapper: A transformation to apply to configuration key names :raises errors.PluginError: If the file does not exist or is not a valid format. z+Error parsing credentials configuration: %sT)exc_infoz,Error parsing credentials configuration: {0}N) validate_file_permissions configobjZ ConfigObjconfobjZConfigObjErrorloggerdebugr rZr-rk)rrSrkerrrrs"z!CredentialsConfiguration.__init__)rRrcCsg}xZ|D]R}|j|s6|jdj|j|||q |j|s |jdj|j|||q W|rtjdjt|dkr|dnd|jj dj |dS) zEnsures that the supplied set of variables are all present in the file. :param dict required_variables: Map of variable which must be present to error to display. :raises errors.PluginError: If one or more are missing. z)Property "{0}" not found (should be {1}).z'Property "{0}" not set (should be {1}).z9Missing {0} in credentials configuration file {1}: * {2}r(propertyZ propertiesz * N) _hasr;r-rk_getr rZlenrorSjoin)rrRZmessagesvarrrrrTs   z CredentialsConfiguration.require)rxrcCs |j|S)zFind a configuration value for variable `var`, as transformed by `mapper`. :param str var: The variable to get. :returns: The value of the variable. :rtype: str )ru)rrxrrrr,1szCredentialsConfiguration.confcCs|j||jkS)N)rkro)rrxrrrrt;szCredentialsConfiguration._hascCs|jj|j|S)N)rogetrk)rrxrrrru>szCredentialsConfiguration._get) r_r`rarbrVrrrrTr,boolrtrurrrrrQs $ rQ)rSrcCs<tjj|stjdj|tjj|r8tjdj|dS)z&Ensure that the specified file exists.zFile not found: {0}zPath is a directory: {0}N)rrMexistsr rZr-isdir)rSrrrr^Bs  r^cCs"t|tj|rtjd|dS)zHEnsure that the specified file exists and warn about unsafe permissions.z8Unsafe permissions on credentials configuration file: %sN)r^rZhas_world_permissionsrpZwarning)rSrrrrmLs rm)r6rcs&|jdfddtdtDS)aReturn a list of progressively less-specific domain names. One of these will probably be the domain name known to the DNS provider. :Example: >>> base_domain_name_guesses('foo.bar.baz.example.com') ['foo.bar.baz.example.com', 'bar.baz.example.com', 'baz.example.com', 'example.com', 'com'] :param str domain: The domain for which to return guesses. :returns: The a list of less specific domain names. :rtype: list .csg|]}dj|dqS)r}N)rw).0rY) fragmentsrr esz,base_domain_name_guesses..r)splitrangerv)r6r)rrbase_domain_name_guessesUs r))rbrdZloggingZtimerZtypingrrrrrrrnZacmer Zcertbotr r r r Zcertbot.compatrrZcertbot.displayrrr=Zcertbot.pluginsrZ getLoggerr_rpZPluginZ AuthenticatorABCMetarrQrVr^rmrrrrrs6                  j=