├── .dockerignore ├── .gitattributes ├── .gitcookies.enc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── feature_request.yml │ └── new_dns_provider.yml ├── PULL_REQUEST_TEMPLATE │ └── mnp.md └── workflows │ ├── documentation.yml │ ├── go-cross.yml │ ├── pr.yml │ └── release.yml ├── .gitignore ├── .golangci.yml ├── .goreleaser.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── acme ├── api │ ├── account.go │ ├── api.go │ ├── authorization.go │ ├── certificate.go │ ├── certificate_test.go │ ├── challenge.go │ ├── identifier.go │ ├── identifier_test.go │ ├── internal │ │ ├── nonces │ │ │ ├── nonce_manager.go │ │ │ └── nonce_manager_test.go │ │ ├── secure │ │ │ ├── jws.go │ │ │ └── jws_test.go │ │ └── sender │ │ │ ├── sender.go │ │ │ ├── sender_test.go │ │ │ └── useragent.go │ ├── order.go │ ├── order_test.go │ ├── renewal.go │ ├── service.go │ └── service_test.go ├── commons.go └── errors.go ├── buildx.Dockerfile ├── certcrypto ├── crypto.go └── crypto_test.go ├── certificate ├── authorization.go ├── certificates.go ├── certificates_test.go ├── errors.go ├── errors_test.go ├── renewal.go └── renewal_test.go ├── challenge ├── challenges.go ├── dns01 │ ├── cname.go │ ├── cname_test.go │ ├── dns_challenge.go │ ├── dns_challenge_manual.go │ ├── dns_challenge_manual_test.go │ ├── dns_challenge_test.go │ ├── domain.go │ ├── domain_test.go │ ├── fixtures │ │ └── resolv.conf.1 │ ├── fqdn.go │ ├── fqdn_test.go │ ├── nameserver.go │ ├── nameserver_test.go │ ├── nameserver_unix.go │ ├── nameserver_windows.go │ ├── precheck.go │ └── precheck_test.go ├── http01 │ ├── domain_matcher.go │ ├── domain_matcher_test.go │ ├── http_challenge.go │ ├── http_challenge_server.go │ └── http_challenge_test.go ├── provider.go ├── resolver │ ├── errors.go │ ├── prober.go │ ├── prober_mock_test.go │ ├── prober_test.go │ ├── solver_manager.go │ └── solver_manager_test.go └── tlsalpn01 │ ├── tls_alpn_challenge.go │ ├── tls_alpn_challenge_server.go │ └── tls_alpn_challenge_test.go ├── cmd ├── account.go ├── accounts_storage.go ├── certs_storage.go ├── certs_storage_test.go ├── cmd.go ├── cmd_before.go ├── cmd_dnshelp.go ├── cmd_list.go ├── cmd_renew.go ├── cmd_renew_test.go ├── cmd_revoke.go ├── cmd_run.go ├── flags.go ├── hook.go ├── hook_test.go ├── lego │ ├── main.go │ └── zz_gen_version.go ├── setup.go ├── setup_challenges.go ├── testdata │ ├── sleeping_beauty.sh │ └── sleepy.sh └── zz_gen_cmd_dnshelp.go ├── docs ├── .gitignore ├── Makefile ├── archetypes │ └── default.md ├── content │ ├── _index.md │ ├── dns │ │ ├── _index.md │ │ ├── manual.md │ │ ├── zz_gen_acme-dns.md │ │ ├── zz_gen_active24.md │ │ ├── zz_gen_alidns.md │ │ ├── zz_gen_allinkl.md │ │ ├── zz_gen_arvancloud.md │ │ ├── zz_gen_auroradns.md │ │ ├── zz_gen_autodns.md │ │ ├── zz_gen_axelname.md │ │ ├── zz_gen_azure.md │ │ ├── zz_gen_azuredns.md │ │ ├── zz_gen_baiducloud.md │ │ ├── zz_gen_bindman.md │ │ ├── zz_gen_bluecat.md │ │ ├── zz_gen_bookmyname.md │ │ ├── zz_gen_brandit.md │ │ ├── zz_gen_bunny.md │ │ ├── zz_gen_checkdomain.md │ │ ├── zz_gen_civo.md │ │ ├── zz_gen_clouddns.md │ │ ├── zz_gen_cloudflare.md │ │ ├── zz_gen_cloudns.md │ │ ├── zz_gen_cloudru.md │ │ ├── zz_gen_cloudxns.md │ │ ├── zz_gen_conoha.md │ │ ├── zz_gen_conohav3.md │ │ ├── zz_gen_constellix.md │ │ ├── zz_gen_corenetworks.md │ │ ├── zz_gen_cpanel.md │ │ ├── zz_gen_derak.md │ │ ├── zz_gen_desec.md │ │ ├── zz_gen_designate.md │ │ ├── zz_gen_digitalocean.md │ │ ├── zz_gen_directadmin.md │ │ ├── zz_gen_dnshomede.md │ │ ├── zz_gen_dnsimple.md │ │ ├── zz_gen_dnsmadeeasy.md │ │ ├── zz_gen_dnspod.md │ │ ├── zz_gen_dode.md │ │ ├── zz_gen_domeneshop.md │ │ ├── zz_gen_dreamhost.md │ │ ├── zz_gen_duckdns.md │ │ ├── zz_gen_dyn.md │ │ ├── zz_gen_dynu.md │ │ ├── zz_gen_easydns.md │ │ ├── zz_gen_edgedns.md │ │ ├── zz_gen_efficientip.md │ │ ├── zz_gen_epik.md │ │ ├── zz_gen_exec.md │ │ ├── zz_gen_exoscale.md │ │ ├── zz_gen_f5xc.md │ │ ├── zz_gen_freemyip.md │ │ ├── zz_gen_gandi.md │ │ ├── zz_gen_gandiv5.md │ │ ├── zz_gen_gcloud.md │ │ ├── zz_gen_gcore.md │ │ ├── zz_gen_glesys.md │ │ ├── zz_gen_godaddy.md │ │ ├── zz_gen_googledomains.md │ │ ├── zz_gen_hetzner.md │ │ ├── zz_gen_hostingde.md │ │ ├── zz_gen_hosttech.md │ │ ├── zz_gen_httpnet.md │ │ ├── zz_gen_httpreq.md │ │ ├── zz_gen_huaweicloud.md │ │ ├── zz_gen_hurricane.md │ │ ├── zz_gen_hyperone.md │ │ ├── zz_gen_ibmcloud.md │ │ ├── zz_gen_iij.md │ │ ├── zz_gen_iijdpf.md │ │ ├── zz_gen_infoblox.md │ │ ├── zz_gen_infomaniak.md │ │ ├── zz_gen_internetbs.md │ │ ├── zz_gen_inwx.md │ │ ├── zz_gen_ionos.md │ │ ├── zz_gen_ipv64.md │ │ ├── zz_gen_iwantmyname.md │ │ ├── zz_gen_joker.md │ │ ├── zz_gen_liara.md │ │ ├── zz_gen_lightsail.md │ │ ├── zz_gen_limacity.md │ │ ├── zz_gen_linode.md │ │ ├── zz_gen_liquidweb.md │ │ ├── zz_gen_loopia.md │ │ ├── zz_gen_luadns.md │ │ ├── zz_gen_mailinabox.md │ │ ├── zz_gen_manageengine.md │ │ ├── zz_gen_metaname.md │ │ ├── zz_gen_metaregistrar.md │ │ ├── zz_gen_mijnhost.md │ │ ├── zz_gen_mittwald.md │ │ ├── zz_gen_myaddr.md │ │ ├── zz_gen_mydnsjp.md │ │ ├── zz_gen_mythicbeasts.md │ │ ├── zz_gen_namecheap.md │ │ ├── zz_gen_namedotcom.md │ │ ├── zz_gen_namesilo.md │ │ ├── zz_gen_nearlyfreespeech.md │ │ ├── zz_gen_netcup.md │ │ ├── zz_gen_netlify.md │ │ ├── zz_gen_nicmanager.md │ │ ├── zz_gen_nicru.md │ │ ├── zz_gen_nifcloud.md │ │ ├── zz_gen_njalla.md │ │ ├── zz_gen_nodion.md │ │ ├── zz_gen_ns1.md │ │ ├── zz_gen_oraclecloud.md │ │ ├── zz_gen_otc.md │ │ ├── zz_gen_ovh.md │ │ ├── zz_gen_pdns.md │ │ ├── zz_gen_plesk.md │ │ ├── zz_gen_porkbun.md │ │ ├── zz_gen_rackspace.md │ │ ├── zz_gen_rainyun.md │ │ ├── zz_gen_rcodezero.md │ │ ├── zz_gen_regfish.md │ │ ├── zz_gen_regru.md │ │ ├── zz_gen_rfc2136.md │ │ ├── zz_gen_rimuhosting.md │ │ ├── zz_gen_route53.md │ │ ├── zz_gen_safedns.md │ │ ├── zz_gen_sakuracloud.md │ │ ├── zz_gen_scaleway.md │ │ ├── zz_gen_selectel.md │ │ ├── zz_gen_selectelv2.md │ │ ├── zz_gen_selfhostde.md │ │ ├── zz_gen_servercow.md │ │ ├── zz_gen_shellrent.md │ │ ├── zz_gen_simply.md │ │ ├── zz_gen_sonic.md │ │ ├── zz_gen_spaceship.md │ │ ├── zz_gen_stackpath.md │ │ ├── zz_gen_technitium.md │ │ ├── zz_gen_tencentcloud.md │ │ ├── zz_gen_timewebcloud.md │ │ ├── zz_gen_transip.md │ │ ├── zz_gen_ultradns.md │ │ ├── zz_gen_variomedia.md │ │ ├── zz_gen_vegadns.md │ │ ├── zz_gen_vercel.md │ │ ├── zz_gen_versio.md │ │ ├── zz_gen_vinyldns.md │ │ ├── zz_gen_vkcloud.md │ │ ├── zz_gen_volcengine.md │ │ ├── zz_gen_vscale.md │ │ ├── zz_gen_vultr.md │ │ ├── zz_gen_webnames.md │ │ ├── zz_gen_websupport.md │ │ ├── zz_gen_wedos.md │ │ ├── zz_gen_westcn.md │ │ ├── zz_gen_yandex.md │ │ ├── zz_gen_yandex360.md │ │ ├── zz_gen_yandexcloud.md │ │ ├── zz_gen_zoneee.md │ │ └── zz_gen_zonomi.md │ ├── installation │ │ └── _index.md │ └── usage │ │ ├── _index.md │ │ ├── cli │ │ ├── General-Instructions.md │ │ ├── Obtain-a-Certificate.md │ │ ├── Options.md │ │ ├── Renew-a-Certificate.md │ │ ├── _index.md │ │ └── examples.md │ │ └── library │ │ ├── Writing-a-Challenge-Solver.md │ │ └── _index.md ├── data │ └── zz_cli_help.toml ├── go.mod ├── go.sum ├── hugo.toml ├── layouts │ ├── partials │ │ └── logo.html │ └── shortcodes │ │ ├── clihelp.html │ │ └── tableofdnsproviders.html └── static │ ├── css │ └── theme-custom.css │ └── images │ ├── favicon.png │ ├── favicon.svg │ ├── lego-logo-white.min.svg │ └── lego-logo.min.svg ├── e2e ├── challenges_test.go ├── dnschallenge │ └── dns_challenges_test.go ├── fixtures │ ├── certs │ │ ├── README.md │ │ ├── localhost │ │ │ ├── README.md │ │ │ ├── cert.pem │ │ │ └── key.pem │ │ ├── pebble.minica.key.pem │ │ └── pebble.minica.pem │ ├── csr.cert │ ├── csr.raw │ ├── pebble-config-dns.json │ ├── pebble-config.json │ └── update-dns.sh ├── loader │ └── loader.go └── readme.md ├── go.mod ├── go.sum ├── internal ├── clihelp │ └── generator.go ├── dns │ ├── descriptors │ │ └── descriptors.go │ ├── docs │ │ ├── generator.go │ │ └── templates │ │ │ ├── dns.go.tmpl │ │ │ ├── dns.md.tmpl │ │ │ └── readme.md.tmpl │ └── providers │ │ ├── dns_providers.go.tmpl │ │ └── generator.go └── releaser │ ├── generator.go │ ├── releaser.go │ └── templates │ ├── dns.go.tmpl │ ├── sender.go.tmpl │ └── version.go.tmpl ├── lego ├── client.go ├── client_config.go └── client_test.go ├── log └── logger.go ├── platform ├── config │ └── env │ │ ├── env.go │ │ └── env_test.go ├── tester │ ├── api.go │ ├── env.go │ └── env_test.go └── wait │ ├── wait.go │ └── wait_test.go ├── providers ├── dns │ ├── acmedns │ │ ├── acmedns.go │ │ ├── acmedns.toml │ │ ├── acmedns_test.go │ │ ├── internal │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ ├── fetch-all.json │ │ │ │ └── fetch.json │ │ │ ├── http_storage.go │ │ │ ├── http_storage_test.go │ │ │ └── readme.md │ │ └── mock_test.go │ ├── active24 │ │ ├── active24.go │ │ ├── active24.toml │ │ └── active24_test.go │ ├── alidns │ │ ├── alidns.go │ │ ├── alidns.toml │ │ └── alidns_test.go │ ├── allinkl │ │ ├── allinkl.go │ │ ├── allinkl.toml │ │ ├── allinkl_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add_dns_settings.json │ │ │ ├── add_dns_settings.xml │ │ │ ├── auth.xml │ │ │ ├── auth_fault.xml │ │ │ ├── delete_dns_settings.json │ │ │ ├── delete_dns_settings.xml │ │ │ ├── get_dns_settings.json │ │ │ └── get_dns_settings.xml │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ ├── types.go │ │ │ ├── types_api.go │ │ │ └── types_auth.go │ ├── arvancloud │ │ ├── arvancloud.go │ │ ├── arvancloud.toml │ │ ├── arvancloud_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── create_txt_record.json │ │ │ └── get_txt_record.json │ │ │ └── types.go │ ├── auroradns │ │ ├── auroradns.go │ │ ├── auroradns.toml │ │ └── auroradns_test.go │ ├── autodns │ │ ├── autodns.go │ │ ├── autodns.toml │ │ ├── autodns_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add-record.json │ │ │ └── remove-record.json │ │ │ └── types.go │ ├── axelname │ │ ├── axelname.go │ │ ├── axelname.toml │ │ ├── axelname_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── dns_add.json │ │ │ ├── dns_add_error.json │ │ │ ├── dns_delete.json │ │ │ ├── dns_delete_error.json │ │ │ ├── dns_list.json │ │ │ └── dns_list_error.json │ │ │ └── types.go │ ├── azure │ │ ├── azure.go │ │ ├── azure.toml │ │ ├── azure_test.go │ │ ├── private.go │ │ └── public.go │ ├── azuredns │ │ ├── azuredns.go │ │ ├── azuredns.toml │ │ ├── azuredns_test.go │ │ ├── oidc.go │ │ ├── private.go │ │ ├── public.go │ │ ├── servicediscovery.go │ │ └── servicediscovery_test.go │ ├── baiducloud │ │ ├── baiducloud.go │ │ ├── baiducloud.toml │ │ └── baiducloud_test.go │ ├── bindman │ │ ├── bindman.go │ │ ├── bindman.toml │ │ └── bindman_test.go │ ├── bluecat │ │ ├── bluecat.go │ │ ├── bluecat.toml │ │ ├── bluecat_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ ├── bookmyname │ │ ├── bookmyname.go │ │ ├── bookmyname.toml │ │ ├── bookmyname_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add_success.txt │ │ │ ├── error.txt │ │ │ └── remove_success.txt │ │ │ └── types.go │ ├── brandit │ │ ├── brandit.go │ │ ├── brandit.toml │ │ ├── brandit_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add-record.json │ │ │ ├── delete-record.json │ │ │ ├── error.json │ │ │ ├── list-records.json │ │ │ └── status-domain.json │ │ │ └── types.go │ ├── bunny │ │ ├── bunny.go │ │ ├── bunny.toml │ │ └── bunny_test.go │ ├── checkdomain │ │ ├── checkdomain.go │ │ ├── checkdomain.toml │ │ ├── checkdomain_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── civo │ │ ├── civo.go │ │ ├── civo.toml │ │ └── civo_test.go │ ├── clouddns │ │ ├── clouddns.go │ │ ├── clouddns.toml │ │ ├── clouddns_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ ├── cloudflare │ │ ├── cloudflare.go │ │ ├── cloudflare.toml │ │ ├── cloudflare_test.go │ │ └── wrapper.go │ ├── cloudns │ │ ├── cloudns.go │ │ ├── cloudns.toml │ │ ├── cloudns_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── cloudru │ │ ├── cloudru.go │ │ ├── cloudru.toml │ │ ├── cloudru_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── auth-error.json │ │ │ ├── auth.json │ │ │ ├── record.json │ │ │ ├── records.json │ │ │ └── zones.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ ├── cloudxns │ │ ├── cloudxns.go │ │ └── cloudxns.toml │ ├── conoha │ │ ├── conoha.go │ │ ├── conoha.toml │ │ ├── conoha_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── domains-records_GET.json │ │ │ ├── domains-records_POST.json │ │ │ ├── domains_GET.json │ │ │ └── tokens_POST.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ ├── conohav3 │ │ ├── conohav3.go │ │ ├── conohav3.toml │ │ ├── conohav3_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── domains-records_GET.json │ │ │ ├── domains-records_POST.json │ │ │ └── domains_GET.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ ├── constellix │ │ ├── constellix.go │ │ ├── constellix.toml │ │ ├── constellix_test.go │ │ └── internal │ │ │ ├── auth.go │ │ │ ├── auth_test.go │ │ │ ├── client.go │ │ │ ├── domains.go │ │ │ ├── domains_test.go │ │ │ ├── fixtures │ │ │ ├── domains-GetAll.json │ │ │ ├── domains-Search.json │ │ │ ├── records-Create.json │ │ │ ├── records-Get.json │ │ │ ├── records-GetAll.json │ │ │ └── records-Search.json │ │ │ ├── txtrecords.go │ │ │ ├── txtrecords_test.go │ │ │ └── types.go │ ├── corenetworks │ │ ├── corenetworks.go │ │ ├── corenetworks.toml │ │ ├── corenetworks_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── GetZoneDetails.json │ │ │ ├── ListRecords.json │ │ │ ├── ListZone.json │ │ │ └── auth.json │ │ │ ├── identity.go │ │ │ └── types.go │ ├── cpanel │ │ ├── cpanel.go │ │ ├── cpanel.toml │ │ ├── cpanel_test.go │ │ └── internal │ │ │ ├── cpanel │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── update-zone.json │ │ │ │ ├── update-zone_error.json │ │ │ │ ├── zone-info.json │ │ │ │ └── zone-info_error.json │ │ │ └── types.go │ │ │ ├── shared │ │ │ └── types.go │ │ │ └── whm │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── update-zone.json │ │ │ ├── update-zone_error.json │ │ │ ├── zone-info.json │ │ │ └── zone-info_error.json │ │ │ └── types.go │ ├── derak │ │ ├── derak.go │ │ ├── derak.toml │ │ ├── derak_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── error.json │ │ │ ├── record-DELETE.json │ │ │ ├── record-GET.json │ │ │ ├── record-PATCH.json │ │ │ ├── record-PUT.json │ │ │ ├── records-GET.json │ │ │ └── service-cdn-zones.json │ │ │ ├── readme.md │ │ │ └── types.go │ ├── desec │ │ ├── desec.go │ │ ├── desec.toml │ │ └── desec_test.go │ ├── designate │ │ ├── designate.go │ │ ├── designate.toml │ │ └── designate_test.go │ ├── digitalocean │ │ ├── digitalocean.go │ │ ├── digitalocean.toml │ │ ├── digitalocean_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ └── domains-records_POST.json │ │ │ └── types.go │ ├── directadmin │ │ ├── directadmin.go │ │ ├── directadmin.toml │ │ ├── directadmin_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── dns_providers_test.go │ ├── dnshomede │ │ ├── dnshomede.go │ │ ├── dnshomede.toml │ │ ├── dnshomede_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── readme.md │ ├── dnsimple │ │ ├── dnsimple.go │ │ ├── dnsimple.toml │ │ └── dnsimple_test.go │ ├── dnsmadeeasy │ │ ├── dnsmadeeasy.go │ │ ├── dnsmadeeasy.toml │ │ ├── dnsmadeeasy_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── dnspod │ │ ├── dnspod.go │ │ ├── dnspod.toml │ │ └── dnspod_test.go │ ├── dode │ │ ├── dode.go │ │ ├── dode.toml │ │ ├── dode_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ └── success.json │ │ │ └── types.go │ ├── domeneshop │ │ ├── domeneshop.go │ │ ├── domeneshop.toml │ │ ├── domeneshop_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── dreamhost │ │ ├── dreamhost.go │ │ ├── dreamhost.toml │ │ ├── dreamhost_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── duckdns │ │ ├── duckdns.go │ │ ├── duckdns.toml │ │ ├── duckdns_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ └── client_test.go │ ├── dyn │ │ ├── dyn.go │ │ ├── dyn.toml │ │ ├── dyn_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── create-txt-record.json │ │ │ ├── login.json │ │ │ └── publish.json │ │ │ ├── session.go │ │ │ ├── session_test.go │ │ │ └── types.go │ ├── dynu │ │ ├── dynu.go │ │ ├── dynu.toml │ │ ├── dynu_test.go │ │ └── internal │ │ │ ├── auth.go │ │ │ ├── auth_test.go │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add_new_record.json │ │ │ ├── add_new_record_invalid.json │ │ │ ├── delete_record.json │ │ │ ├── delete_record_invalid.json │ │ │ ├── get_records.json │ │ │ ├── get_records_empty.json │ │ │ ├── get_records_invalid.json │ │ │ ├── get_root_domain.json │ │ │ └── get_root_domain_invalid.json │ │ │ └── types.go │ ├── easydns │ │ ├── easydns.go │ │ ├── easydns.toml │ │ ├── easydns_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add-record.json │ │ │ ├── error.json │ │ │ ├── error1.json │ │ │ └── list-zone.json │ │ │ ├── readme.md │ │ │ └── types.go │ ├── edgedns │ │ ├── edgedns.go │ │ ├── edgedns.toml │ │ ├── edgedns_integration_test.go │ │ └── edgedns_test.go │ ├── efficientip │ │ ├── efficientip.go │ │ ├── efficientip.toml │ │ ├── efficientip_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── dns_rr_add.json │ │ │ ├── dns_rr_delete-error.json │ │ │ ├── dns_rr_delete.json │ │ │ ├── dns_rr_info.json │ │ │ └── dns_rr_list.json │ │ │ └── types.go │ ├── epik │ │ ├── epik.go │ │ ├── epik.toml │ │ ├── epik_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── createHostRecord.json │ │ │ ├── error.json │ │ │ ├── getDnsRecord.json │ │ │ └── removeHostRecord.json │ │ │ └── types.go │ ├── exec │ │ ├── exec.go │ │ ├── exec.toml │ │ ├── exec_test.go │ │ └── log_mock_test.go │ ├── exoscale │ │ ├── exoscale.go │ │ ├── exoscale.toml │ │ └── exoscale_test.go │ ├── f5xc │ │ ├── f5xc.go │ │ ├── f5xc.toml │ │ ├── f5xc_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── create.json │ │ │ ├── delete.json │ │ │ ├── error_404.json │ │ │ ├── error_503.json │ │ │ ├── get.json │ │ │ └── replace.json │ │ │ └── types.go │ ├── freemyip │ │ ├── freemyip.go │ │ ├── freemyip.toml │ │ └── freemyip_test.go │ ├── gandi │ │ ├── gandi.go │ │ ├── gandi.toml │ │ ├── gandi_mock_test.go │ │ ├── gandi_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ └── types.go │ ├── gandiv5 │ │ ├── gandiv5.go │ │ ├── gandiv5.toml │ │ ├── gandiv5_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ └── types.go │ ├── gcloud │ │ ├── fixtures │ │ │ └── gce_account_service_file.json │ │ ├── gcloud.toml │ │ ├── googlecloud.go │ │ └── googlecloud_test.go │ ├── gcore │ │ ├── gcore.go │ │ ├── gcore.toml │ │ ├── gcore_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── glesys │ │ ├── glesys.go │ │ ├── glesys.toml │ │ ├── glesys_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── add-record.json │ │ │ └── delete-record.json │ │ │ └── types.go │ ├── godaddy │ │ ├── godaddy.go │ │ ├── godaddy.toml │ │ ├── godaddy_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── error-extended.json │ │ │ ├── errors.json │ │ │ └── getrecords.json │ │ │ └── types.go │ ├── googledomains │ │ ├── googledomains.go │ │ ├── googledomains.toml │ │ └── googledomains_test.go │ ├── hetzner │ │ ├── hetzner.go │ │ ├── hetzner.toml │ │ ├── hetzner_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── create_txt_record.json │ │ │ ├── get_txt_record.json │ │ │ └── get_zone_id.json │ │ │ └── types.go │ ├── hostingde │ │ ├── hostingde.go │ │ ├── hostingde.toml │ │ └── hostingde_test.go │ ├── hosttech │ │ ├── hosttech.go │ │ ├── hosttech.toml │ │ ├── hosttech_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── error-details.json │ │ │ ├── error.json │ │ │ ├── record.json │ │ │ ├── records.json │ │ │ ├── zone.json │ │ │ └── zones.json │ │ │ └── types.go │ ├── httpnet │ │ ├── httpnet.go │ │ ├── httpnet.toml │ │ └── httpnet_test.go │ ├── httpreq │ │ ├── httpreq.go │ │ ├── httpreq.toml │ │ └── httpreq_test.go │ ├── huaweicloud │ │ ├── huaweicloud.go │ │ ├── huaweicloud.toml │ │ └── huaweicloud_test.go │ ├── hurricane │ │ ├── hurricane.go │ │ ├── hurricane.toml │ │ ├── hurricane_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ └── client_test.go │ ├── hyperone │ │ ├── hyperone.go │ │ ├── hyperone.toml │ │ ├── hyperone_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ ├── createRecord.json │ │ │ ├── createRecordset.json │ │ │ ├── invalidPassport.json │ │ │ ├── record.json │ │ │ ├── recordset.json │ │ │ ├── validPassport.json │ │ │ └── zones.json │ │ │ ├── passport.go │ │ │ ├── passport_test.go │ │ │ ├── token.go │ │ │ ├── token_test.go │ │ │ └── types.go │ ├── ibmcloud │ │ ├── ibmcloud.go │ │ ├── ibmcloud.toml │ │ ├── ibmcloud_test.go │ │ └── internal │ │ │ └── wrapper.go │ ├── iij │ │ ├── iij.go │ │ ├── iij.toml │ │ └── iij_test.go │ ├── iijdpf │ │ ├── iijdpf.go │ │ ├── iijdpf.toml │ │ ├── iijdpf_test.go │ │ └── wrapper.go │ ├── infoblox │ │ ├── infoblox.go │ │ ├── infoblox.toml │ │ └── infoblox_test.go │ ├── infomaniak │ │ ├── infomaniak.go │ │ ├── infomaniak.toml │ │ ├── infomaniak_test.go │ │ └── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ ├── internal │ │ ├── active24 │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error_403.json │ │ │ │ ├── error_422.json │ │ │ │ ├── error_v1.json │ │ │ │ ├── records.json │ │ │ │ └── services.json │ │ │ └── types.go │ │ ├── errutils │ │ │ └── client.go │ │ ├── hostingde │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── zoneConfigsFind.json │ │ │ │ ├── zoneConfigsFind_error.json │ │ │ │ ├── zoneUpdate.json │ │ │ │ └── zoneUpdate_error.json │ │ │ └── types.go │ │ ├── ptr │ │ │ └── types.go │ │ ├── rimuhosting │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add_record.xml │ │ │ │ ├── add_record_error.xml │ │ │ │ ├── add_record_same_domain.xml │ │ │ │ ├── delete_record.xml │ │ │ │ ├── delete_record_error.xml │ │ │ │ ├── delete_record_nothing.xml │ │ │ │ ├── find_records.xml │ │ │ │ ├── find_records_empty.xml │ │ │ │ └── find_records_pattern.xml │ │ │ └── types.go │ │ ├── selectel │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── domains.json │ │ │ │ ├── error.json │ │ │ │ └── list_records.json │ │ │ └── types.go │ │ └── useragent │ │ │ └── useragent.go │ ├── internetbs │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── Domain_DnsRecord_Add_FAILURE.json │ │ │ │ ├── Domain_DnsRecord_Add_SUCCESS.json │ │ │ │ ├── Domain_DnsRecord_List_FAILURE.json │ │ │ │ ├── Domain_DnsRecord_List_SUCCESS.json │ │ │ │ └── Domain_DnsRecord_Remove_SUCCESS.json │ │ │ └── types.go │ │ ├── internetbs.go │ │ ├── internetbs.toml │ │ └── internetbs_test.go │ ├── inwx │ │ ├── inwx.go │ │ ├── inwx.toml │ │ └── inwx_test.go │ ├── ionos │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── get_records.json │ │ │ │ ├── get_records_error.json │ │ │ │ ├── list_zones.json │ │ │ │ ├── list_zones_error.json │ │ │ │ ├── remove_record_error.json │ │ │ │ └── replace_records_error.json │ │ │ └── types.go │ │ ├── ionos.go │ │ ├── ionos.toml │ │ └── ionos_test.go │ ├── ipv64 │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add_record-error.json │ │ │ │ ├── add_record.json │ │ │ │ ├── del_record-error.json │ │ │ │ ├── del_record.json │ │ │ │ ├── error.json │ │ │ │ └── get_domains.json │ │ │ └── types.go │ │ ├── ipv64.go │ │ ├── ipv64.toml │ │ └── ipv64_test.go │ ├── iwantmyname │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── iwantmyname.go │ │ ├── iwantmyname.toml │ │ └── iwantmyname_test.go │ ├── joker │ │ ├── internal │ │ │ ├── dmapi │ │ │ │ ├── client.go │ │ │ │ ├── client_test.go │ │ │ │ ├── identity.go │ │ │ │ └── identity_test.go │ │ │ └── svc │ │ │ │ ├── client.go │ │ │ │ └── client_test.go │ │ ├── joker.go │ │ ├── joker.toml │ │ ├── joker_test.go │ │ ├── provider_dmapi.go │ │ ├── provider_dmapi_test.go │ │ ├── provider_svc.go │ │ └── provider_svc_test.go │ ├── liara │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── RecordResponse.json │ │ │ │ ├── RecordsResponse.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── liara.go │ │ ├── liara.toml │ │ └── liara_test.go │ ├── lightsail │ │ ├── lightsail.go │ │ ├── lightsail.toml │ │ ├── lightsail_integration_test.go │ │ ├── lightsail_test.go │ │ └── mock_server_test.go │ ├── limacity │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ ├── get-domains.json │ │ │ │ ├── get-records.json │ │ │ │ └── ok.json │ │ │ └── types.go │ │ ├── limacity.go │ │ ├── limacity.toml │ │ └── limacity_test.go │ ├── linode │ │ ├── linode.go │ │ ├── linode.toml │ │ └── linode_test.go │ ├── liquidweb │ │ ├── liquidweb.go │ │ ├── liquidweb.toml │ │ ├── liquidweb_test.go │ │ └── servermock_test.go │ ├── loopia │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── mock_test.go │ │ │ └── types.go │ │ ├── loopia.go │ │ ├── loopia.toml │ │ ├── loopia_mock_test.go │ │ └── loopia_test.go │ ├── luadns │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── create_record.json │ │ │ │ ├── delete_record.json │ │ │ │ └── list_zones.json │ │ │ └── types.go │ │ ├── luadns.go │ │ ├── luadns.toml │ │ └── luadns_test.go │ ├── mailinabox │ │ ├── mailinabox.go │ │ ├── mailinabox.toml │ │ └── mailinabox_test.go │ ├── manageengine │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ ├── error_bad_request.json │ │ │ │ ├── zone_domains_all.json │ │ │ │ ├── zone_record_create.json │ │ │ │ ├── zone_record_delete.json │ │ │ │ ├── zone_record_update.json │ │ │ │ └── zone_records_all.json │ │ │ ├── identity.go │ │ │ └── types.go │ │ ├── manageengine.go │ │ ├── manageengine.toml │ │ └── manageengine_test.go │ ├── metaname │ │ ├── metaname.go │ │ ├── metaname.toml │ │ └── metaname_test.go │ ├── metaregistrar │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error-response.json │ │ │ │ ├── error.json │ │ │ │ └── update-dns-zone.json │ │ │ └── types.go │ │ ├── metaregistrar.go │ │ ├── metaregistrar.toml │ │ └── metaregistrar_test.go │ ├── mijnhost │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ ├── get-dns-records.json │ │ │ │ ├── list-domains.json │ │ │ │ └── update-dns-records.json │ │ │ └── types.go │ │ ├── mijnhost.go │ │ ├── mijnhost.toml │ │ └── mijnhost_test.go │ ├── mittwald │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── dns-create-dns-zone.json │ │ │ │ ├── dns-get-dns-zone.json │ │ │ │ ├── dns-list-dns-zones.json │ │ │ │ ├── domain-list-domains.json │ │ │ │ ├── error-client.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── mittwald.go │ │ ├── mittwald.toml │ │ └── mittwald_test.go │ ├── myaddr │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ └── error.txt │ │ │ └── types.go │ │ ├── myaddr.go │ │ ├── myaddr.toml │ │ └── myaddr_test.go │ ├── mydnsjp │ │ ├── internal │ │ │ ├── client.go │ │ │ └── client_test.go │ │ ├── mydnsjp.go │ │ ├── mydnsjp.toml │ │ └── mydnsjp_test.go │ ├── mythicbeasts │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── delete-zoneszonerecords.json │ │ │ │ └── post-zoneszonerecords.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ │ ├── mythicbeasts.go │ │ ├── mythicbeasts.toml │ │ └── mythicbeasts_test.go │ ├── namecheap │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── getHosts.xml │ │ │ │ ├── getHosts_errorBadAPIKey1.xml │ │ │ │ ├── getHosts_success1.xml │ │ │ │ ├── getHosts_success2.xml │ │ │ │ ├── setHosts.xml │ │ │ │ ├── setHosts_errorBadAPIKey1.xml │ │ │ │ ├── setHosts_success1.xml │ │ │ │ └── setHosts_success2.xml │ │ │ ├── ip.go │ │ │ └── types.go │ │ ├── namecheap.go │ │ ├── namecheap.toml │ │ └── namecheap_test.go │ ├── namedotcom │ │ ├── namedotcom.go │ │ ├── namedotcom.toml │ │ └── namedotcom_test.go │ ├── namesilo │ │ ├── namesilo.go │ │ ├── namesilo.toml │ │ └── namesilo_test.go │ ├── nearlyfreespeech │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── nearlyfreespeech.go │ │ ├── nearlyfreespeech.toml │ │ └── nearlyfreespeech_test.go │ ├── netcup │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── session.go │ │ │ ├── session_test.go │ │ │ └── types.go │ │ ├── netcup.go │ │ ├── netcup.toml │ │ └── netcup_test.go │ ├── netlify │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── create_record.json │ │ │ │ └── get_records.json │ │ │ └── types.go │ │ ├── netlify.go │ │ ├── netlify.toml │ │ └── netlify_test.go │ ├── nicmanager │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ └── zone.json │ │ │ └── types.go │ │ ├── nicmanager.go │ │ ├── nicmanager.toml │ │ └── nicmanager_test.go │ ├── nicru │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── commit_POST.xml │ │ │ │ ├── errors.xml │ │ │ │ ├── record_DELETE.xml │ │ │ │ ├── records_GET.xml │ │ │ │ ├── records_PUT.xml │ │ │ │ ├── services_GET.xml │ │ │ │ ├── zones_GET.xml │ │ │ │ └── zones_all_GET.xml │ │ │ ├── identity.go │ │ │ └── types.go │ │ ├── nicru.go │ │ ├── nicru.toml │ │ └── nicru_test.go │ ├── nifcloud │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── nifcloud.go │ │ ├── nifcloud.toml │ │ └── nifcloud_test.go │ ├── njalla │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── njalla.go │ │ ├── njalla.toml │ │ └── njalla_test.go │ ├── nodion │ │ ├── nodion.go │ │ ├── nodion.toml │ │ └── nodion_test.go │ ├── ns1 │ │ ├── ns1.go │ │ ├── ns1.toml │ │ └── ns1_test.go │ ├── oraclecloud │ │ ├── configprovider.go │ │ ├── oraclecloud.go │ │ ├── oraclecloud.toml │ │ └── oraclecloud_test.go │ ├── otc │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── fixtures │ │ │ │ ├── zones-recordsets_DELETE.json │ │ │ │ ├── zones-recordsets_GET.json │ │ │ │ ├── zones-recordsets_GET_empty.json │ │ │ │ ├── zones-recordsets_POST.json │ │ │ │ ├── zones_GET.json │ │ │ │ └── zones_GET_empty.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ ├── mock.go │ │ │ └── types.go │ │ ├── otc.go │ │ ├── otc.toml │ │ └── otc_test.go │ ├── ovh │ │ ├── ovh.go │ │ ├── ovh.toml │ │ └── ovh_test.go │ ├── pdns │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ ├── versions.json │ │ │ │ └── zone.json │ │ │ └── types.go │ │ ├── pdns.go │ │ ├── pdns.toml │ │ └── pdns_test.go │ ├── plesk │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add-record-error.xml │ │ │ │ ├── add-record.xml │ │ │ │ ├── delete-record-error.xml │ │ │ │ ├── delete-record.xml │ │ │ │ ├── get-site-error.xml │ │ │ │ ├── get-site.xml │ │ │ │ └── global-error.xml │ │ │ └── types.go │ │ ├── plesk.go │ │ ├── plesk.toml │ │ └── plesk_test.go │ ├── porkbun │ │ ├── porkbun.go │ │ ├── porkbun.toml │ │ └── porkbun_test.go │ ├── rackspace │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add-records.json │ │ │ │ ├── delete-records_error.json │ │ │ │ ├── list-domains-by-name.json │ │ │ │ ├── search-records.json │ │ │ │ └── tokens.json │ │ │ ├── identity.go │ │ │ ├── identity_test.go │ │ │ └── types.go │ │ ├── rackspace.go │ │ ├── rackspace.toml │ │ ├── rackspace_mock_test.go │ │ └── rackspace_test.go │ ├── rainyun │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── domains.json │ │ │ │ ├── error.json │ │ │ │ └── records.json │ │ │ └── types.go │ │ ├── rainyun.go │ │ ├── rainyun.toml │ │ └── rainyun_test.go │ ├── rcodezero │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ └── rrsets-response.json │ │ │ └── types.go │ │ ├── rcodezero.go │ │ ├── rcodezero.toml │ │ └── rcodezero_test.go │ ├── regfish │ │ ├── regfish.go │ │ ├── regfish.toml │ │ └── regfish_test.go │ ├── regru │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── regru.go │ │ ├── regru.toml │ │ └── regru_test.go │ ├── rfc2136 │ │ ├── internal │ │ │ ├── fixtures │ │ │ │ ├── invalid_field.conf │ │ │ │ ├── invalid_key.conf │ │ │ │ ├── mising_algo.conf │ │ │ │ ├── missing_secret.conf │ │ │ │ ├── sample.conf │ │ │ │ ├── text_after.conf │ │ │ │ └── text_before.conf │ │ │ ├── readme.md │ │ │ ├── tsigkey.go │ │ │ └── tsigkey_test.go │ │ ├── rfc2136.go │ │ ├── rfc2136.toml │ │ └── rfc2136_test.go │ ├── rimuhosting │ │ ├── rimuhosting.go │ │ ├── rimuhosting.toml │ │ └── rimuhosting_test.go │ ├── route53 │ │ ├── fixtures_test.go │ │ ├── mock_test.go │ │ ├── route53.go │ │ ├── route53.toml │ │ ├── route53_integration_test.go │ │ └── route53_test.go │ ├── safedns │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── safedns.go │ │ ├── safedns.toml │ │ └── safedns_test.go │ ├── sakuracloud │ │ ├── sakuracloud.go │ │ ├── sakuracloud.toml │ │ ├── sakuracloud_test.go │ │ ├── wrapper.go │ │ └── wrapper_test.go │ ├── scaleway │ │ ├── scaleway.go │ │ ├── scaleway.toml │ │ └── scaleway_test.go │ ├── selectel │ │ ├── selectel.go │ │ ├── selectel.toml │ │ └── selectel_test.go │ ├── selectelv2 │ │ ├── selectelv2.go │ │ ├── selectelv2.toml │ │ └── selectelv2_test.go │ ├── selfhostde │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── readme.md │ │ ├── mapping.go │ │ ├── mapping_test.go │ │ ├── selfhostde.go │ │ ├── selfhostde.toml │ │ └── selfhostde_test.go │ ├── servercow │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ └── records-01.json │ │ │ ├── types.go │ │ │ └── types_test.go │ │ ├── servercow.go │ │ ├── servercow.toml │ │ └── servercow_test.go │ ├── shellrent │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── dns_record-remove.json │ │ │ │ ├── dns_record-store.json │ │ │ │ ├── domain-details.json │ │ │ │ ├── error.json │ │ │ │ ├── purchase-details.json │ │ │ │ └── purchase.json │ │ │ └── types.go │ │ ├── shellrent.go │ │ ├── shellrent.toml │ │ └── shellrent_test.go │ ├── simply │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add_record.json │ │ │ │ ├── bad_auth_error.json │ │ │ │ ├── bad_zone_error.json │ │ │ │ ├── get_records.json │ │ │ │ ├── invalid_record_id_error.json │ │ │ │ └── success.json │ │ │ └── types.go │ │ ├── simply.go │ │ ├── simply.toml │ │ └── simply_test.go │ ├── sonic │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── sonic.go │ │ ├── sonic.toml │ │ └── sonic_test.go │ ├── spaceship │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ └── get-records.json │ │ │ └── types.go │ │ ├── spaceship.go │ │ ├── spaceship.toml │ │ └── spaceship_test.go │ ├── stackpath │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── identity.go │ │ │ └── types.go │ │ ├── stackpath.go │ │ ├── stackpath.toml │ │ └── stackpath_test.go │ ├── technitium │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add-record.json │ │ │ │ ├── delete-record.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── technitium.go │ │ ├── technitium.toml │ │ └── technitium_test.go │ ├── tencentcloud │ │ ├── tencentcloud.go │ │ ├── tencentcloud.toml │ │ ├── tencentcloud_test.go │ │ └── wrapper.go │ ├── timewebcloud │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── createDomainDNSRecord.json │ │ │ │ ├── error_bad_request.json │ │ │ │ └── error_unauthorized.json │ │ │ ├── readme.md │ │ │ └── types.go │ │ ├── timewebcloud.go │ │ ├── timewebcloud.toml │ │ └── timewebcloud_test.go │ ├── transip │ │ ├── fixtures │ │ │ └── private.key │ │ ├── transip.go │ │ ├── transip.toml │ │ └── transip_test.go │ ├── ultradns │ │ ├── ultradns.go │ │ ├── ultradns.toml │ │ └── ultradns_test.go │ ├── variomedia │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── DELETE_dns-records_done.json │ │ │ │ ├── DELETE_dns-records_pending.json │ │ │ │ ├── GET_dns-records.json │ │ │ │ ├── GET_queue-jobs.json │ │ │ │ ├── POST_dns-records.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── variomedia.go │ │ ├── variomedia.toml │ │ └── variomedia_test.go │ ├── vegadns │ │ ├── vegadns.go │ │ ├── vegadns.toml │ │ ├── vegadns_mock_test.go │ │ └── vegadns_test.go │ ├── vercel │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── vercel.go │ │ ├── vercel.toml │ │ └── vercel_test.go │ ├── versio │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── README.md │ │ │ │ ├── get-domain-error.json │ │ │ │ ├── get-domain.json │ │ │ │ ├── update-domain-error.json │ │ │ │ └── update-domain.json │ │ │ └── types.go │ │ ├── versio.go │ │ ├── versio.toml │ │ ├── versio_mock_test.go │ │ └── versio_test.go │ ├── vinyldns │ │ ├── fixtures │ │ │ ├── recordSetChange-create.json │ │ │ ├── recordSetChange-delete.json │ │ │ ├── recordSetDelete.json │ │ │ ├── recordSetUpdate-create.json │ │ │ ├── recordSetsListAll-empty.json │ │ │ ├── recordSetsListAll.json │ │ │ └── zoneByName.json │ │ ├── mock_test.go │ │ ├── vinyldns.go │ │ ├── vinyldns.toml │ │ ├── vinyldns_test.go │ │ └── wrapper.go │ ├── vkcloud │ │ ├── internal │ │ │ ├── client.go │ │ │ └── types.go │ │ ├── vkcloud.go │ │ ├── vkcloud.toml │ │ └── vkcloud_test.go │ ├── volcengine │ │ ├── volcengine.go │ │ ├── volcengine.toml │ │ └── volcengine_test.go │ ├── vscale │ │ ├── vscale.go │ │ ├── vscale.toml │ │ └── vscale_test.go │ ├── vultr │ │ ├── vultr.go │ │ ├── vultr.toml │ │ └── vultr_test.go │ ├── webnames │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── error.json │ │ │ │ └── ok.json │ │ │ └── types.go │ │ ├── webnames.go │ │ ├── webnames.toml │ │ └── webnames_test.go │ ├── websupport │ │ ├── websupport.go │ │ ├── websupport.toml │ │ └── websupport_test.go │ ├── wedos │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── dns-domain-commit.json │ │ │ │ ├── dns-row-add.json │ │ │ │ ├── dns-row-delete.json │ │ │ │ ├── dns-row-update.json │ │ │ │ └── dns-rows-list.json │ │ │ ├── token.go │ │ │ └── types.go │ │ ├── wedos.go │ │ ├── wedos.toml │ │ └── wedos_test.go │ ├── westcn │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── adddnsrecord.json │ │ │ │ ├── deldnsrecord.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── westcn.go │ │ ├── westcn.toml │ │ └── westcn_test.go │ ├── yandex │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ └── types.go │ │ ├── yandex.go │ │ ├── yandex.toml │ │ └── yandex_test.go │ ├── yandex360 │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── add-record.json │ │ │ │ ├── delete-record.json │ │ │ │ └── error.json │ │ │ └── types.go │ │ ├── yandex360.go │ │ ├── yandex360.toml │ │ └── yandex360_test.go │ ├── yandexcloud │ │ ├── yandexcloud.go │ │ ├── yandexcloud.toml │ │ └── yandexcloud_test.go │ ├── zoneee │ │ ├── internal │ │ │ ├── client.go │ │ │ ├── client_test.go │ │ │ ├── fixtures │ │ │ │ ├── create-txt-record.json │ │ │ │ └── get-txt-records.json │ │ │ └── types.go │ │ ├── zoneee.go │ │ ├── zoneee.toml │ │ └── zoneee_test.go │ ├── zonomi │ │ ├── zonomi.go │ │ ├── zonomi.toml │ │ └── zonomi_test.go │ └── zz_gen_dns_providers.go └── http │ ├── memcached │ ├── README.md │ ├── memcached.go │ └── memcached_test.go │ ├── s3 │ ├── s3.go │ ├── s3.toml │ └── s3_test.go │ └── webroot │ ├── webroot.go │ └── webroot_test.go └── registration ├── registar.go ├── registar_test.go ├── user.go └── user_test.go /.dockerignore: -------------------------------------------------------------------------------- 1 | lego.exe 2 | .lego 3 | .gitcookies 4 | .idea 5 | .vscode/ 6 | dist/ 7 | builds/ 8 | docs/ 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | **/zz_gen_*.* linguist-generated 2 | -------------------------------------------------------------------------------- /.gitcookies.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-acme/lego/476f9ed9100ed25d7a4c37eb6946d7831e3a9e09/.gitcookies.enc -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: ❓ Questions 4 | url: https://github.com/go-acme/lego/discussions 5 | about: If you have a question, or are looking for advice, please post on our Discussions section! 6 | - name: 📖 Documentation 7 | url: https://go-acme.github.io/lego/ 8 | about: Please take a look to our documentation. 9 | -------------------------------------------------------------------------------- /.github/workflows/go-cross.yml: -------------------------------------------------------------------------------- 1 | name: Go Matrix 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | 11 | cross: 12 | name: Go 13 | runs-on: ${{ matrix.os }} 14 | env: 15 | CGO_ENABLED: 0 16 | 17 | strategy: 18 | matrix: 19 | go-version: [ oldstable, stable ] 20 | os: [ubuntu-latest, macos-latest, windows-latest] 21 | 22 | steps: 23 | # https://github.com/marketplace/actions/checkout 24 | - name: Checkout code 25 | uses: actions/checkout@v4 26 | 27 | # https://github.com/marketplace/actions/setup-go-environment 28 | - name: Set up Go ${{ matrix.go-version }} 29 | uses: actions/setup-go@v5 30 | with: 31 | go-version: ${{ matrix.go-version }} 32 | 33 | - name: Test 34 | run: go test -v -cover ./... 35 | 36 | - name: Build 37 | run: go build -v -ldflags "-s -w" -trimpath -o ./dist/lego ./cmd/lego/ 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .lego 2 | .gitcookies 3 | .idea 4 | .vscode/ 5 | dist/ 6 | builds/ 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1-alpine as builder 2 | 3 | RUN apk --no-cache --no-progress add make git 4 | 5 | WORKDIR /go/lego 6 | 7 | ENV GO111MODULE on 8 | 9 | # Download go modules 10 | COPY go.mod . 11 | COPY go.sum . 12 | RUN go mod download 13 | 14 | COPY . . 15 | RUN make build 16 | 17 | FROM alpine:3 18 | RUN apk update \ 19 | && apk add --no-cache ca-certificates tzdata \ 20 | && update-ca-certificates 21 | 22 | COPY --from=builder /go/lego/dist/lego /usr/bin/lego 23 | 24 | ENTRYPOINT [ "/usr/bin/lego" ] 25 | -------------------------------------------------------------------------------- /acme/api/identifier.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "cmp" 5 | "slices" 6 | 7 | "github.com/go-acme/lego/v4/acme" 8 | ) 9 | 10 | // compareIdentifiers compares 2 slices of [acme.Identifier]. 11 | func compareIdentifiers(a, b []acme.Identifier) int { 12 | // Clones slices to avoid modifying original slices. 13 | right := slices.Clone(a) 14 | left := slices.Clone(b) 15 | 16 | slices.SortStableFunc(right, compareIdentifier) 17 | slices.SortStableFunc(left, compareIdentifier) 18 | 19 | return slices.CompareFunc(right, left, compareIdentifier) 20 | } 21 | 22 | func compareIdentifier(right, left acme.Identifier) int { 23 | return cmp.Or( 24 | cmp.Compare(right.Type, left.Type), 25 | cmp.Compare(right.Value, left.Value), 26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /acme/api/internal/sender/useragent.go: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package sender 4 | 5 | const ( 6 | // ourUserAgent is the User-Agent of this underlying library package. 7 | ourUserAgent = "xenolf-acme/4.23.1" 8 | 9 | // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. 10 | // values: detach|release 11 | // NOTE: Update this with each tagged release. 12 | ourUserAgentComment = "detach" 13 | ) 14 | -------------------------------------------------------------------------------- /buildx.Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.4 2 | FROM alpine:3 3 | 4 | RUN apk --no-cache --no-progress add git ca-certificates tzdata \ 5 | && rm -rf /var/cache/apk/* 6 | 7 | COPY lego / 8 | 9 | ENTRYPOINT ["/lego"] 10 | EXPOSE 80 11 | -------------------------------------------------------------------------------- /certificate/errors.go: -------------------------------------------------------------------------------- 1 | package certificate 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | type obtainError struct { 9 | data map[string]error 10 | } 11 | 12 | func newObtainError() *obtainError { 13 | return &obtainError{data: make(map[string]error)} 14 | } 15 | 16 | func (e *obtainError) Add(domain string, err error) { 17 | e.data[domain] = err 18 | } 19 | 20 | func (e *obtainError) Join() error { 21 | if e == nil { 22 | return nil 23 | } 24 | 25 | if len(e.data) == 0 { 26 | return nil 27 | } 28 | 29 | var err error 30 | for d, e := range e.data { 31 | err = errors.Join(err, fmt.Errorf("%s: %w", d, e)) 32 | } 33 | 34 | return fmt.Errorf("error: one or more domains had a problem:\n%w", err) 35 | } 36 | 37 | type domainError struct { 38 | Domain string 39 | Error error 40 | } 41 | -------------------------------------------------------------------------------- /challenge/dns01/cname.go: -------------------------------------------------------------------------------- 1 | package dns01 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/miekg/dns" 7 | ) 8 | 9 | // Update FQDN with CNAME if any. 10 | func updateDomainWithCName(r *dns.Msg, fqdn string) string { 11 | for _, rr := range r.Answer { 12 | if cn, ok := rr.(*dns.CNAME); ok { 13 | if strings.EqualFold(cn.Hdr.Name, fqdn) { 14 | return cn.Target 15 | } 16 | } 17 | } 18 | 19 | return fqdn 20 | } 21 | -------------------------------------------------------------------------------- /challenge/dns01/cname_test.go: -------------------------------------------------------------------------------- 1 | package dns01 2 | 3 | import ( 4 | "strings" 5 | "testing" 6 | 7 | "github.com/miekg/dns" 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func Test_updateDomainWithCName_caseInsensitive(t *testing.T) { 12 | qname := "_acme-challenge.uppercase-test.example.com." 13 | cnameTarget := "_acme-challenge.uppercase-test.cname-target.example.com." 14 | 15 | msg := &dns.Msg{ 16 | MsgHdr: dns.MsgHdr{ 17 | Authoritative: true, 18 | }, 19 | Answer: []dns.RR{ 20 | &dns.CNAME{ 21 | Hdr: dns.RR_Header{ 22 | Name: strings.ToUpper(qname), // CNAME names are case-insensitive 23 | Rrtype: dns.TypeCNAME, 24 | Class: dns.ClassINET, 25 | Ttl: 3600, 26 | }, 27 | Target: cnameTarget, 28 | }, 29 | }, 30 | } 31 | 32 | fqdn := updateDomainWithCName(msg, qname) 33 | 34 | assert.Equal(t, cnameTarget, fqdn) 35 | } 36 | -------------------------------------------------------------------------------- /challenge/dns01/domain.go: -------------------------------------------------------------------------------- 1 | package dns01 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/miekg/dns" 8 | ) 9 | 10 | // ExtractSubDomain extracts the subdomain part from a domain and a zone. 11 | func ExtractSubDomain(domain, zone string) (string, error) { 12 | canonDomain := dns.Fqdn(domain) 13 | canonZone := dns.Fqdn(zone) 14 | 15 | if canonDomain == canonZone { 16 | return "", fmt.Errorf("no subdomain because the domain and the zone are identical: %s", canonDomain) 17 | } 18 | 19 | if !dns.IsSubDomain(canonZone, canonDomain) { 20 | return "", fmt.Errorf("%s is not a subdomain of %s", canonDomain, canonZone) 21 | } 22 | 23 | return strings.TrimSuffix(canonDomain, "."+canonZone), nil 24 | } 25 | -------------------------------------------------------------------------------- /challenge/dns01/fixtures/resolv.conf.1: -------------------------------------------------------------------------------- 1 | domain company.com 2 | nameserver 10.200.3.249 3 | nameserver 10.200.3.250:5353 4 | nameserver 2001:4860:4860::8844 5 | nameserver [10.0.0.1]:5353 6 | -------------------------------------------------------------------------------- /challenge/dns01/fqdn.go: -------------------------------------------------------------------------------- 1 | package dns01 2 | 3 | // ToFqdn converts the name into a fqdn appending a trailing dot. 4 | func ToFqdn(name string) string { 5 | n := len(name) 6 | if n == 0 || name[n-1] == '.' { 7 | return name 8 | } 9 | return name + "." 10 | } 11 | 12 | // UnFqdn converts the fqdn into a name removing the trailing dot. 13 | func UnFqdn(name string) string { 14 | n := len(name) 15 | if n != 0 && name[n-1] == '.' { 16 | return name[:n-1] 17 | } 18 | return name 19 | } 20 | -------------------------------------------------------------------------------- /challenge/dns01/nameserver_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package dns01 4 | 5 | import "time" 6 | 7 | // dnsTimeout is used to override the default DNS timeout of 10 seconds. 8 | var dnsTimeout = 10 * time.Second 9 | -------------------------------------------------------------------------------- /challenge/dns01/nameserver_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package dns01 4 | 5 | import "time" 6 | 7 | // dnsTimeout is used to override the default DNS timeout of 20 seconds. 8 | var dnsTimeout = 20 * time.Second 9 | -------------------------------------------------------------------------------- /challenge/resolver/errors.go: -------------------------------------------------------------------------------- 1 | package resolver 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "sort" 7 | ) 8 | 9 | // obtainError is returned when there are specific errors available per domain. 10 | type obtainError map[string]error 11 | 12 | func (e obtainError) Error() string { 13 | buffer := bytes.NewBufferString("error: one or more domains had a problem:\n") 14 | 15 | var domains []string 16 | for domain := range e { 17 | domains = append(domains, domain) 18 | } 19 | sort.Strings(domains) 20 | 21 | for _, domain := range domains { 22 | _, _ = fmt.Fprintf(buffer, "[%s] %s\n", domain, e[domain]) 23 | } 24 | return buffer.String() 25 | } 26 | -------------------------------------------------------------------------------- /cmd/account.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "crypto" 5 | 6 | "github.com/go-acme/lego/v4/registration" 7 | ) 8 | 9 | // Account represents a users local saved credentials. 10 | type Account struct { 11 | Email string `json:"email"` 12 | Registration *registration.Resource `json:"registration"` 13 | key crypto.PrivateKey 14 | } 15 | 16 | /** Implementation of the registration.User interface **/ 17 | 18 | // GetEmail returns the email address for the account. 19 | func (a *Account) GetEmail() string { 20 | return a.Email 21 | } 22 | 23 | // GetPrivateKey returns the private RSA account key. 24 | func (a *Account) GetPrivateKey() crypto.PrivateKey { 25 | return a.key 26 | } 27 | 28 | // GetRegistration returns the server registration. 29 | func (a *Account) GetRegistration() *registration.Resource { 30 | return a.Registration 31 | } 32 | -------------------------------------------------------------------------------- /cmd/cmd.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import "github.com/urfave/cli/v2" 4 | 5 | // CreateCommands Creates all CLI commands. 6 | func CreateCommands() []*cli.Command { 7 | return []*cli.Command{ 8 | createRun(), 9 | createRevoke(), 10 | createRenew(), 11 | createDNSHelp(), 12 | createList(), 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cmd/cmd_before.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/go-acme/lego/v4/log" 5 | "github.com/urfave/cli/v2" 6 | ) 7 | 8 | func Before(ctx *cli.Context) error { 9 | if ctx.String(flgPath) == "" { 10 | log.Fatalf("Could not determine current working directory. Please pass --%s.", flgPath) 11 | } 12 | 13 | err := createNonExistingFolder(ctx.String(flgPath)) 14 | if err != nil { 15 | log.Fatalf("Could not check/create path: %v", err) 16 | } 17 | 18 | if ctx.String(flgServer) == "" { 19 | log.Fatalf("Could not determine current working server. Please pass --%s.", flgServer) 20 | } 21 | 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /cmd/lego/zz_gen_version.go: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package main 4 | 5 | const defaultVersion = "v4.23.1+dev-detach" 6 | 7 | var version = "" 8 | 9 | func getVersion() string { 10 | if version == "" { 11 | return defaultVersion 12 | } 13 | 14 | return version 15 | } 16 | -------------------------------------------------------------------------------- /cmd/testdata/sleeping_beauty.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | sleep 50 4 | -------------------------------------------------------------------------------- /cmd/testdata/sleepy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | for i in `seq 1 10` 4 | do 5 | echo $i 6 | sleep 0.2 7 | done 8 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | themes/ 2 | public/ 3 | .hugo_build.lock 4 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default clean hugo hugo-build 2 | 3 | default: clean hugo 4 | 5 | clean: 6 | rm -rf public/ 7 | 8 | 9 | hugo-build: clean 10 | hugo --enableGitInfo --source . 11 | 12 | hugo: 13 | hugo server --disableFastRender --enableGitInfo --watch --source . 14 | # hugo server -D 15 | -------------------------------------------------------------------------------- /docs/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /docs/content/usage/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Usage" 3 | date: 2019-03-03T16:39:46+01:00 4 | draft: false 5 | weight: 2 6 | --- 7 | 8 | {{% children style="h2" description="true" %}} 9 | -------------------------------------------------------------------------------- /docs/content/usage/cli/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "CLI" 3 | date: 2019-03-03T16:39:46+01:00 4 | draft: false 5 | --- 6 | 7 | Lego can be use as a CLI. 8 | 9 | 10 | 11 | {{% children style="h2" description="true" %}} 12 | -------------------------------------------------------------------------------- /docs/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-acme/lego/docs 2 | 3 | go 1.20 4 | 5 | require github.com/McShelby/hugo-theme-relearn v0.0.0-20240802145348-259f21f89851 6 | -------------------------------------------------------------------------------- /docs/go.sum: -------------------------------------------------------------------------------- 1 | github.com/McShelby/hugo-theme-relearn v0.0.0-20240802145348-259f21f89851 h1:JpmKIb1bRzuAcgnphwSb35Xz9rk/Alq19uRWVGSwScA= 2 | github.com/McShelby/hugo-theme-relearn v0.0.0-20240802145348-259f21f89851/go.mod h1:mKQQdxZNIlLvAj8X3tMq+RzntIJSr9z7XdzuMomt0IM= 3 | -------------------------------------------------------------------------------- /docs/layouts/partials/logo.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/layouts/shortcodes/clihelp.html: -------------------------------------------------------------------------------- 1 | {{ $tabs := slice }} 2 | 3 | {{ $commands := index $.Site.Data.zz_cli_help "command" }} 4 | {{ range $idx, $tab := $commands }} 5 | {{ $content := (print "```\n" $tab.content "\n```") }} 6 | {{ $tabs = $tabs | append (dict "title" $tab.title "content" ($content | page.RenderString) "icon" "terminal") }} 7 | {{ end }} 8 | 9 | {{ partial "shortcodes/tabs.html" (dict 10 | "page" page 11 | "content" $tabs 12 | ) }} 13 | -------------------------------------------------------------------------------- /docs/layouts/shortcodes/tableofdnsproviders.html: -------------------------------------------------------------------------------- 1 | {{ $_hugo_config := `{ "version": 1 }` }} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{- range .Site.AllPages.ByWeight -}} 13 | {{- if .Params.dnsprovider -}} 14 | {{- $params := .Params.dnsprovider -}} 15 | 16 | 19 | 24 | 27 | 28 | 29 | {{ end }} 30 | {{ end }} 31 | 32 |
Provider nameCLI flag nameRequired lego version
17 | {{ .Title }} 18 | 20 | {{- if $params.url -}} 21 | Website 22 | {{- end -}} 23 | 25 | {{ $params.code }} 26 | {{ $params.since }}
33 | -------------------------------------------------------------------------------- /docs/static/css/theme-custom.css: -------------------------------------------------------------------------------- 1 | #top-bar-sticky-wrapper, 2 | #top-bar, 3 | #body-inner { 4 | max-width: 72em; 5 | margin: 0 auto; 6 | } 7 | -------------------------------------------------------------------------------- /docs/static/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-acme/lego/476f9ed9100ed25d7a4c37eb6946d7831e3a9e09/docs/static/images/favicon.png -------------------------------------------------------------------------------- /e2e/fixtures/certs/localhost/README.md: -------------------------------------------------------------------------------- 1 | # certs/localhost 2 | 3 | This directory contains an end-entity (leaf) certificate (`cert.pem`) and 4 | a private key (`key.pem`) for the Pebble HTTPS server. It includes `127.0.0.1` 5 | as an IP address SAN, and `[localhost, pebble]` as DNS SANs. 6 | -------------------------------------------------------------------------------- /e2e/fixtures/csr.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-acme/lego/476f9ed9100ed25d7a4c37eb6946d7831e3a9e09/e2e/fixtures/csr.raw -------------------------------------------------------------------------------- /e2e/fixtures/pebble-config-dns.json: -------------------------------------------------------------------------------- 1 | { 2 | "pebble": { 3 | "listenAddress": "0.0.0.0:15000", 4 | "certificate": "fixtures/certs/localhost/cert.pem", 5 | "privateKey": "fixtures/certs/localhost/key.pem", 6 | "httpPort": 5004, 7 | "tlsPort": 5003, 8 | "profiles": { 9 | "default": { 10 | "description": "The profile you know and love", 11 | "validityPeriod": 7776000 12 | }, 13 | "shortlived": { 14 | "description": "A short-lived cert profile, without actual enforcement", 15 | "validityPeriod": 518400 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /e2e/fixtures/pebble-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "pebble": { 3 | "listenAddress": "0.0.0.0:14000", 4 | "certificate": "fixtures/certs/localhost/cert.pem", 5 | "privateKey": "fixtures/certs/localhost/key.pem", 6 | "httpPort": 5002, 7 | "tlsPort": 5001, 8 | "profiles": { 9 | "default": { 10 | "description": "The profile you know and love", 11 | "validityPeriod": 7776000 12 | }, 13 | "shortlived": { 14 | "description": "A short-lived cert profile, without actual enforcement", 15 | "validityPeriod": 518400 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /e2e/fixtures/update-dns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Simple DNS challenge exec solver. 3 | # Use challtestsrv https://github.com/letsencrypt/boulder/tree/master/test/challtestsrv 4 | 5 | set -e 6 | 7 | case "$1" in 8 | "present") 9 | echo "Present" 10 | payload="{\"host\":\"$2\", \"value\":\"$3\"}" 11 | echo "payload=${payload}" 12 | curl -s -X POST -d "${payload}" localhost:8055/set-txt 13 | ;; 14 | "cleanup") 15 | echo "cleanup" 16 | payload="{\"host\":\"$2\"}" 17 | echo "payload=${payload}" 18 | curl -s -X POST -d "${payload}" localhost:8055/clear-txt 19 | ;; 20 | *) 21 | echo "OOPS" 22 | ;; 23 | esac 24 | -------------------------------------------------------------------------------- /e2e/readme.md: -------------------------------------------------------------------------------- 1 | # E2E tests 2 | 3 | How to run: 4 | 5 | - Add the following entries to your `/etc/hosts`: 6 | ``` 7 | 127.0.0.1 acme.wtf 8 | 127.0.0.1 lego.wtf 9 | 127.0.0.1 acme.lego.wtf 10 | 127.0.0.1 légô.wtf 11 | 127.0.0.1 xn--lg-bja9b.wtf 12 | ``` 13 | 14 | - Install [Pebble](https://github.com/letsencrypt/pebble): 15 | ```bash 16 | go install github.com/letsencrypt/pebble/v2/cmd/pebble@main 17 | go install github.com/letsencrypt/pebble/v2/cmd/pebble-challtestsrv@main 18 | ``` 19 | 20 | - Launch tests: 21 | ```bash 22 | make e2e 23 | ``` 24 | -------------------------------------------------------------------------------- /internal/dns/docs/templates/readme.md.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{- range . -}} 4 | 5 | {{- range . }} 6 | 7 | {{- end }} 8 | 9 | {{- end -}} 10 |
{{if .Code }}{{ .Name }}{{end}}
11 | 12 | -------------------------------------------------------------------------------- /internal/dns/providers/dns_providers.go.tmpl: -------------------------------------------------------------------------------- 1 | // Code generated by 'make generate-dns'; DO NOT EDIT. 2 | 3 | package dns 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/go-acme/lego/v4/challenge" 9 | "github.com/go-acme/lego/v4/challenge/dns01" 10 | {{- range $provider := .Providers }} 11 | "github.com/go-acme/lego/v4/providers/dns/{{ cleanName $provider.Code }}" 12 | {{- end}} 13 | ) 14 | 15 | // NewDNSChallengeProviderByName Factory for DNS providers. 16 | func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) { 17 | switch name { 18 | case "manual": 19 | return dns01.NewDNSProviderManual() 20 | {{- range $provider := .Providers }} 21 | case "{{ $provider.Code }}"{{range $alias := $provider.Aliases }},"{{ $alias }}"{{end}}: 22 | return {{ cleanName $provider.Code }}.NewDNSProvider() 23 | {{- end}} 24 | default: 25 | return nil, fmt.Errorf("unrecognized DNS provider: %s", name) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /internal/releaser/templates/dns.go.tmpl: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package useragent 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | "runtime" 9 | ) 10 | 11 | const ( 12 | // ourUserAgent is the User-Agent of this underlying library package. 13 | ourUserAgent = "goacme-lego/{{ .version }}" 14 | 15 | // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. 16 | // values: detach|release 17 | // NOTE: Update this with each tagged release. 18 | ourUserAgentComment = "{{ .comment }}" 19 | ) 20 | 21 | // Get builds and returns the User-Agent string. 22 | func Get() string { 23 | return fmt.Sprintf("%s (%s; %s; %s)", ourUserAgent, ourUserAgentComment, runtime.GOOS, runtime.GOARCH) 24 | } 25 | 26 | // SetHeader sets the User-Agent header. 27 | func SetHeader(h http.Header) { 28 | h.Set("User-Agent", Get()) 29 | } 30 | -------------------------------------------------------------------------------- /internal/releaser/templates/sender.go.tmpl: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package sender 4 | 5 | const ( 6 | // ourUserAgent is the User-Agent of this underlying library package. 7 | ourUserAgent = "xenolf-acme/{{ .version }}" 8 | 9 | // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. 10 | // values: detach|release 11 | // NOTE: Update this with each tagged release. 12 | ourUserAgentComment = "{{ .comment }}" 13 | ) 14 | -------------------------------------------------------------------------------- /internal/releaser/templates/version.go.tmpl: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package main 4 | 5 | const defaultVersion = "v{{ .version }}+dev{{ if .comment }}-{{ .comment }}{{end}}" 6 | 7 | var version = "" 8 | 9 | func getVersion() string { 10 | if version == "" { 11 | return defaultVersion 12 | } 13 | 14 | return version 15 | } 16 | -------------------------------------------------------------------------------- /platform/wait/wait.go: -------------------------------------------------------------------------------- 1 | package wait 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/go-acme/lego/v4/log" 8 | ) 9 | 10 | // For polls the given function 'f', once every 'interval', up to 'timeout'. 11 | func For(msg string, timeout, interval time.Duration, f func() (bool, error)) error { 12 | log.Infof("Wait for %s [timeout: %s, interval: %s]", msg, timeout, interval) 13 | 14 | var lastErr error 15 | timeUp := time.After(timeout) 16 | for { 17 | select { 18 | case <-timeUp: 19 | if lastErr == nil { 20 | return fmt.Errorf("%s: time limit exceeded", msg) 21 | } 22 | return fmt.Errorf("%s: time limit exceeded: last error: %w", msg, lastErr) 23 | default: 24 | } 25 | 26 | stop, err := f() 27 | if stop { 28 | return nil 29 | } 30 | if err != nil { 31 | lastErr = err 32 | } 33 | 34 | time.Sleep(interval) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /platform/wait/wait_test.go: -------------------------------------------------------------------------------- 1 | package wait 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func TestForTimeout(t *testing.T) { 9 | c := make(chan error) 10 | go func() { 11 | c <- For("", 3*time.Second, 1*time.Second, func() (bool, error) { 12 | return false, nil 13 | }) 14 | }() 15 | 16 | timeout := time.After(6 * time.Second) 17 | select { 18 | case <-timeout: 19 | t.Fatal("timeout exceeded") 20 | case err := <-c: 21 | if err == nil { 22 | t.Errorf("expected timeout error; got %v", err) 23 | } 24 | t.Logf("%v", err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /providers/dns/acmedns/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "There is an error" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/acmedns/internal/fixtures/fetch-all.json: -------------------------------------------------------------------------------- 1 | { 2 | "a": { 3 | "fulldomain": "foo.example.com", 4 | "subdomain": "foo", 5 | "username": "user", 6 | "password": "secret", 7 | "server_url": "https://example.com" 8 | }, 9 | "b": { 10 | "fulldomain": "bar.example.com", 11 | "subdomain": "bar", 12 | "username": "user", 13 | "password": "secret", 14 | "server_url": "https://example.com" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/acmedns/internal/fixtures/fetch.json: -------------------------------------------------------------------------------- 1 | { 2 | "fulldomain": "foo.example.com", 3 | "subdomain": "foo", 4 | "username": "user", 5 | "password": "secret", 6 | "server_url": "https://example.com" 7 | } 8 | -------------------------------------------------------------------------------- /providers/dns/allinkl/allinkl.toml: -------------------------------------------------------------------------------- 1 | Name = "all-inkl" 2 | Description = '''''' 3 | URL = "https://all-inkl.com" 4 | Code = "allinkl" 5 | Since = "v4.5.0" 6 | 7 | Example = ''' 8 | ALL_INKL_LOGIN=xxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | ALL_INKL_PASSWORD=yyyyyyyyyyyyyyyyyyyyyyyyyy \ 10 | lego --email you@example.com --dns allinkl -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | ALL_INKL_LOGIN = "KAS login" 16 | ALL_INKL_PASSWORD = "KAS password" 17 | [Configuration.Additional] 18 | ALL_INKL_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 19 | ALL_INKL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 20 | ALL_INKL_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://kasapi.kasserver.com/dokumentation/phpdoc/index.html" 24 | Guide = "https://kasapi.kasserver.com/dokumentation/" 25 | -------------------------------------------------------------------------------- /providers/dns/allinkl/internal/fixtures/add_dns_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Request": { 3 | "KasRequestParams": { 4 | "record_aux": 0, 5 | "record_data": "abcdefgh", 6 | "record_name": "lego", 7 | "record_type": "TXT", 8 | "zone_host": "example.org." 9 | }, 10 | "KasRequestTime": 1625014992, 11 | "KasRequestType": true 12 | }, 13 | "Response": { 14 | "KasFloodDelay": 0.5, 15 | "ReturnInfo": "57347444", 16 | "ReturnString": "TRUE" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /providers/dns/allinkl/internal/fixtures/auth.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 593959ca04f0de9689b586c6a647d15d 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/allinkl/internal/fixtures/auth_fault.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SOAP-ENV:Client 6 | kas_login_syntax_incorrect 7 | KasAuth 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /providers/dns/allinkl/internal/fixtures/delete_dns_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Request": { 3 | "KasRequestParams": { 4 | "record_id": "57347444" 5 | }, 6 | "KasRequestTime": 1625016066, 7 | "KasRequestType": true 8 | }, 9 | "Response": { 10 | "KasFloodDelay": 0.5, 11 | "ReturnInfo": true, 12 | "ReturnString": "TRUE" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/arvancloud/arvancloud.toml: -------------------------------------------------------------------------------- 1 | Name = "ArvanCloud" 2 | Description = '''''' 3 | URL = "https://arvancloud.ir" 4 | Code = "arvancloud" 5 | Since = "v3.8.0" 6 | 7 | Example = ''' 8 | ARVANCLOUD_API_KEY="Apikey xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns arvancloud -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | ARVANCLOUD_API_KEY = "API key" 15 | [Configuration.Additional] 16 | ARVANCLOUD_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | ARVANCLOUD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | ARVANCLOUD_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)" 19 | ARVANCLOUD_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://www.arvancloud.ir/docs/api/cdn/4.0" 23 | -------------------------------------------------------------------------------- /providers/dns/arvancloud/internal/fixtures/create_txt_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", 4 | "type": "txt", 5 | "name": "_acme-challenge", 6 | "value": { 7 | "text": "txtxtxt" 8 | }, 9 | "ttl": 120, 10 | "cloud": false, 11 | "upstream_https": "default", 12 | "ip_filter_mode": { 13 | "count": "single", 14 | "order": "none", 15 | "geo_filter": "none" 16 | }, 17 | "can_delete": true, 18 | "health_check_status": false, 19 | "health_check_setting": { 20 | "protocol": "http", 21 | "port": "", 22 | "uri": "" 23 | }, 24 | "created_at": "2020-05-27T23:57:02Z", 25 | "updated_at": "2020-05-27T23:57:02Z" 26 | }, 27 | "message": "DNS record created successfully" 28 | } 29 | -------------------------------------------------------------------------------- /providers/dns/autodns/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "origin": "example.com", 3 | "resourceRecords": [ 4 | { 5 | "name": "example.com", 6 | "ttl": 120, 7 | "type": "TXT", 8 | "value": "txt", 9 | "pref": 1 10 | } 11 | ], 12 | "action": "xxx", 13 | "virtualNameServer": "yyy" 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/autodns/internal/fixtures/remove-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "origin": "example.com", 3 | "resourceRecords": [ 4 | { 5 | "name": "example.com", 6 | "ttl": 120, 7 | "type": "TXT", 8 | "value": "txt", 9 | "pref": 1 10 | } 11 | ], 12 | "action": "xxx", 13 | "virtualNameServer": "yyy" 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_add.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "OK", 3 | "message": "DNS record added", 4 | "result": "success" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_add_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error_code": "1", 3 | "error_text": "Domain not found", 4 | "result": "error" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_delete.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "OK", 3 | "message": "DNS record deleted", 4 | "result": "success" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_delete_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error_code": "1", 3 | "error_text": "Domain not found", 4 | "result": "error" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "OK", 3 | "message": "DNS-records", 4 | "count": 4, 5 | "result": "success", 6 | "list": [ 7 | { 8 | "id": "74749", 9 | "name": "example.com", 10 | "type": "A", 11 | "value": "46.161.54.22" 12 | }, 13 | { 14 | "id": "417", 15 | "name": "example.com", 16 | "type": "MX", 17 | "value": "mx.yandex.ru.", 18 | "prio": "10" 19 | }, 20 | { 21 | "id": "419", 22 | "name": "mail.example.com", 23 | "type": "CNAME", 24 | "value": "mail.yandex.ru." 25 | }, 26 | { 27 | "id": "74750", 28 | "name": "www.example.com", 29 | "type": "A", 30 | "value": "46.161.54.22" 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /providers/dns/axelname/internal/fixtures/dns_list_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error_code": "1", 3 | "error_text": "Domain not found", 4 | "result": "error" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/bluecat/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // Entity JSON body for Bluecat entity requests. 4 | type Entity struct { 5 | ID string `json:"id,omitempty"` 6 | Name string `json:"name"` 7 | Type string `json:"type"` 8 | Properties string `json:"properties"` 9 | } 10 | 11 | // EntityResponse JSON body for Bluecat entity responses. 12 | type EntityResponse struct { 13 | ID uint `json:"id"` 14 | Name string `json:"name"` 15 | Type string `json:"type"` 16 | Properties string `json:"properties"` 17 | } 18 | -------------------------------------------------------------------------------- /providers/dns/bookmyname/internal/fixtures/add_success.txt: -------------------------------------------------------------------------------- 1 | good: update done, cid 123, domain id 456, type txt, ip xxx 2 | -------------------------------------------------------------------------------- /providers/dns/bookmyname/internal/fixtures/error.txt: -------------------------------------------------------------------------------- 1 | notfqdn: Host _acme-challenge.sub.example.com. malformed / vhn 2 | -------------------------------------------------------------------------------- /providers/dns/bookmyname/internal/fixtures/remove_success.txt: -------------------------------------------------------------------------------- 1 | good: remove done 1, cid 123, domain id 456, ttl 300, type txt, ip xxx 2 | -------------------------------------------------------------------------------- /providers/dns/bookmyname/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type Record struct { 4 | Hostname string `url:"hostname"` 5 | Type string `url:"type"` 6 | TTL int `url:"ttl"` 7 | Value string `url:"value"` 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/brandit/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "zonetype": [ 4 | "com" 5 | ], 6 | "signed": [ 7 | 1 8 | ] 9 | }, 10 | "record": "example.com. 600 IN TXT txttxttxt", 11 | "code": 200, 12 | "status": "success", 13 | "error": "" 14 | } -------------------------------------------------------------------------------- /providers/dns/brandit/internal/fixtures/delete-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 200, 3 | "status": "success", 4 | "error": "" 5 | } -------------------------------------------------------------------------------- /providers/dns/brandit/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 402, 3 | "status": "error", 4 | "error": "Invalid user." 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/brandit/internal/fixtures/list-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "limit": [ 4 | 100 5 | ], 6 | "column": [ 7 | "rr" 8 | ], 9 | "count": [ 10 | 1 11 | ], 12 | "first": [ 13 | 0 14 | ], 15 | "total": [ 16 | 1 17 | ], 18 | "rr": [ 19 | "example.com. 600 IN TXT txttxttxt" 20 | ], 21 | "last": [ 22 | 0 23 | ] 24 | }, 25 | "code": 200, 26 | "status": "success", 27 | "error": "" 28 | } -------------------------------------------------------------------------------- /providers/dns/bunny/bunny.toml: -------------------------------------------------------------------------------- 1 | Name = "Bunny" 2 | Description = '''''' 3 | URL = "https://bunny.net" 4 | Code = "bunny" 5 | Since = "v4.11.0" 6 | 7 | Example = ''' 8 | BUNNY_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ 9 | lego --email you@example.com --dns bunny -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | BUNNY_API_KEY = "API key" 15 | [Configuration.Additional] 16 | BUNNY_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | BUNNY_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | BUNNY_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 19 | 20 | [Links] 21 | API = "https://docs.bunny.net/reference/dnszonepublic_index" 22 | bunny-go = "https://github.com/nrdcg/bunny-go" 23 | -------------------------------------------------------------------------------- /providers/dns/civo/civo.toml: -------------------------------------------------------------------------------- 1 | Name = "Civo" 2 | Description = '''''' 3 | URL = "https://civo.com" 4 | Code = "civo" 5 | Since = "v4.9.0" 6 | 7 | Example = ''' 8 | CIVO_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns civo -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | CIVO_TOKEN = "Authentication token" 15 | [Configuration.Additional] 16 | CIVO_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 30)" 17 | CIVO_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 300)" 18 | CIVO_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)" 19 | 20 | [Links] 21 | API = "https://www.civo.com/api/dns" 22 | -------------------------------------------------------------------------------- /providers/dns/cloudru/internal/fixtures/auth-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "invalid_client", 3 | "error_description": "client not found" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/cloudru/internal/fixtures/record.json: -------------------------------------------------------------------------------- 1 | { 2 | "zone_id": "59556fcd-95ff-451f-b49b-9732f21f944a", 3 | "name": "www.example.com.", 4 | "type": "TXT", 5 | "values": [ 6 | "txt" 7 | ], 8 | "ttl": "3600", 9 | "enables": true, 10 | "readonly": false 11 | } 12 | -------------------------------------------------------------------------------- /providers/dns/cloudru/internal/fixtures/zones.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "id": "59556fcd-95ff-451f-b49b-9732f21f944a", 5 | "parent_id": "2d7b6194-2b83-4f71-86fd-a1e727e347b2", 6 | "name": "example.com", 7 | "valid": true, 8 | "validation_text": "sbc-verification: 5c86c962-7ee2-4983-b39b-1d9461959d8b", 9 | "delegated": true, 10 | "created_at": "2023-07-23T08:12:41.000000Z", 11 | "updated_at": "2023-07-24T05:50:28.000000Z" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/cloudxns/cloudxns.toml: -------------------------------------------------------------------------------- 1 | Name = "CloudXNS (Deprecated)" 2 | Description = ''' 3 | The CloudXNS DNS provider has shut down. 4 | ''' 5 | URL = "https://github.com/go-acme/lego/issues/2323" 6 | Code = "cloudxns" 7 | Since = "v0.5.0" 8 | 9 | Example = ''' 10 | CLOUDXNS_API_KEY=xxxx \ 11 | CLOUDXNS_SECRET_KEY=yyyy \ 12 | lego --email you@example.com --dns cloudxns -d '*.example.com' -d example.com run 13 | ''' 14 | 15 | [Configuration] 16 | [Configuration.Credentials] 17 | CLOUDXNS_API_KEY = "The API key" 18 | CLOUDXNS_SECRET_KEY = "The API secret key" 19 | [Configuration.Additional] 20 | CLOUDXNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: )" 21 | CLOUDXNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: )" 22 | CLOUDXNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: )" 23 | CLOUDXNS_HTTP_TIMEOUT = "API request timeout in seconds (Default: )" 24 | -------------------------------------------------------------------------------- /providers/dns/conoha/internal/fixtures/domains-records_POST.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2e32e609-3a4f-45ba-bdef-e50eacd345ad", 3 | "name": "www.example.com.", 4 | "type": "A", 5 | "created_at": "2012-11-02T19:56:26.366792", 6 | "updated_at": null, 7 | "domain_id": "89acac79-38e7-497d-807c-a011e1310438", 8 | "ttl": null, 9 | "data": "192.0.2.3", 10 | "gslb_check": 1, 11 | "gslb_region": "JP", 12 | "gslb_weight": 250 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/conoha/internal/fixtures/domains_GET.json: -------------------------------------------------------------------------------- 1 | { 2 | "domains":[ 3 | { 4 | "id": "09494b72-b65b-4297-9efb-187f65a0553e", 5 | "name": "domain1.com.", 6 | "ttl": 3600, 7 | "serial": 1351800668, 8 | "email": "nsadmin@example.org", 9 | "gslb": 0, 10 | "created_at": "2012-11-01T20:11:08.000000", 11 | "updated_at": null, 12 | "description": "memo" 13 | }, 14 | { 15 | "id": "cf661142-e577-40b5-b3eb-75795cdc0cd7", 16 | "name": "domain2.com.", 17 | "ttl": 7200, 18 | "serial": 1351800670, 19 | "email": "nsadmin2@example.org", 20 | "gslb": 1, 21 | "created_at": "2012-11-01T20:11:08.000000", 22 | "updated_at": "2012-12-01T20:11:08.000000", 23 | "description": "memomemo" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /providers/dns/conoha/internal/fixtures/tokens_POST.json: -------------------------------------------------------------------------------- 1 | { 2 | "access": { 3 | "token": { 4 | "issued_at": "2015-05-19T07:08:21.927295", 5 | "expires": "2015-05-20T07:08:21Z", 6 | "id": "sample00d88246078f2bexample788f7", 7 | "tenant": { 8 | "name": "example00000000", 9 | "enabled": true, 10 | "tyo1_image_size": "550GB" 11 | }, 12 | "endpoints_links": [], 13 | "type": "mailhosting", 14 | "name": "Mail Hosting Service" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /providers/dns/conohav3/internal/fixtures/domains-records_POST.json: -------------------------------------------------------------------------------- 1 | { 2 | "uuid": "2e32e609-3a4f-45ba-bdef-e50eacd345ad", 3 | "name": "www.example.com.", 4 | "type": "A", 5 | "created_at": "2012-11-02T19:56:26.366792", 6 | "updated_at": null, 7 | "domain_id": "89acac79-38e7-497d-807c-a011e1310438", 8 | "ttl": null, 9 | "data": "192.0.2.3", 10 | "gslb_check": 1, 11 | "gslb_region": "JP", 12 | "gslb_weight": 250 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/conohav3/internal/fixtures/domains_GET.json: -------------------------------------------------------------------------------- 1 | { 2 | "domains": [ 3 | { 4 | "uuid": "09494b72-b65b-4297-9efb-187f65a0553e", 5 | "name": "domain1.com.", 6 | "project_id": "cf661142-e577-40b5-b3eb-75795cdc0cd7", 7 | "serial": 1701909248, 8 | "ttl": 3600, 9 | "email": "nsadmin1@example.org", 10 | "created_at": "2023-12-07T00:34:08Z", 11 | "updated_at": "2023-12-07T00:34:08Z" 12 | }, 13 | { 14 | "uuid": "cf661142-e577-40b5-b3eb-75795cdc0cd7", 15 | "name": "domain2.com.", 16 | "project_id": "cf661144-e578-39b6-b4eb-75794cdc1cd8", 17 | "serial": 1351800670, 18 | "ttl": 7200, 19 | "email": "nsadmin2@example.org", 20 | "created_at": "2012-11-01T20:11:08Z", 21 | "updated_at": "2012-12-01T20:11:08Z" 22 | } 23 | ], 24 | "total_count": 1 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/constellix/internal/fixtures/records-Create.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 3557066, 4 | "type": "TXT", 5 | "recordType": "txt", 6 | "name": "test", 7 | "recordOption": "roundRobin", 8 | "ttl": 300, 9 | "gtdRegion": 1, 10 | "parentId": 273302, 11 | "parent": "domain", 12 | "source": "Domain", 13 | "modifiedTs": 1580908547865, 14 | "value": [ 15 | { 16 | "value": "\"test\"" 17 | } 18 | ], 19 | "roundRobin": [ 20 | { 21 | "value": "\"test\"" 22 | } 23 | ] 24 | } 25 | ] -------------------------------------------------------------------------------- /providers/dns/constellix/internal/fixtures/records-Get.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 3557066, 3 | "type": "TXT", 4 | "recordType": "txt", 5 | "name": "test", 6 | "recordOption": "roundRobin", 7 | "ttl": 300, 8 | "gtdRegion": 1, 9 | "parentId": 273302, 10 | "parent": "domain", 11 | "source": "Domain", 12 | "modifiedTs": 1580908547863, 13 | "value": [ 14 | { 15 | "value": "\"test\"" 16 | } 17 | ], 18 | "roundRobin": [ 19 | { 20 | "value": "\"test\"" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /providers/dns/constellix/internal/fixtures/records-GetAll.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 3557066, 4 | "type": "TXT", 5 | "recordType": "txt", 6 | "name": "test", 7 | "recordOption": "roundRobin", 8 | "ttl": 300, 9 | "gtdRegion": 1, 10 | "parentId": 273302, 11 | "parent": "domain", 12 | "source": "Domain", 13 | "modifiedTs": 1580908547865, 14 | "value": [ 15 | { 16 | "value": "\"test\"" 17 | } 18 | ], 19 | "roundRobin": [ 20 | { 21 | "value": "\"test\"" 22 | } 23 | ] 24 | } 25 | ] -------------------------------------------------------------------------------- /providers/dns/constellix/internal/fixtures/records-Search.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 3557066, 4 | "name": "test", 5 | "recordType": "", 6 | "type": "" 7 | } 8 | ] -------------------------------------------------------------------------------- /providers/dns/corenetworks/internal/fixtures/GetZoneDetails.json: -------------------------------------------------------------------------------- 1 | { 2 | "active": true, 3 | "dnssec": true, 4 | "master": null, 5 | "name": "example.com", 6 | "tsig": null, 7 | "type": "master" 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/corenetworks/internal/fixtures/ListRecords.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "@", 4 | "ttl": 86400, 5 | "type": "NS", 6 | "data": "ns2.core-networks.eu." 7 | }, 8 | { 9 | "name": "@", 10 | "ttl": 86400, 11 | "type": "NS", 12 | "data": "ns3.core-networks.com." 13 | }, 14 | { 15 | "name": "@", 16 | "ttl": 86400, 17 | "type": "NS", 18 | "data": "ns1.core-networks.de." 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /providers/dns/corenetworks/internal/fixtures/ListZone.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "example.com", 4 | "type": "master" 5 | }, 6 | { 7 | "name": "example.net", 8 | "type": "slave" 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /providers/dns/corenetworks/internal/fixtures/auth.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "authsecret", 3 | "expires": 123 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/cpanel/fixtures/update-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "transformed": 1 4 | }, 5 | "messages": null, 6 | "status": 1, 7 | "warnings": null, 8 | "errors": null, 9 | "data": { 10 | "new_serial": "2021031903" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/cpanel/fixtures/update-zone_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": null, 3 | "messages": [ 4 | "a", 5 | "b", 6 | "c" 7 | ], 8 | "data": null, 9 | "errors": [ 10 | "You do not control a DNS zone named example.com." 11 | ], 12 | "metadata": {}, 13 | "status": 0 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/cpanel/fixtures/zone-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "transformed": 1 4 | }, 5 | "messages": null, 6 | "status": 1, 7 | "warnings": null, 8 | "errors": null, 9 | "data": [ 10 | { 11 | "line_index": 22, 12 | "dname_b64": "dGV4YXMuY29tLg==", 13 | "data_b64": [ 14 | "dGV4YXMuY29tLg==" 15 | ], 16 | "type": "record", 17 | "ttl": 14400, 18 | "record_type": "MX" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/cpanel/fixtures/zone-info_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "warnings": null, 3 | "messages": [ 4 | "a", 5 | "b", 6 | "c" 7 | ], 8 | "data": null, 9 | "errors": [ 10 | "You do not control a DNS zone named example.com." 11 | ], 12 | "metadata": {}, 13 | "status": 0 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/cpanel/types.go: -------------------------------------------------------------------------------- 1 | package cpanel 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type APIResponse[T any] struct { 9 | Metadata Metadata `json:"metadata,omitempty"` 10 | Data T `json:"data,omitempty"` 11 | 12 | Status int `json:"status,omitempty"` 13 | Messages []string `json:"messages,omitempty"` 14 | Warnings []string `json:"warnings,omitempty"` 15 | Errors []string `json:"errors,omitempty"` 16 | } 17 | 18 | type Metadata struct { 19 | Transformed int `json:"transformed,omitempty"` 20 | } 21 | 22 | func toError[T any](r APIResponse[T]) error { 23 | return fmt.Errorf("error(%d): %s: %s", r.Status, strings.Join(r.Errors, ", "), strings.Join(r.Messages, ", ")) 24 | } 25 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/shared/types.go: -------------------------------------------------------------------------------- 1 | package shared 2 | 3 | type Record struct { 4 | DName string `json:"dname,omitempty"` 5 | TTL int `json:"ttl,omitempty"` 6 | RecordType string `json:"record_type,omitempty"` 7 | Data []string `json:"data,omitempty"` 8 | LineIndex int `json:"line_index,omitempty"` 9 | } 10 | 11 | type ZoneRecord struct { 12 | LineIndex int `json:"line_index,omitempty"` 13 | Type string `json:"type,omitempty"` 14 | DataB64 []string `json:"data_b64,omitempty"` 15 | DNameB64 string `json:"dname_b64,omitempty"` 16 | TextB64 string `json:"text_b64,omitempty"` 17 | RecordType string `json:"record_type,omitempty"` 18 | TTL int `json:"ttl,omitempty"` 19 | } 20 | 21 | type ZoneSerial struct { 22 | NewSerial string `json:"new_serial,omitempty"` 23 | } 24 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/whm/fixtures/update-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "new_serial": "2021031903" 4 | }, 5 | "metadata": { 6 | "command": "mass_edit_dns_zone", 7 | "reason": "OK", 8 | "result": 1, 9 | "version": 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/whm/fixtures/update-zone_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": null, 3 | "metadata": { 4 | "command": "mass_edit_dns_zone", 5 | "reason": "There is a problem", 6 | "result": 0, 7 | "version": 1 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/whm/fixtures/zone-info.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "payload": [ 4 | { 5 | "line_index": 22, 6 | "type": "record", 7 | "data_b64": [ 8 | "dGV4YXMuY29tLg==" 9 | ], 10 | "dname_b64": "dGV4YXMuY29tLg==", 11 | "record_type": "MX", 12 | "ttl": 14400 13 | } 14 | ] 15 | }, 16 | "metadata": { 17 | "command": "parse_dns_zone", 18 | "reason": "OK", 19 | "result": 1, 20 | "version": 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/whm/fixtures/zone-info_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": null, 3 | "metadata": { 4 | "command": "parse_dns_zone", 5 | "reason": "There is a problem", 6 | "result": 0, 7 | "version": 1 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/cpanel/internal/whm/types.go: -------------------------------------------------------------------------------- 1 | package whm 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-acme/lego/v4/providers/dns/cpanel/internal/shared" 7 | ) 8 | 9 | type APIResponse[T any] struct { 10 | Metadata Metadata `json:"metadata,omitempty"` 11 | Data T `json:"data,omitempty"` 12 | } 13 | 14 | type Metadata struct { 15 | Command string `json:"command,omitempty"` 16 | Reason string `json:"reason,omitempty"` 17 | Result int `json:"result,omitempty"` 18 | Version int `json:"version,omitempty"` 19 | } 20 | 21 | type ZoneData struct { 22 | Payload []shared.ZoneRecord `json:"payload,omitempty"` 23 | } 24 | 25 | func toError(m Metadata) error { 26 | return fmt.Errorf("%s error(%d): %s", m.Command, m.Result, m.Reason) 27 | } 28 | -------------------------------------------------------------------------------- /providers/dns/derak/derak.toml: -------------------------------------------------------------------------------- 1 | Name = "Derak Cloud" 2 | Description = '''''' 3 | URL = "https://derak.cloud/" 4 | Code = "derak" 5 | Since = "v4.12.0" 6 | 7 | Example = ''' 8 | DERAK_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns derak -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DERAK_API_KEY = "The API key" 15 | [Configuration.Additional] 16 | DERAK_WEBSITE_ID = "Force the zone/website ID" 17 | DERAK_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 5)" 18 | DERAK_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 19 | DERAK_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 20 | DERAK_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | -------------------------------------------------------------------------------- /providers/dns/derak/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | {"success":false,"error":1010} 2 | -------------------------------------------------------------------------------- /providers/dns/derak/internal/fixtures/record-DELETE.json: -------------------------------------------------------------------------------- 1 | { 2 | "success": true 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/derak/internal/fixtures/record-GET.json: -------------------------------------------------------------------------------- 1 | { 2 | "recordId": "812bee17a0b440b0bd5ee099a78b839c", 3 | "type": "A", 4 | "host": "example.com", 5 | "content": "188.114.97.3", 6 | "ttl": 0, 7 | "cloud": false, 8 | "advanced": false, 9 | "customSSLType": "" 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/derak/internal/fixtures/record-PATCH.json: -------------------------------------------------------------------------------- 1 | { 2 | "recordId": "812bee17a0b440b0bd5ee099a78b839c", 3 | "type": "A", 4 | "host": "example.com", 5 | "content": "188.114.97.3", 6 | "ttl": 0, 7 | "cloud": false, 8 | "advanced": false, 9 | "customSSLType": "" 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/derak/internal/fixtures/record-PUT.json: -------------------------------------------------------------------------------- 1 | { 2 | "recordId": "812bee17a0b440b0bd5ee099a78b839c", 3 | "type": "A", 4 | "host": "example.com", 5 | "content": "188.114.97.3", 6 | "ttl": 0, 7 | "cloud": false, 8 | "advanced": false, 9 | "customSSLType": "" 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/desec/desec.toml: -------------------------------------------------------------------------------- 1 | Name = "deSEC.io" 2 | Description = '''''' 3 | URL = "https://desec.io" 4 | Code = "desec" 5 | Since = "v3.7.0" 6 | 7 | Example = ''' 8 | DESEC_TOKEN=x-xxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns desec -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DESEC_TOKEN = "Domain token" 15 | [Configuration.Additional] 16 | DESEC_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 4)" 17 | DESEC_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | DESEC_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | DESEC_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://desec.readthedocs.io/en/latest/" 23 | -------------------------------------------------------------------------------- /providers/dns/digitalocean/internal/fixtures/domains-records_POST.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain_record": { 3 | "id": 1234567, 4 | "type": "TXT", 5 | "name": "_acme-challenge", 6 | "data": "w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI", 7 | "priority": null, 8 | "port": null, 9 | "weight": null 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /providers/dns/digitalocean/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | // TxtRecordResponse represents a response from DO's API after making a TXT record. 6 | type TxtRecordResponse struct { 7 | DomainRecord Record `json:"domain_record"` 8 | } 9 | 10 | type Record struct { 11 | ID int `json:"id,omitempty"` 12 | Type string `json:"type,omitempty"` 13 | Name string `json:"name,omitempty"` 14 | Data string `json:"data,omitempty"` 15 | TTL int `json:"ttl,omitempty"` 16 | } 17 | 18 | type APIError struct { 19 | ID string `json:"id"` 20 | Message string `json:"message"` 21 | } 22 | 23 | func (a APIError) Error() string { 24 | return fmt.Sprintf("%s: %s", a.ID, a.Message) 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/directadmin/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | // Record represents a DNS record. 6 | type Record struct { 7 | Name string `url:"name,omitempty"` 8 | Type string `url:"type,omitempty"` 9 | Value string `url:"value,omitempty"` 10 | TTL int `url:"ttl,omitempty"` 11 | } 12 | 13 | // APIError represents a API error. 14 | type APIError struct { 15 | Message string `json:"error,omitempty"` 16 | Result string `json:"result,omitempty"` 17 | } 18 | 19 | func (a APIError) Error() string { 20 | return fmt.Sprintf("%s: %s", a.Message, a.Result) 21 | } 22 | -------------------------------------------------------------------------------- /providers/dns/dnsmadeeasy/internal/client_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "net/http" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func Test_sign(t *testing.T) { 13 | apiKey := "key" 14 | 15 | client := Client{apiKey: apiKey, apiSecret: "secret"} 16 | 17 | req, err := http.NewRequest(http.MethodGet, "", http.NoBody) 18 | require.NoError(t, err) 19 | 20 | timestamp := time.Date(2015, time.June, 2, 2, 36, 7, 0, time.UTC).Format(time.RFC1123) 21 | 22 | err = client.sign(req, timestamp) 23 | require.NoError(t, err) 24 | 25 | assert.Equal(t, apiKey, req.Header.Get("x-dnsme-apiKey")) 26 | assert.Equal(t, timestamp, req.Header.Get("x-dnsme-requestDate")) 27 | assert.Equal(t, "6b6c8432119c31e1d3776eb4cd3abd92fae4a71c", req.Header.Get("x-dnsme-hmac")) 28 | } 29 | -------------------------------------------------------------------------------- /providers/dns/dnsmadeeasy/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // Domain holds the DNSMadeEasy API representation of a Domain. 4 | type Domain struct { 5 | ID int `json:"id"` 6 | Name string `json:"name"` 7 | } 8 | 9 | // Record holds the DNSMadeEasy API representation of a Domain Record. 10 | type Record struct { 11 | ID int `json:"id"` 12 | Type string `json:"type"` 13 | Name string `json:"name"` 14 | Value string `json:"value"` 15 | TTL int `json:"ttl"` 16 | SourceID int `json:"sourceId"` 17 | } 18 | 19 | type recordsResponse struct { 20 | Records *[]Record `json:"data"` 21 | } 22 | -------------------------------------------------------------------------------- /providers/dns/dnspod/dnspod.toml: -------------------------------------------------------------------------------- 1 | Name = "DNSPod (deprecated)" 2 | Description = ''' 3 | Use the Tencent Cloud provider instead. 4 | ''' 5 | URL = "https://www.dnspod.com/" 6 | Code = "dnspod" 7 | Since = "v0.4.0" 8 | 9 | Example = ''' 10 | DNSPOD_API_KEY=xxxxxx \ 11 | lego --email you@example.com --dns dnspod -d '*.example.com' -d example.com run 12 | ''' 13 | 14 | [Configuration] 15 | [Configuration.Credentials] 16 | DNSPOD_API_KEY = "The user token" 17 | [Configuration.Additional] 18 | DNSPOD_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 19 | DNSPOD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 20 | DNSPOD_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 600)" 21 | DNSPOD_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://docs.dnspod.com/api/" 25 | GoClient = "https://github.com/nrdcg/dnspod-go" 26 | -------------------------------------------------------------------------------- /providers/dns/dode/dode.toml: -------------------------------------------------------------------------------- 1 | Name = "Domain Offensive (do.de)" 2 | Description = '''''' 3 | URL = "https://www.do.de/" 4 | Code = "dode" 5 | Since = "v2.4.0" 6 | 7 | Example = ''' 8 | DODE_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns dode -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DODE_TOKEN = "API token" 15 | [Configuration.Additional] 16 | DODE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | DODE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | DODE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | DODE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | DODE_SEQUENCE_INTERVAL = "Time between sequential requests in seconds (Default: 60)" 21 | 22 | [Links] 23 | API = "https://www.do.de/wiki/freie-ssl-tls-zertifikate-ueber-acme/" 24 | -------------------------------------------------------------------------------- /providers/dns/dode/internal/fixtures/success.json: -------------------------------------------------------------------------------- 1 | { 2 | "Domain" : "example.com", 3 | "Success": true 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/dode/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type apiResponse struct { 4 | Domain string 5 | Success bool 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/domeneshop/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // Domain JSON data structure. 4 | type Domain struct { 5 | Name string `json:"domain"` 6 | ID int `json:"id"` 7 | ExpiryDate string `json:"expiry_date"` 8 | Nameservers []string `json:"nameservers"` 9 | RegisteredDate string `json:"registered_date"` 10 | Registrant string `json:"registrant"` 11 | Renew bool `json:"renew"` 12 | Services Service `json:"services"` 13 | Status string 14 | } 15 | 16 | type Service struct { 17 | DNS bool `json:"dns"` 18 | Email bool `json:"email"` 19 | Registrar bool `json:"registrar"` 20 | Webhotel string `json:"webhotel"` 21 | } 22 | 23 | // DNSRecord JSON data structure. 24 | type DNSRecord struct { 25 | Data string `json:"data"` 26 | Host string `json:"host"` 27 | ID int `json:"id"` 28 | TTL int `json:"ttl"` 29 | Type string `json:"type"` 30 | } 31 | -------------------------------------------------------------------------------- /providers/dns/dreamhost/dreamhost.toml: -------------------------------------------------------------------------------- 1 | Name = "DreamHost" 2 | Description = '''''' 3 | URL = "https://www.dreamhost.com" 4 | Code = "dreamhost" 5 | Since = "v1.1.0" 6 | 7 | Example = ''' 8 | DREAMHOST_API_KEY="YOURAPIKEY" \ 9 | lego --email you@example.com --dns dreamhost -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DREAMHOST_API_KEY = "The API key" 15 | [Configuration.Additional] 16 | DREAMHOST_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 60)" 17 | DREAMHOST_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 3600)" 18 | DREAMHOST_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 19 | 20 | [Links] 21 | API = "https://help.dreamhost.com/hc/en-us/articles/217560167-API_overview" 22 | -------------------------------------------------------------------------------- /providers/dns/dreamhost/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type apiResponse struct { 4 | Data string `json:"data"` 5 | Result string `json:"result"` 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/duckdns/duckdns.toml: -------------------------------------------------------------------------------- 1 | Name = "Duck DNS" 2 | Description = '''''' 3 | URL = "https://www.duckdns.org/" 4 | Code = "duckdns" 5 | Since = "v0.5.0" 6 | 7 | Example = ''' 8 | DUCKDNS_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns duckdns -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DUCKDNS_TOKEN = "Account token" 15 | [Configuration.Additional] 16 | DUCKDNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | DUCKDNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | DUCKDNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | DUCKDNS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | DUCKDNS_SEQUENCE_INTERVAL = "Time between sequential requests in seconds (Default: 60)" 21 | 22 | [Links] 23 | API = "https://www.duckdns.org/spec.jsp" 24 | -------------------------------------------------------------------------------- /providers/dns/dyn/dyn.toml: -------------------------------------------------------------------------------- 1 | Name = "Dyn" 2 | Description = '''''' 3 | URL = "https://dyn.com/" 4 | Code = "dyn" 5 | Since = "v0.3.0" 6 | 7 | Example = ''' 8 | DYN_CUSTOMER_NAME=xxxxxx \ 9 | DYN_USER_NAME=yyyyy \ 10 | DYN_PASSWORD=zzzz \ 11 | lego --email you@example.com --dns dyn -d '*.example.com' -d example.com run 12 | ''' 13 | 14 | [Configuration] 15 | [Configuration.Credentials] 16 | DYN_CUSTOMER_NAME = "Customer name" 17 | DYN_USER_NAME = "User name" 18 | DYN_PASSWORD = "Password" 19 | [Configuration.Additional] 20 | DYN_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 21 | DYN_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 22 | DYN_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 23 | DYN_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 24 | 25 | [Links] 26 | API = "https://help.dyn.com/rest/" 27 | -------------------------------------------------------------------------------- /providers/dns/dyn/internal/fixtures/create-txt-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "fqdn": "example.com.", 3 | "rdata": { 4 | "txtdata": "txt" 5 | }, 6 | "record_type": "TXT", 7 | "ttl": 120, 8 | "zone": "example.com" 9 | } 10 | 11 | -------------------------------------------------------------------------------- /providers/dns/dyn/internal/fixtures/login.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "success", 3 | "data": { 4 | "token": "tok", 5 | "version": "456" 6 | }, 7 | "job_id": 123, 8 | "msgs": [] 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/dyn/internal/fixtures/publish.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "success", 3 | "data": {}, 4 | "job_id": 123, 5 | "msgs": [] 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/dyn/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "encoding/json" 4 | 5 | type APIResponse struct { 6 | // One of 'success', 'failure', or 'incomplete' 7 | Status string `json:"status"` 8 | 9 | // The structure containing the actual results of the request 10 | Data json.RawMessage `json:"data"` 11 | 12 | // The ID of the job that was created in response to a request. 13 | JobID int `json:"job_id"` 14 | 15 | // A list of zero or more messages 16 | Messages json.RawMessage `json:"msgs"` 17 | } 18 | 19 | type credentials struct { 20 | Customer string `json:"customer_name"` 21 | User string `json:"user_name"` 22 | Pass string `json:"password"` 23 | } 24 | 25 | type session struct { 26 | Token string `json:"token"` 27 | Version string `json:"version"` 28 | } 29 | 30 | type publish struct { 31 | Publish bool `json:"publish"` 32 | Notes string `json:"notes"` 33 | } 34 | -------------------------------------------------------------------------------- /providers/dns/dynu/dynu.toml: -------------------------------------------------------------------------------- 1 | Name = "Dynu" 2 | Description = '''''' 3 | URL = "https://www.dynu.com/" 4 | Code = "dynu" 5 | Since = "v3.5.0" 6 | 7 | Example = ''' 8 | DYNU_API_KEY=1234567890abcdefghijklmnopqrstuvwxyz \ 9 | lego --email you@example.com --dns dynu -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | DYNU_API_KEY = "API key" 15 | [Configuration.Additional] 16 | DYNU_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)" 17 | DYNU_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 180)" 18 | DYNU_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 19 | DYNU_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://www.dynu.com/en-US/Support/API" 23 | -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/add_new_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 200, 3 | "id": 6041417, 4 | "domainId": 9007481, 5 | "domainName": "lego.freeddns.org", 6 | "nodeName": "_acme-challenge", 7 | "hostname": "_acme-challenge.lego.freeddns.org", 8 | "recordType": "TXT", 9 | "ttl": 300, 10 | "state": true, 11 | "content": "_acme-challenge.lego.freeddns.org. 300 IN TXT \"txt_txt_txt_txt_txt_txt_txt\"", 12 | "updatedOn": "2020-03-10T04:00:36.923", 13 | "textData": "txt_txt_txt_txt_txt_txt_txt" 14 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/add_new_record_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 501, 3 | "type": "Argument Exception", 4 | "message": "Invalid." 5 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/delete_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 200 3 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/delete_record_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 501, 3 | "type": "Argument Exception", 4 | "message": "Invalid." 5 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/get_records_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 200, 3 | "dnsRecords": [] 4 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/get_records_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 501, 3 | "type": "Argument Exception", 4 | "message": "Invalid." 5 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/get_root_domain.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 200, 3 | "id": 9007481, 4 | "domainName": "lego.freeddns.org", 5 | "hostname": "test.lego.freeddns.org", 6 | "node": "test" 7 | } -------------------------------------------------------------------------------- /providers/dns/dynu/internal/fixtures/get_root_domain_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 501, 3 | "type": "Argument Exception", 4 | "message": "Invalid." 5 | } -------------------------------------------------------------------------------- /providers/dns/easydns/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "msg": "message", 3 | "tm": 1, 4 | "data": { 5 | "id": "xxx", 6 | "domain": "example.com", 7 | "host": "test631", 8 | "ttl": "300", 9 | "prio": "0", 10 | "type": "TXT", 11 | "rdata": "txt" 12 | }, 13 | "status": 201 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/easydns/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "msg": "Enhance your calm", 3 | "status": 403 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/easydns/internal/fixtures/error1.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "code": 420, 4 | "message": "Enhance Your Calm. Rate limit exceeded (too many requests) OR you did NOT provide any credentials with your request!" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/easydns/internal/fixtures/list-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "msg": "message", 3 | "status": 200, 4 | "tm": 0, 5 | "data": [ 6 | { 7 | "id": "60898922", 8 | "domain": "example.com", 9 | "host": "hosta", 10 | "ttl": "300", 11 | "prio": "0", 12 | "geozone_id": "0", 13 | "type": "A", 14 | "rdata": "1.2.3.4", 15 | "last_mod": "2019-08-28 19:09:50" 16 | } 17 | ], 18 | "count": 43, 19 | "total": 43, 20 | "start": 0, 21 | "max": 1000 22 | } 23 | -------------------------------------------------------------------------------- /providers/dns/efficientip/internal/fixtures/dns_rr_add.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ret_oid": "239" 4 | } 5 | ] 6 | -------------------------------------------------------------------------------- /providers/dns/efficientip/internal/fixtures/dns_rr_delete-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "errno": "20117", 3 | "errmsg": "This RR does not exist", 4 | "severity": "error", 5 | "category": "dns_rr_delete" 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/efficientip/internal/fixtures/dns_rr_delete.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ret_oid": "251" 4 | } 5 | ] 6 | -------------------------------------------------------------------------------- /providers/dns/epik/epik.toml: -------------------------------------------------------------------------------- 1 | Name = "Epik" 2 | Description = '''''' 3 | URL = "https://www.epik.com/" 4 | Code = "epik" 5 | Since = "v4.5.0" 6 | 7 | Example = ''' 8 | EPIK_SIGNATURE=xxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns epik -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | EPIK_SIGNATURE = "Epik API signature (https://registrar.epik.com/account/api-settings/)" 15 | [Configuration.Additional] 16 | EPIK_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | EPIK_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | EPIK_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | EPIK_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://docs-userapi.epik.com/v2/" 23 | -------------------------------------------------------------------------------- /providers/dns/epik/internal/fixtures/createHostRecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 1000, 3 | "message": "Command completed successfully.", 4 | "description": null 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/epik/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "code": 1, 5 | "message": "Unauthorized", 6 | "description": "Unauthorized: Signature was not provided or was invalid" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/epik/internal/fixtures/removeHostRecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 1000, 3 | "message": "Command completed successfully.", 4 | "description": null 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/exec/log_mock_test.go: -------------------------------------------------------------------------------- 1 | package exec 2 | 3 | import "github.com/stretchr/testify/mock" 4 | 5 | type LogRecorder struct { 6 | mock.Mock 7 | } 8 | 9 | func (*LogRecorder) Fatal(args ...interface{}) { 10 | panic("implement me") 11 | } 12 | 13 | func (*LogRecorder) Fatalln(args ...interface{}) { 14 | panic("implement me") 15 | } 16 | 17 | func (*LogRecorder) Fatalf(format string, args ...interface{}) { 18 | panic("implement me") 19 | } 20 | 21 | func (*LogRecorder) Print(args ...interface{}) { 22 | panic("implement me") 23 | } 24 | 25 | func (l *LogRecorder) Println(args ...interface{}) { 26 | l.Called(args...) 27 | } 28 | 29 | func (*LogRecorder) Printf(format string, args ...interface{}) { 30 | panic("implement me") 31 | } 32 | -------------------------------------------------------------------------------- /providers/dns/f5xc/internal/fixtures/error_404.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 5, 3 | "details": [], 4 | "message": "the requested resource record was not found: (group,name,type) (acme-records,_acme-challenge,TXT)" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/f5xc/internal/fixtures/error_503.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 14, 3 | "details": [], 4 | "message": "Previous DNS zone change is pending. Try again later" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/freemyip/freemyip.toml: -------------------------------------------------------------------------------- 1 | Name = "freemyip.com" 2 | Description = '''''' 3 | URL = "https://freemyip.com/" 4 | Code = "freemyip" 5 | Since = "v4.5.0" 6 | 7 | Example = ''' 8 | FREEMYIP_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns freemyip -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | FREEMYIP_TOKEN = "Account token" 15 | [Configuration.Additional] 16 | FREEMYIP_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | FREEMYIP_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | FREEMYIP_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | FREEMYIP_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | FREEMYIP_SEQUENCE_INTERVAL = "Time between sequential requests in seconds (Default: 60)" 21 | 22 | [Links] 23 | API = "https://freemyip.com/help" 24 | -------------------------------------------------------------------------------- /providers/dns/gandi/gandi.toml: -------------------------------------------------------------------------------- 1 | Name = "Gandi" 2 | Description = """""" 3 | URL = "https://www.gandi.net" 4 | Code = "gandi" 5 | Since = "v0.3.0" 6 | 7 | Example = ''' 8 | GANDI_API_KEY=abcdefghijklmnopqrstuvwx \ 9 | lego --email you@example.com --dns gandi -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | GANDI_API_KEY = "API key" 15 | [Configuration.Additional] 16 | GANDI_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 60)" 17 | GANDI_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 2400)" 18 | GANDI_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 19 | GANDI_HTTP_TIMEOUT = "API request timeout in seconds (Default: 60)" 20 | 21 | [Links] 22 | API = "https://doc.rpc.gandi.net/index.html" 23 | -------------------------------------------------------------------------------- /providers/dns/gandiv5/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // types for JSON responses with only a message. 4 | type apiResponse struct { 5 | Message string `json:"message"` 6 | UUID string `json:"uuid,omitempty"` 7 | } 8 | 9 | // Record TXT record representation. 10 | type Record struct { 11 | RRSetTTL int `json:"rrset_ttl"` 12 | RRSetValues []string `json:"rrset_values"` 13 | RRSetName string `json:"rrset_name,omitempty"` 14 | RRSetType string `json:"rrset_type,omitempty"` 15 | } 16 | -------------------------------------------------------------------------------- /providers/dns/gcloud/fixtures/gce_account_service_file.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_id": "A", 3 | "type": "service_account", 4 | "client_email": "foo@bar.com", 5 | "private_key_id": "pki", 6 | "private_key": "pk", 7 | "token_uri": "/token", 8 | "client_secret": "secret", 9 | "client_id": "C", 10 | "refresh_token": "D" 11 | } -------------------------------------------------------------------------------- /providers/dns/gcore/gcore.toml: -------------------------------------------------------------------------------- 1 | Name = "G-Core" 2 | Description = '''''' 3 | URL = "https://gcore.com/dns/" 4 | Code = "gcore" 5 | Since = "v4.5.0" 6 | 7 | Example = ''' 8 | GCORE_PERMANENT_API_TOKEN=xxxxx \ 9 | lego --email you@example.com --dns gcore -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | GCORE_PERMANENT_API_TOKEN = "Permanent API token (https://gcore.com/blog/permanent-api-token-explained/)" 15 | [Configuration.Additional] 16 | GCORE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 20)" 17 | GCORE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 360)" 18 | GCORE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | GCORE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 20 | 21 | [Links] 22 | API = "https://api.gcore.com/docs/dns#tag/zones" 23 | -------------------------------------------------------------------------------- /providers/dns/gcore/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type Zone struct { 6 | Name string `json:"name"` 7 | } 8 | 9 | type RRSet struct { 10 | TTL int `json:"ttl"` 11 | Records []Records `json:"resource_records"` 12 | } 13 | 14 | type Records struct { 15 | Content []string `json:"content"` 16 | } 17 | 18 | type APIError struct { 19 | StatusCode int `json:"-"` 20 | Message string `json:"error,omitempty"` 21 | } 22 | 23 | func (a APIError) Error() string { 24 | return fmt.Sprintf("%d: %s", a.StatusCode, a.Message) 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/glesys/glesys.toml: -------------------------------------------------------------------------------- 1 | Name = "Glesys" 2 | Description = '''''' 3 | URL = "https://glesys.com/" 4 | Code = "glesys" 5 | Since = "v0.5.0" 6 | 7 | Example = ''' 8 | GLESYS_API_USER=xxxxx \ 9 | GLESYS_API_KEY=yyyyy \ 10 | lego --email you@example.com --dns glesys -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | GLESYS_API_USER = "API user" 16 | GLESYS_API_KEY = "API key" 17 | [Configuration.Additional] 18 | GLESYS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 20)" 19 | GLESYS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 1200)" 20 | GLESYS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 21 | GLESYS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 22 | 23 | [Links] 24 | API = "https://github.com/GleSYS/API/wiki/API-Documentation" 25 | -------------------------------------------------------------------------------- /providers/dns/glesys/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "status": { 4 | "code": 200 5 | }, 6 | "record": { 7 | "recordid": 123 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/glesys/internal/fixtures/delete-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "status": { 4 | "code": 200 5 | }, 6 | "record": { 7 | "recordid": 123 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/glesys/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type addRecordRequest struct { 4 | DomainName string `json:"domainname"` 5 | Host string `json:"host"` 6 | Type string `json:"type"` 7 | Data string `json:"data"` 8 | TTL int `json:"ttl,omitempty"` 9 | } 10 | 11 | type deleteRecordRequest struct { 12 | RecordID int `json:"recordid"` 13 | } 14 | 15 | type apiResponse struct { 16 | Response Response `json:"response"` 17 | } 18 | 19 | type Response struct { 20 | Status Status `json:"status"` 21 | Record Record `json:"record"` 22 | } 23 | 24 | type Status struct { 25 | Code int `json:"code"` 26 | } 27 | 28 | type Record struct { 29 | RecordID int `json:"recordid"` 30 | } 31 | -------------------------------------------------------------------------------- /providers/dns/godaddy/internal/fixtures/error-extended.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "ACCESS_DENIED", 3 | "fields": [ 4 | { 5 | "code": "test", 6 | "message": "content", 7 | "path": "/foo", 8 | "pathRelated": "/bar" 9 | } 10 | ], 11 | "message": "Authenticated user is not allowed access" 12 | } 13 | -------------------------------------------------------------------------------- /providers/dns/godaddy/internal/fixtures/errors.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": "INVALID_BODY", 3 | "message": "Request body doesn't fulfill schema, see details in `fields`" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/godaddy/internal/fixtures/getrecords.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"_acme-challenge", 4 | "type":"TXT", 5 | "data":" ", 6 | "ttl":600 7 | }, 8 | { 9 | "name":"_acme-challenge.example", 10 | "type":"TXT", 11 | "data":"6rrai7-jm7l3PxL4WGmGoS6VMeefSHx24r-qCvUIOxU", 12 | "ttl":600 13 | }, 14 | { 15 | "name":"_acme-challenge.example", 16 | "type":"TXT", 17 | "data":"8Axt-PXQvjOVD2oi2YXqyyn8U5CDcC8P-BphlCxk3Ek", 18 | "ttl":600 19 | }, 20 | { 21 | "name":"_acme-challenge.lego", 22 | "type":"TXT", 23 | "data":" ", 24 | "ttl":600 25 | }, 26 | { 27 | "name":"_acme-challenge.lego", 28 | "type":"TXT", 29 | "data":"0Ad60wO_yxxJPFPb1deir6lQ37FPLeA02YCobo7Qm8A", 30 | "ttl":600 31 | }, 32 | { 33 | "name":"_acme-challenge.lego", 34 | "type":"TXT", 35 | "data":"acme", 36 | "ttl":600 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /providers/dns/googledomains/googledomains.toml: -------------------------------------------------------------------------------- 1 | Name = "Google Domains" 2 | Description = '''''' 3 | URL = "https://domains.google" 4 | Code = "googledomains" 5 | Since = "v4.11.0" 6 | 7 | Example = ''' 8 | GOOGLE_DOMAINS_ACCESS_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns googledomains -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | GOOGLE_DOMAINS_ACCESS_TOKEN = "Access token" 15 | [Configuration.Additional] 16 | GOOGLE_DOMAINS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | GOOGLE_DOMAINS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | GOOGLE_DOMAINS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 19 | 20 | [Links] 21 | GoClient = "https://github.com/googleapis/google-api-go-client" 22 | 23 | -------------------------------------------------------------------------------- /providers/dns/hetzner/hetzner.toml: -------------------------------------------------------------------------------- 1 | Name = "Hetzner" 2 | Description = '''''' 3 | URL = "https://hetzner.com" 4 | Code = "hetzner" 5 | Since = "v3.7.0" 6 | 7 | Example = ''' 8 | HETZNER_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ 9 | lego --email you@example.com --dns hetzner -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | HETZNER_API_KEY = "API key" 15 | [Configuration.Additional] 16 | HETZNER_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | HETZNER_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | HETZNER_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 19 | HETZNER_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://dns.hetzner.com/api-docs" 23 | -------------------------------------------------------------------------------- /providers/dns/hetzner/internal/fixtures/create_txt_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "record": { 3 | "type": "A", 4 | "id": "string", 5 | "created": "2020-05-08T10:49:18Z", 6 | "modified": "2020-05-08T10:49:18Z", 7 | "zone_id": "string", 8 | "name": "string", 9 | "value": "string", 10 | "ttl": 0 11 | } 12 | } -------------------------------------------------------------------------------- /providers/dns/hetzner/internal/fixtures/get_txt_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "records": [ 3 | { 4 | "type": "A", 5 | "id": "1a", 6 | "created": "2020-05-08T10:49:18Z", 7 | "modified": "2020-05-08T10:49:18Z", 8 | "zone_id": "zoneA", 9 | "name": "test", 10 | "value": "10.10.10.10", 11 | "ttl": 600 12 | }, 13 | { 14 | "type": "TXT", 15 | "id": "1b", 16 | "created": "2020-05-08T10:49:19Z", 17 | "modified": "2020-05-08T10:49:19Z", 18 | "zone_id": "zoneA", 19 | "name": "test1", 20 | "value": "txttxttxt", 21 | "ttl": 600 22 | } 23 | ], 24 | "meta": { 25 | "pagination": { 26 | "page": 1, 27 | "per_page": 20, 28 | "last_page": 1, 29 | "total_entries": 2 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /providers/dns/hostingde/hostingde.toml: -------------------------------------------------------------------------------- 1 | Name = "Hosting.de" 2 | Description = '''''' 3 | URL = "https://www.hosting.de/" 4 | Code = "hostingde" 5 | Since = "v1.1.0" 6 | 7 | Example = ''' 8 | HOSTINGDE_API_KEY=xxxxxxxx \ 9 | lego --email you@example.com --dns hostingde -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | HOSTINGDE_API_KEY = "API key" 15 | [Configuration.Additional] 16 | HOSTINGDE_ZONE_NAME = "Zone name in ACE format" 17 | HOSTINGDE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | HOSTINGDE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 19 | HOSTINGDE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 20 | HOSTINGDE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://www.hosting.de/api/#dns" 24 | 25 | 26 | -------------------------------------------------------------------------------- /providers/dns/hosttech/hosttech.toml: -------------------------------------------------------------------------------- 1 | Name = "Hosttech" 2 | Description = '''''' 3 | URL = "https://www.hosttech.eu/" 4 | Code = "hosttech" 5 | Since = "v4.5.0" 6 | 7 | Example = ''' 8 | HOSTTECH_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns hosttech -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | HOSTTECH_API_KEY = "API login" 15 | HOSTTECH_PASSWORD = "API password" 16 | [Configuration.Additional] 17 | HOSTTECH_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | HOSTTECH_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 19 | HOSTTECH_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 20 | HOSTTECH_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://api.ns1.hosttech.eu/api/documentation" 24 | -------------------------------------------------------------------------------- /providers/dns/hosttech/internal/fixtures/error-details.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "The given data was invalid.", 3 | "errors": { 4 | "type": [ 5 | "Darf nicht leer sein." 6 | ] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/hosttech/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Unauthenticated." 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/hosttech/internal/fixtures/record.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": 10, 4 | "type": "TXT", 5 | "name": "lego", 6 | "Text": "content", 7 | "ttl": 3600, 8 | "comment": "example" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/hosttech/internal/fixtures/zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": 10, 4 | "name": "user1.ch", 5 | "email": "test@hosttech.ch", 6 | "ttl": 10800, 7 | "nameserver": "ns1.hosttech.ch", 8 | "dnssec": false, 9 | "dnssec_email": "test@hosttech.ch", 10 | "ds_records": "[]", 11 | "records": "[{'id': 10, 'type': 'A', 'name': 'www', 'ipv4': '1.2.3.4', 'ttl': 3600, 'comment': 'my first record'}]" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/hosttech/internal/fixtures/zones.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "id": 10, 5 | "name": "user1.ch", 6 | "email": "test@hosttech.ch", 7 | "ttl": 10800, 8 | "nameserver": "ns1.hosttech.ch", 9 | "dnssec": false, 10 | "dnssec_email": "test@hosttech.ch" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/httpnet/httpnet.toml: -------------------------------------------------------------------------------- 1 | Name = "http.net" 2 | Description = '''''' 3 | URL = "https://www.http.net/" 4 | Code = "httpnet" 5 | Since = "v4.15.0" 6 | 7 | Example = ''' 8 | HTTPNET_API_KEY=xxxxxxxx \ 9 | lego --email you@example.com --dns httpnet -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | HTTPNET_API_KEY = "API key" 15 | [Configuration.Additional] 16 | HTTPNET_ZONE_NAME = "Zone name in ACE format" 17 | HTTPNET_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | HTTPNET_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 19 | HTTPNET_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 20 | HTTPNET_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://www.http.net/docs/api/#dns" 24 | 25 | 26 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/createRecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "123321qwerqwewqerq", 3 | "content": "value", 4 | "enabled": true 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/createRecordset.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "1234567890qwertyuiop", 3 | "name": "test.example.com.", 4 | "type": "TXT", 5 | "ttl": 3600 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/invalidPassport.json: -------------------------------------------------------------------------------- 1 | { 2 | "subject_id": "/iam/project/projectId/sa/serviceAccountId", 3 | "certificate_id": "certificateID", 4 | "issuer": "https://api.hyperone.com/v2/iam/project/projectId/sa/serviceAccountId" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/record.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "135128352183572dd", 4 | "content": "pns.hyperone.com. hostmaster.hyperone.com. 1 15 180 1209600 1800", 5 | "enabled": true 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/recordset.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "123456789abcd", 4 | "name": "example.com.", 5 | "type": "SOA", 6 | "ttl": 1800 7 | }, 8 | { 9 | "id": "123456789abcde", 10 | "name": "example.com.", 11 | "type": "NS", 12 | "ttl": 3600 13 | }, 14 | { 15 | "id": "123456789abcdf", 16 | "name": "example.com.", 17 | "type": "CNAME", 18 | "ttl": 3600 19 | } 20 | ] 21 | -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/fixtures/zones.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "zoneA", 4 | "name": "example.org", 5 | "dnsName": "example.org", 6 | "fqdn": "example.org.", 7 | "uri": "" 8 | }, 9 | { 10 | "id": "zoneB", 11 | "name": "example.com", 12 | "dnsName": "example.com", 13 | "fqdn": "example.com.", 14 | "uri": "" 15 | } 16 | ] -------------------------------------------------------------------------------- /providers/dns/hyperone/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type Recordset struct { 4 | RecordType string `json:"type"` 5 | Name string `json:"name"` 6 | TTL int `json:"ttl,omitempty"` 7 | ID string `json:"id,omitempty"` 8 | Record *Record `json:"record,omitempty"` 9 | } 10 | 11 | type Record struct { 12 | ID string `json:"id,omitempty"` 13 | Content string `json:"content"` 14 | Enabled bool `json:"enabled,omitempty"` 15 | } 16 | 17 | type Zone struct { 18 | ID string `json:"id"` 19 | Name string `json:"name"` 20 | DNSName string `json:"dnsName"` 21 | FQDN string `json:"fqdn"` 22 | URI string `json:"uri"` 23 | } 24 | -------------------------------------------------------------------------------- /providers/dns/internal/active24/fixtures/error_403.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "/errors/httpException", 3 | "status": 403, 4 | "title": "This action is unauthorized." 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/internal/active24/fixtures/error_422.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "/errors/validation", 3 | "status": 422, 4 | "title": "The given data was invalid.", 5 | "violations": [ 6 | { 7 | "propertyPath": "string", 8 | "errors": [ 9 | {} 10 | ] 11 | } 12 | ], 13 | "data": { 14 | "name": "Merlin" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/internal/active24/fixtures/error_v1.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "No username or password.", 3 | "code": 401 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/internal/active24/fixtures/records.json: -------------------------------------------------------------------------------- 1 | { 2 | "currentPage": 0, 3 | "rowsPerPage": 0, 4 | "totalPages": 0, 5 | "totalRecords": 0, 6 | "actions": { 7 | "additionalProp1": { 8 | "additionalProp1": {} 9 | }, 10 | "additionalProp2": { 11 | "additionalProp1": {} 12 | }, 13 | "additionalProp3": { 14 | "additionalProp1": {} 15 | } 16 | }, 17 | "data": [ 18 | { 19 | "id": 13, 20 | "name": "string", 21 | "content": "string", 22 | "ttl": 120, 23 | "priority": 1, 24 | "port": 443, 25 | "weight": 50 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /providers/dns/internal/active24/fixtures/services.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": 3 | [ 4 | { 5 | "id": 1111, 6 | "serviceName": ".sk doména", 7 | "status": "active", 8 | "name": "mydomain.sk", 9 | "createTime": 1374357600, 10 | "expireTime": 1405914526, 11 | "price": 12.3, 12 | "autoExtend": false 13 | }, 14 | { 15 | "id": 2222, 16 | "serviceName": "The Hosting", 17 | "status": "active", 18 | "name": "myname_1", 19 | "createTime": 1400145443, 20 | "expireTime": 1431702371, 21 | "price": 55.2, 22 | "autoExtend": false 23 | } 24 | ], 25 | "pager": 26 | { 27 | "page": 1, 28 | "pagesize": null, 29 | "items": 2 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /providers/dns/internal/ptr/types.go: -------------------------------------------------------------------------------- 1 | package ptr 2 | 3 | func Deref[T any](v *T) T { 4 | if v == nil { 5 | var zero T 6 | return zero 7 | } 8 | 9 | return *v 10 | } 11 | 12 | func Pointer[T any](v T) *T { return &v } 13 | -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/add_record.xml: -------------------------------------------------------------------------------- 1 | ]>OK: 2 | 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/add_record_error.xml: -------------------------------------------------------------------------------- 1 | ]> 2 | ERROR: No zone found for example.com -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/delete_record.xml: -------------------------------------------------------------------------------- 1 | ]>OK: 2 | 7 | 8 | 9 | 14 | -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/delete_record_error.xml: -------------------------------------------------------------------------------- 1 | ]> 2 | ERROR: No zone found for example.com -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/delete_record_nothing.xml: -------------------------------------------------------------------------------- 1 | ]>OK: 2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/find_records.xml: -------------------------------------------------------------------------------- 1 | ]>OK: 2 | 7 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /providers/dns/internal/rimuhosting/fixtures/find_records_empty.xml: -------------------------------------------------------------------------------- 1 | ]>OK: 2 | 7 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /providers/dns/internal/selectel/fixtures/domains.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 123, 3 | "name": "example.org" 4 | } -------------------------------------------------------------------------------- /providers/dns/internal/selectel/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "error description", 3 | "code": 400, 4 | "field": "field that the error occurred in" 5 | } -------------------------------------------------------------------------------- /providers/dns/internal/selectel/fixtures/list_records.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 123, 4 | "name": "example.com", 5 | "type": "TXT", 6 | "ttl": 60, 7 | "email": "email@example.com", 8 | "content": "txttxttxtA" 9 | }, 10 | { 11 | "id": 1234, 12 | "name": "example.org", 13 | "type": "TXT", 14 | "ttl": 60, 15 | "email": "email@example.org", 16 | "content": "txttxttxtB" 17 | }, 18 | { 19 | "id": 12345, 20 | "name": "example.net", 21 | "type": "TXT", 22 | "ttl": 60, 23 | "email": "email@example.net", 24 | "content": "txttxttxtC" 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /providers/dns/internal/useragent/useragent.go: -------------------------------------------------------------------------------- 1 | // Code generated by 'internal/releaser'; DO NOT EDIT. 2 | 3 | package useragent 4 | 5 | import ( 6 | "fmt" 7 | "net/http" 8 | "runtime" 9 | ) 10 | 11 | const ( 12 | // ourUserAgent is the User-Agent of this underlying library package. 13 | ourUserAgent = "goacme-lego/4.23.1" 14 | 15 | // ourUserAgentComment is part of the UA comment linked to the version status of this underlying library package. 16 | // values: detach|release 17 | // NOTE: Update this with each tagged release. 18 | ourUserAgentComment = "detach" 19 | ) 20 | 21 | // Get builds and returns the User-Agent string. 22 | func Get() string { 23 | return fmt.Sprintf("%s (%s; %s; %s)", ourUserAgent, ourUserAgentComment, runtime.GOOS, runtime.GOARCH) 24 | } 25 | 26 | // SetHeader sets the User-Agent header. 27 | func SetHeader(h http.Header) { 28 | h.Set("User-Agent", Get()) 29 | } 30 | -------------------------------------------------------------------------------- /providers/dns/internetbs/internal/fixtures/Domain_DnsRecord_Add_FAILURE.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactid": "67e4689073df2f153e7184aeb47a98f9", 3 | "status": "FAILURE", 4 | "message": "Invalid value \"www.example.com.\" for parameter \"fullrecordname\"!", 5 | "code": 100002 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/internetbs/internal/fixtures/Domain_DnsRecord_Add_SUCCESS.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactid": "548e3298130b492de23258634fd74481", 3 | "status": "SUCCESS" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/internetbs/internal/fixtures/Domain_DnsRecord_List_FAILURE.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactid": "5d554e0a5d145feb316b1805aae50706", 3 | "status": "FAILURE", 4 | "message": "The domain www.example.com does not have a supported extension!", 5 | "code": 100004 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/internetbs/internal/fixtures/Domain_DnsRecord_Remove_SUCCESS.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactid": "221a0fe572f0505194214405f395a847", 3 | "status": "SUCCESS" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/get_records.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "11af3414-ebba-11e9-8df5-66fbe8a334b4", 3 | "name": "example-zone.de", 4 | "type": "NATIVE", 5 | "records": [ 6 | { 7 | "id": "22af3414-abbe-9e11-5df5-66fbe8e334b4", 8 | "name": "string", 9 | "rootName": "string", 10 | "type": "A", 11 | "content": "string", 12 | "changeDate": "string", 13 | "ttl": 0, 14 | "prio": 0, 15 | "disabled": false 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/get_records_error.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "UNAUTHORIZED", 4 | "message": "The customer is not authorized to do this operation." 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/list_zones.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "11af3414-ebba-11e9-8df5-66fbe8a334b4", 4 | "name": "test.com", 5 | "type": "NATIVE" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/list_zones_error.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "UNAUTHORIZED", 4 | "message": "The customer is not authorized to do this operation." 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/remove_record_error.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "UNAUTHORIZED", 4 | "message": "The customer is not authorized to do this operation." 5 | }, 6 | { 7 | "code": "RECORD_NOT_FOUND", 8 | "message": "Record does not exist." 9 | }, 10 | { 11 | "code": "INTERNAL_SERVER_ERROR" 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /providers/dns/ionos/internal/fixtures/replace_records_error.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "INVALID_RECORD", 4 | "message": "string", 5 | "parameters": { 6 | "errorRecord": { 7 | "id": "string", 8 | "name": "string", 9 | "disabled": false, 10 | "rootName": "string", 11 | "changeDate": "string", 12 | "type": "A", 13 | "content": "string", 14 | "ttl": 0, 15 | "prio": 0 16 | }, 17 | "requiredFields": [ 18 | "string" 19 | ], 20 | "invalid": [ 21 | "string" 22 | ], 23 | "invalidFields": [ 24 | "string" 25 | ] 26 | } 27 | }, 28 | { 29 | "code": "UNAUTHORIZED", 30 | "message": "The customer is not authorized to do this operation." 31 | }, 32 | { 33 | "code": "INTERNAL_SERVER_ERROR" 34 | } 35 | ] -------------------------------------------------------------------------------- /providers/dns/ionos/ionos.toml: -------------------------------------------------------------------------------- 1 | Name = "Ionos" 2 | Description = '''''' 3 | URL = "https://ionos.com" 4 | Code = "ionos" 5 | Since = "v4.2.0" 6 | 7 | Example = ''' 8 | IONOS_API_KEY=xxxxxxxx \ 9 | lego --email you@example.com --dns ionos -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | IONOS_API_KEY = "API key `.` https://developer.hosting.ionos.com/docs/getstarted" 15 | [Configuration.Additional] 16 | IONOS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | IONOS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | IONOS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 19 | IONOS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://developer.hosting.ionos.com/docs/dns" 23 | -------------------------------------------------------------------------------- /providers/dns/ipv64/internal/fixtures/add_record-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "error", 3 | "status": "400 Bad Request", 4 | "add_record": "dns record already there" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/ipv64/internal/fixtures/add_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "success", 3 | "status": "201 Created", 4 | "add_record": "lego.ipv64.net" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/ipv64/internal/fixtures/del_record-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "error", 3 | "status": "403 Forbidden", 4 | "del_record": "del_record" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/ipv64/internal/fixtures/del_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": "success", 3 | "status": "202 Accepted", 4 | "del_record": "del_record" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/ipv64/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "401 Unauthorized", 3 | "info": "Unauthorized" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/ipv64/ipv64.toml: -------------------------------------------------------------------------------- 1 | Name = "IPv64" 2 | Description = '''''' 3 | URL = "https://ipv64.net/" 4 | Code = "ipv64" 5 | Since = "v4.13.0" 6 | 7 | Example = ''' 8 | IPV64_API_KEY=xxxxxx \ 9 | lego --email you@example.com --dns ipv64 -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | IPV64_API_KEY = "Account API Key" 15 | [Configuration.Additional] 16 | IPV64_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | IPV64_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | IPV64_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 19 | 20 | [Links] 21 | API = "https://ipv64.net/dyndns_updater_api" 22 | -------------------------------------------------------------------------------- /providers/dns/iwantmyname/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // Record represents a record. 4 | type Record struct { 5 | Hostname string `url:"hostname,omitempty"` 6 | Type string `url:"type,omitempty"` 7 | Value string `url:"value,omitempty"` 8 | TTL int `url:"ttl,omitempty"` 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/liara/internal/fixtures/RecordResponse.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "string", 3 | "data": { 4 | "id": "string", 5 | "name": "string", 6 | "type": "string", 7 | "ttl": 3600, 8 | "contents": [{ "text": "string" }] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/liara/internal/fixtures/RecordsResponse.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "string", 3 | "data": [ 4 | { 5 | "id": "string", 6 | "name": "string", 7 | "type": "string", 8 | "ttl": 3600, 9 | "contents": [{ "text": "string" }] 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /providers/dns/liara/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "statusCode": 401, 3 | "error": "Unauthorized", 4 | "message": "Invalid token missing header" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/liara/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type Content struct { 6 | Text string `json:"text,omitempty"` 7 | } 8 | 9 | type Record struct { 10 | ID string `json:"id,omitempty"` 11 | Name string `json:"name"` 12 | Type string `json:"type"` 13 | TTL int `json:"ttl"` 14 | Contents []Content `json:"contents"` 15 | } 16 | 17 | type Response[D any] struct { 18 | Status string `json:"status"` 19 | Data D `json:"data"` 20 | } 21 | 22 | type APIError struct { 23 | StatusCode int `json:"statusCode"` 24 | ErrorCode string `json:"error"` 25 | ErrorMessage string `json:"message"` 26 | } 27 | 28 | func (a APIError) Error() string { 29 | return fmt.Sprintf("%s: %s", a.ErrorCode, a.ErrorMessage) 30 | } 31 | -------------------------------------------------------------------------------- /providers/dns/liara/liara.toml: -------------------------------------------------------------------------------- 1 | Name = "Liara" 2 | Description = '''''' 3 | URL = "https://liara.ir" 4 | Code = "liara" 5 | Since = "v4.10.0" 6 | 7 | Example = ''' 8 | LIARA_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns liara -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | LIARA_API_KEY = "The API key" 15 | [Configuration.Additional] 16 | LIARA_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | LIARA_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | LIARA_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | LIARA_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://openapi.liara.ir/?urls.primaryName=DNS" 23 | -------------------------------------------------------------------------------- /providers/dns/limacity/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "invalid_resource", 3 | "errors": { 4 | "name": [ 5 | "muss ausgefüllt werden" 6 | ] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/limacity/internal/fixtures/get-domains.json: -------------------------------------------------------------------------------- 1 | { 2 | "domains": [ 3 | { 4 | "id": 123, 5 | "mode": "CREATE", 6 | "tld": "com", 7 | "domain": "example", 8 | "in_subscription": false, 9 | "auto_renew": false, 10 | "status": "ok", 11 | "unicode_fqdn": "example.com", 12 | "registered_at": "1970-01-01T00:00:00+00:00", 13 | "registered_until": "2000-01-01T00:00:00+00:00" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/limacity/internal/fixtures/get-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "records": [ 3 | { 4 | "id": 1234, 5 | "content": "ns1.lima-city.de", 6 | "name": "example.com", 7 | "ttl": 36000, 8 | "type": "NS", 9 | "priority": null 10 | }, 11 | { 12 | "id": 5678, 13 | "content": "\"foobar\"", 14 | "name": "_acme-challenge.example.com", 15 | "subdomain": "_acme-challenge", 16 | "ttl": 36000, 17 | "type": "TXT", 18 | "priority": null 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /providers/dns/limacity/internal/fixtures/ok.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/luadns/internal/fixtures/create_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 100, 3 | "name": "example.com.", 4 | "type": "MX", 5 | "content": "10 mail.example.com.", 6 | "ttl": 300, 7 | "zone_id": 1, 8 | "created_at": "2015-01-17T14:04:35.251785849Z", 9 | "updated_at": "2015-01-17T14:04:35.251785972Z" 10 | } -------------------------------------------------------------------------------- /providers/dns/luadns/internal/fixtures/delete_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 100, 3 | "name": "example.com.", 4 | "type": "MX", 5 | "content": "10 mail.example.com.", 6 | "ttl": 300, 7 | "zone_id": 1, 8 | "created_at": "2015-01-17T14:04:35.251785849Z", 9 | "updated_at": "2015-01-17T14:04:35.251785972Z" 10 | } -------------------------------------------------------------------------------- /providers/dns/luadns/internal/fixtures/list_zones.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "example.com", 5 | "synced": false, 6 | "queries_count": 0, 7 | "records_count": 3, 8 | "aliases_count": 0, 9 | "redirects_count": 0, 10 | "forwards_count": 0, 11 | "template_id": 0 12 | }, 13 | { 14 | "id": 2, 15 | "name": "example.net", 16 | "synced": false, 17 | "queries_count": 0, 18 | "records_count": 3, 19 | "aliases_count": 0, 20 | "redirects_count": 0, 21 | "forwards_count": 0, 22 | "template_id": 0 23 | } 24 | ] -------------------------------------------------------------------------------- /providers/dns/luadns/luadns.toml: -------------------------------------------------------------------------------- 1 | Name = "LuaDNS" 2 | Description = '''''' 3 | URL = "https://luadns.com" 4 | Code = "luadns" 5 | Since = "v3.7.0" 6 | 7 | Example = ''' 8 | LUADNS_API_USERNAME=youremail \ 9 | LUADNS_API_TOKEN=xxxxxxxx \ 10 | lego --email you@example.com --dns luadns -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | LUADNS_API_USERNAME = "Username (your email)" 16 | LUADNS_API_TOKEN = "API token" 17 | [Configuration.Additional] 18 | LUADNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 19 | LUADNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 20 | LUADNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 21 | LUADNS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://luadns.com/api.html" 25 | -------------------------------------------------------------------------------- /providers/dns/mailinabox/mailinabox.toml: -------------------------------------------------------------------------------- 1 | Name = "Mail-in-a-Box" 2 | Description = '''''' 3 | URL = "https://mailinabox.email" 4 | Code = "mailinabox" 5 | Since = "v4.16.0" 6 | 7 | Example = ''' 8 | MAILINABOX_EMAIL=user@example.com \ 9 | MAILINABOX_PASSWORD=yyyy \ 10 | MAILINABOX_BASE_URL=https://box.example.com \ 11 | lego --email you@example.com --dns mailinabox -d '*.example.com' -d example.com run 12 | ''' 13 | 14 | [Configuration] 15 | [Configuration.Credentials] 16 | MAILINABOX_EMAIL = "User email" 17 | MAILINABOX_PASSWORD = "User password" 18 | MAILINABOX_BASE_URL = "Base API URL (ex: https://box.example.com)" 19 | [Configuration.Additional] 20 | MAILINABOX_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 4)" 21 | MAILINABOX_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 22 | 23 | [Links] 24 | API = "https://mailinabox.email/api-docs.html" 25 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "detail": "Authentication credentials were not provided." 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/fixtures/error_bad_request.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "Invalid record format, Record should be in list." 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/fixtures/zone_record_create.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Record created successfully" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/fixtures/zone_record_delete.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Record deleted successfully" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/fixtures/zone_record_update.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Record updated successfully" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/manageengine/internal/identity.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "golang.org/x/oauth2/clientcredentials" 8 | ) 9 | 10 | const defaultAuthURL = "https://clouddns.manageengine.com/oauth2/token/" 11 | 12 | func createOAuthClient(ctx context.Context, clientID, clientSecret string) *http.Client { 13 | config := &clientcredentials.Config{ 14 | TokenURL: defaultAuthURL, 15 | ClientID: clientID, 16 | ClientSecret: clientSecret, 17 | } 18 | 19 | return config.Client(ctx) 20 | } 21 | -------------------------------------------------------------------------------- /providers/dns/metaregistrar/internal/fixtures/error-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "responseId": "1_0a407cb0634a56374ba80f863fda53ae37fd0042", 3 | "status": "error", 4 | "errorCode": "does_not_exist", 5 | "errorMessage": "This server does not exist" 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/metaregistrar/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "invalid_token", 3 | "message": "the supplied token is invalid" 4 | } -------------------------------------------------------------------------------- /providers/dns/metaregistrar/internal/fixtures/update-dns-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "responseId": "mapi1_cb46ad8790b62b76535bd3102bd282aec83b894c", 3 | "status": "ok", 4 | "message": "Command completed successfully" 5 | } 6 | -------------------------------------------------------------------------------- /providers/dns/metaregistrar/metaregistrar.toml: -------------------------------------------------------------------------------- 1 | Name = "Metaregistrar" 2 | Description = '''''' 3 | URL = "https://metaregistrar.com/" 4 | Code = "metaregistrar" 5 | Since = "v4.23.0" 6 | 7 | Example = ''' 8 | METAREGISTRAR_API_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns metaregistrar -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | METAREGISTRAR_API_TOKEN = "The API token" 15 | [Configuration.Additional] 16 | METAREGISTRAR_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | METAREGISTRAR_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | METAREGISTRAR_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | METAREGISTRAR_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://metaregistrar.dev/docu/metaapi/" 23 | -------------------------------------------------------------------------------- /providers/dns/mijnhost/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 400, 3 | "status_description": "Wrong request method" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/mijnhost/internal/fixtures/get-dns-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "status_description": "Request successful", 4 | "data": { 5 | "domain": "example.com", 6 | "records": [ 7 | { 8 | "type": "A", 9 | "name": "example.com.", 10 | "value": "135.226.123.12", 11 | "ttl": 900 12 | }, 13 | { 14 | "type": "AAAA", 15 | "name": "example.com.", 16 | "value": "2009:21d0:322:6100::5:c92b", 17 | "ttl": 900 18 | }, 19 | { 20 | "type": "MX", 21 | "name": "example.com.", 22 | "value": "10 mail.example.com.", 23 | "ttl": 900 24 | }, 25 | { 26 | "type": "TXT", 27 | "name": "example.com.", 28 | "value": "v=spf1 include:spf.mijn.host ~all", 29 | "ttl": 900 30 | } 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /providers/dns/mijnhost/internal/fixtures/list-domains.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "status_description": "Request successful", 4 | "data": { 5 | "domains": [ 6 | { 7 | "id": 1000, 8 | "domain": "example.com", 9 | "renewal_date": "2030-01-01", 10 | "status": "Active", 11 | "status_id": 1, 12 | "tags": [ 13 | "my-tag" 14 | ] 15 | } 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /providers/dns/mijnhost/internal/fixtures/update-dns-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "status_description": "DNS successfully updated" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/mittwald/internal/fixtures/dns-create-dns-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/mittwald/internal/fixtures/dns-get-dns-zone.json: -------------------------------------------------------------------------------- 1 | { 2 | "domain": "string", 3 | "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", 4 | "recordSet": { 5 | "cname": {}, 6 | "combinedARecords": {}, 7 | "mx": {}, 8 | "srv": {}, 9 | "txt": {} 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /providers/dns/mittwald/internal/fixtures/dns-list-dns-zones.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "domain": "string", 4 | "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", 5 | "recordSet": { 6 | "cname": {}, 7 | "combinedARecords": {}, 8 | "mx": {}, 9 | "srv": {}, 10 | "txt": {} 11 | } 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /providers/dns/mittwald/internal/fixtures/error-client.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "ValidationError", 3 | "message": "Validation failed", 4 | "validationErrors": [ 5 | { 6 | "message": "should be string", 7 | "path": ".address.street", 8 | "type": "format", 9 | "context": { 10 | "format": "email" 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /providers/dns/mittwald/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Something went wrong", 3 | "type": "InternalServerError" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/myaddr/internal/fixtures/error.txt: -------------------------------------------------------------------------------- 1 | invalid value for "key" 2 | -------------------------------------------------------------------------------- /providers/dns/myaddr/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type ACMEChallenge struct { 4 | Key string `json:"key"` 5 | Data string `json:"acme_challenge"` 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/mydnsjp/mydnsjp.toml: -------------------------------------------------------------------------------- 1 | Name = "MyDNS.jp" 2 | Description = '''''' 3 | URL = "https://www.mydns.jp" 4 | Code = "mydnsjp" 5 | Since = "v1.2.0" 6 | 7 | Example = ''' 8 | MYDNSJP_MASTER_ID=xxxxx \ 9 | MYDNSJP_PASSWORD=xxxxx \ 10 | lego --email you@example.com --dns mydnsjp -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | MYDNSJP_MASTER_ID = "Master ID" 16 | MYDNSJP_PASSWORD = "Password" 17 | [Configuration.Additional] 18 | MYDNSJP_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 19 | MYDNSJP_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 20 | MYDNSJP_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://www.mydns.jp/?MENU=030" 24 | -------------------------------------------------------------------------------- /providers/dns/mythicbeasts/internal/fixtures/delete-zoneszonerecords.json: -------------------------------------------------------------------------------- 1 | { 2 | "records_removed": 1, 3 | "message": "1 record removed" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/mythicbeasts/internal/fixtures/post-zoneszonerecords.json: -------------------------------------------------------------------------------- 1 | { 2 | "records_added": 1, 3 | "message": "1 record added" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/getHosts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | namecheap.domains.dns.getHosts 5 | 6 | 7 | 8 | 9 | 10 | 11 | SERVER-NAME 12 | +5 13 | 32.76 14 | 15 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/getHosts_errorBadAPIKey1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Key is invalid or API access has not been enabled 5 | 6 | 7 | 8 | PHX01SBAPI01 9 | --5:00 10 | 0 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/setHosts.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | namecheap.domains.dns.setHosts 5 | 6 | 7 | 8 | SERVER-NAME 9 | +5 10 | 32.76 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/setHosts_errorBadAPIKey1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | API Key is invalid or API access has not been enabled 5 | 6 | 7 | 8 | PHX01SBAPI01 9 | --5:00 10 | 0 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/setHosts_success1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | namecheap.domains.dns.setHosts 6 | 7 | 8 | 9 | 10 | 11 | PHX01SBAPI01 12 | --5:00 13 | 2.347 14 | 15 | -------------------------------------------------------------------------------- /providers/dns/namecheap/internal/fixtures/setHosts_success2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | namecheap.domains.dns.setHosts 6 | 7 | 8 | 9 | 10 | 11 | PHX01SBAPI01 12 | --5:00 13 | 2.347 14 | 15 | -------------------------------------------------------------------------------- /providers/dns/nearlyfreespeech/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "The API request could not be authenticated.", 3 | "debug": "The X-NFSN-Authentication header is not present." 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/nearlyfreespeech/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type Record struct { 6 | Name string `url:"name,omitempty"` 7 | Type string `url:"type,omitempty"` 8 | Data string `url:"data,omitempty"` 9 | TTL int `url:"ttl,omitempty"` 10 | } 11 | 12 | type APIError struct { 13 | Message string `json:"error"` 14 | Debug string `json:"debug"` 15 | } 16 | 17 | func (a APIError) Error() string { 18 | return fmt.Sprintf("%s: %s", a.Message, a.Debug) 19 | } 20 | -------------------------------------------------------------------------------- /providers/dns/netcup/netcup.toml: -------------------------------------------------------------------------------- 1 | Name = "Netcup" 2 | Description = '''''' 3 | URL = "https://www.netcup.eu/" 4 | Code = "netcup" 5 | Since = "v1.1.0" 6 | 7 | Example = ''' 8 | NETCUP_CUSTOMER_NUMBER=xxxx \ 9 | NETCUP_API_KEY=yyyy \ 10 | NETCUP_API_PASSWORD=zzzz \ 11 | lego --email you@example.com --dns netcup -d '*.example.com' -d example.com run 12 | ''' 13 | 14 | [Configuration] 15 | [Configuration.Credentials] 16 | NETCUP_CUSTOMER_NUMBER = "Customer number" 17 | NETCUP_API_KEY = "API key" 18 | NETCUP_API_PASSWORD = "API password" 19 | [Configuration.Additional] 20 | NETCUP_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 30)" 21 | NETCUP_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 900)" 22 | NETCUP_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 23 | 24 | [Links] 25 | API = "https://www.netcup-wiki.de/wiki/DNS_API" 26 | -------------------------------------------------------------------------------- /providers/dns/netlify/internal/fixtures/create_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "hostname": "test.example.org", 3 | "type": "TXT", 4 | "ttl": 300, 5 | "priority": null, 6 | "weight": null, 7 | "port": null, 8 | "flag": null, 9 | "tag": null, 10 | "id": "u6b4764216f272872ac0ff71", 11 | "site_id": null, 12 | "dns_zone_id": "u6b4336178f002e0a06bb0b6", 13 | "errors": [], 14 | "managed": false, 15 | "value": "txtxtxtxtxtxt" 16 | } -------------------------------------------------------------------------------- /providers/dns/netlify/internal/fixtures/get_records.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "hostname": "example.org", 4 | "type": "A", 5 | "ttl": 3600, 6 | "priority": null, 7 | "weight": null, 8 | "port": null, 9 | "flag": null, 10 | "tag": null, 11 | "id": "u6b433c15a27a2d79c6616d6", 12 | "site_id": null, 13 | "dns_zone_id": "u6b4336178f002e0a06bb0b6", 14 | "errors": [], 15 | "managed": false, 16 | "value": "10.10.10.10" 17 | }, 18 | { 19 | "hostname": "test.example.org", 20 | "type": "TXT", 21 | "ttl": 300, 22 | "priority": null, 23 | "weight": null, 24 | "port": null, 25 | "flag": null, 26 | "tag": null, 27 | "id": "u6b4764216f272872ac0ff71", 28 | "site_id": null, 29 | "dns_zone_id": "u6b4336178f002e0a06bb0b6", 30 | "errors": [], 31 | "managed": false, 32 | "value": "txtxtxtxtxtxt" 33 | } 34 | ] 35 | -------------------------------------------------------------------------------- /providers/dns/netlify/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // DNSRecord DNS record representation. 4 | type DNSRecord struct { 5 | ID string `json:"id,omitempty"` 6 | Hostname string `json:"hostname,omitempty"` 7 | TTL int `json:"ttl,omitempty"` 8 | Type string `json:"type,omitempty"` 9 | Value string `json:"value,omitempty"` 10 | } 11 | -------------------------------------------------------------------------------- /providers/dns/netlify/netlify.toml: -------------------------------------------------------------------------------- 1 | Name = "Netlify" 2 | Description = '''''' 3 | URL = "https://www.netlify.com" 4 | Code = "netlify" 5 | Since = "v3.7.0" 6 | 7 | Example = ''' 8 | NETLIFY_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns netlify -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | NETLIFY_TOKEN = "Token" 15 | [Configuration.Additional] 16 | NETLIFY_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | NETLIFY_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | NETLIFY_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 19 | NETLIFY_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://open-api.netlify.com/" 23 | -------------------------------------------------------------------------------- /providers/dns/nicmanager/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "message": "Not Found" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/nicmanager/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type Record struct { 6 | ID int `json:"id"` 7 | Name string `json:"name"` 8 | 9 | Type string `json:"type"` 10 | Content string `json:"content"` 11 | TTL int `json:"ttl"` 12 | } 13 | 14 | type Zone struct { 15 | Name string `json:"name"` 16 | Active bool `json:"active"` 17 | Records []Record `json:"records"` 18 | } 19 | 20 | type RecordCreateUpdate struct { 21 | Name string `json:"name"` 22 | Value string `json:"value"` 23 | TTL int `json:"ttl"` 24 | Type string `json:"type"` 25 | } 26 | 27 | type APIError struct { 28 | Message string `json:"message"` 29 | StatusCode int `json:"-"` 30 | } 31 | 32 | func (a APIError) Error() string { 33 | return fmt.Sprintf("%d: %s", a.StatusCode, a.Message) 34 | } 35 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/commit_POST.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/errors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | fail 4 | 5 | Access token expired or not found 6 | 7 | 8 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/record_DELETE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/records_PUT.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | 6 | @@NSns4-l2.nic.ru.ns4-l2.nic.ru. 7 | @@NSns8-l2.nic.ru.ns8-l2.nic.ru. 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/services_GET.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/zones_GET.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | 7 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /providers/dns/nicru/internal/fixtures/zones_all_GET.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | success 4 | 5 | 7 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /providers/dns/njalla/njalla.toml: -------------------------------------------------------------------------------- 1 | Name = "Njalla" 2 | Description = '''''' 3 | URL = "https://njal.la" 4 | Code = "njalla" 5 | Since = "v4.3.0" 6 | 7 | Example = ''' 8 | NJALLA_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns njalla -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | NJALLA_TOKEN = "API token" 15 | [Configuration.Additional] 16 | NJALLA_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | NJALLA_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | NJALLA_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 19 | NJALLA_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://njal.la/api/" 23 | -------------------------------------------------------------------------------- /providers/dns/nodion/nodion.toml: -------------------------------------------------------------------------------- 1 | Name = "Nodion" 2 | Description = '''''' 3 | URL = "https://www.nodion.com" 4 | Code = "nodion" 5 | Since = "v4.11.0" 6 | 7 | Example = ''' 8 | NODION_API_TOKEN="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns nodion -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | NODION_API_TOKEN = "The API token" 15 | [Configuration.Additional] 16 | NODION_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | NODION_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | NODION_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | NODION_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://www.nodion.com/en/docs/dns/api/" 23 | -------------------------------------------------------------------------------- /providers/dns/ns1/ns1.toml: -------------------------------------------------------------------------------- 1 | Name = "NS1" 2 | Description = '''''' 3 | URL = "https://ns1.com" 4 | Code = "ns1" 5 | Since = "v0.4.0" 6 | 7 | Example = ''' 8 | NS1_API_KEY=xxxx \ 9 | lego --email you@example.com --dns ns1 -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | NS1_API_KEY = "API key" 15 | [Configuration.Additional] 16 | NS1_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | NS1_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | NS1_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | NS1_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 20 | 21 | [Links] 22 | API = "https://ns1.com/api" 23 | GoClient = "https://github.com/ns1/ns1-go" 24 | -------------------------------------------------------------------------------- /providers/dns/otc/internal/fixtures/zones-recordsets_DELETE.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2c9eb155587228570158722b6ac30007", 3 | "name": "www.example.com.", 4 | "description": "This is an example record set.", 5 | "type": "A", 6 | "ttl": 300, 7 | "status": "PENDING_DELETE", 8 | "links": { 9 | "self": "https://Endpoint/v2/zones/2c9eb155587194ec01587224c9f90149/recordsets/2c9eb155587228570158722b6ac30007" 10 | }, 11 | "zone_id": "2c9eb155587194ec01587224c9f90149", 12 | "zone_name": "example.com.", 13 | "create_at": "2016-11-17T12:03:17.827", 14 | "update_at": "2016-11-17T12:56:03.827", 15 | "default": false, 16 | "project_id": "e55c6f3dc4e34c9f86353b664ae0e70c" 17 | } 18 | -------------------------------------------------------------------------------- /providers/dns/otc/internal/fixtures/zones-recordsets_GET_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "recordsets": [] 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/otc/internal/fixtures/zones-recordsets_POST.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "2c9eb155587228570158722b6ac30007", 3 | "name": "www.example.com.", 4 | "description": "This is an example record set.", 5 | "type": "A", 6 | "ttl": 300, 7 | "records": [ 8 | "192.168.10.1", 9 | "192.168.10.2" 10 | ], 11 | "status": "PENDING_CREATE", 12 | "links": { 13 | "self": "https://Endpoint/v2/zones/2c9eb155587194ec01587224c9f90149/recordsets/2c9eb155587228570158722b6ac30007" 14 | }, 15 | "zone_id": "2c9eb155587194ec01587224c9f90149", 16 | "zone_name": "example.com.", 17 | "create_at": "2016-11-17T12:03:17.827", 18 | "update_at": null, 19 | "default": false, 20 | "project_id": "e55c6f3dc4e34c9f86353b664ae0e70c" 21 | } 22 | -------------------------------------------------------------------------------- /providers/dns/otc/internal/fixtures/zones_GET_empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "zones": [] 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/otc/internal/identity_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "net/url" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | "github.com/stretchr/testify/require" 10 | ) 11 | 12 | func TestClient_Login(t *testing.T) { 13 | mock := NewDNSServerMock(t) 14 | mock.HandleAuthSuccessfully() 15 | 16 | client := NewClient("user", "secret", "example.com", "test") 17 | client.IdentityEndpoint, _ = url.JoinPath(mock.GetServerURL(), "/v3/auth/token") 18 | 19 | err := client.Login(context.Background()) 20 | require.NoError(t, err) 21 | 22 | serverURL, _ := url.Parse(mock.GetServerURL()) 23 | assert.Equal(t, serverURL.JoinPath("v2").String(), client.baseURL.String()) 24 | assert.Equal(t, fakeOTCToken, client.token) 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/pdns/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": "A human readable error message" 3 | } 4 | -------------------------------------------------------------------------------- /providers/dns/pdns/internal/fixtures/versions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "url": "/fooa", 4 | "version": 0 5 | }, 6 | { 7 | "url": "/foob", 8 | "version": 4 9 | }, 10 | { 11 | "url": "/fooc", 12 | "version": 2 13 | }, 14 | { 15 | "url": "/food", 16 | "version": 1 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/add-record-error.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | error 7 | 1015 8 | Domain does not exist. 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/add-record.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ok 7 | 4537 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/delete-record-error.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | error 7 | 1013 8 | Record does not exist 9 | 453899 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/delete-record.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ok 7 | 4537 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/get-site-error.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | error 7 | 1013 8 | Site does not exist 9 | bollox.com 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /providers/dns/plesk/internal/fixtures/global-error.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | error 5 | 1001 6 | You have entered incorrect username or password. 7 | 8 | 9 | -------------------------------------------------------------------------------- /providers/dns/rackspace/internal/fixtures/delete-records_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "failedItems" : { 3 | "faults" : [ { 4 | "message" : "Object not Found.", 5 | "code" : 404, 6 | "details" : "Domain ID: 2720150; Record ID: 111111111" 7 | }, { 8 | "message" : "Object not Found.", 9 | "code" : 404, 10 | "details" : "Domain ID: 2720150; Record ID: 222222222" 11 | } ] 12 | }, 13 | "message" : "One or more items could not be deleted.", 14 | "code" : 500, 15 | "details" : "See errors list for details." 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/rackspace/internal/fixtures/list-domains-by-name.json: -------------------------------------------------------------------------------- 1 | { 2 | "domains": [ 3 | { 4 | "name": "sub1.example.com", 5 | "id": "2725257", 6 | "comment": "1st sample subdomain", 7 | "updated": "2011-06-23T03:09:34.000+0000", 8 | "emailAddress": "sample@rackspace.com", 9 | "created": "2011-06-23T03:09:33.000+0000" 10 | } 11 | ], 12 | "totalEntries": 114 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/rackspace/rackspace.toml: -------------------------------------------------------------------------------- 1 | Name = "Rackspace" 2 | Description = '''''' 3 | URL = "https://www.rackspace.com/" 4 | Code = "rackspace" 5 | Since = "v0.4.0" 6 | 7 | Example = ''' 8 | RACKSPACE_USER=xxxx \ 9 | RACKSPACE_API_KEY=yyyy \ 10 | lego --email you@example.com --dns rackspace -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | RACKSPACE_USER = "API user" 16 | RACKSPACE_API_KEY = "API key" 17 | [Configuration.Additional] 18 | RACKSPACE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 3)" 19 | RACKSPACE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 20 | RACKSPACE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 300)" 21 | RACKSPACE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://developer.rackspace.com/docs/cloud-dns/v1/" 25 | -------------------------------------------------------------------------------- /providers/dns/rainyun/internal/fixtures/domains.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 0, 3 | "data": { 4 | "TotalRecords": 2, 5 | "Records": [ 6 | { 7 | "id": 1, 8 | "domain": "example.com" 9 | }, 10 | { 11 | "id": 2, 12 | "domain": "example.org" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/rainyun/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 30039, 3 | "message": "密钥认证错误或已失效" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/rainyun/internal/fixtures/records.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 0, 3 | "data": { 4 | "TotalRecords": 2, 5 | "Records": [ 6 | { 7 | "record_id": 1, 8 | "host": "_acme-challenge.foo.example.com", 9 | "type": "TXT", 10 | "TTL": 120, 11 | "value": "foo", 12 | "line": "DEFAULT" 13 | }, 14 | { 15 | "record_id": 2, 16 | "host": "_acme-challenge.bar.example.com", 17 | "type": "TXT", 18 | "TTL": 300, 19 | "value": "bar", 20 | "line": "DEFAULT" 21 | } 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /providers/dns/rainyun/rainyun.toml: -------------------------------------------------------------------------------- 1 | Name = "Rain Yun/雨云" 2 | Description = '''''' 3 | URL = "https://www.rainyun.com" 4 | Code = "rainyun" 5 | Since = "v4.21.0" 6 | 7 | Example = ''' 8 | RAINYUN_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns rainyun -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | RAINYUN_API_KEY = "API key" 15 | [Configuration.Additional] 16 | RAINYUN_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | RAINYUN_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 18 | RAINYUN_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | RAINYUN_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://www.apifox.cn/apidoc/shared-a4595cc8-44c5-4678-a2a3-eed7738dab03/api-151416609" 23 | -------------------------------------------------------------------------------- /providers/dns/rcodezero/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "failed", 3 | "message": "A human readable error message" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/rcodezero/internal/fixtures/rrsets-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "ok", 3 | "message": "RRsets updated" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/rcodezero/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type UpdateRRSet struct { 6 | Name string `json:"name"` 7 | Type string `json:"type"` 8 | ChangeType string `json:"changetype"` 9 | Records []Record `json:"records"` 10 | TTL int `json:"ttl"` 11 | } 12 | 13 | type Record struct { 14 | Content string `json:"content"` 15 | Disabled bool `json:"disabled"` 16 | } 17 | 18 | type APIResponse struct { 19 | Status string `json:"status"` 20 | Message string `json:"message"` 21 | } 22 | 23 | func (a APIResponse) Error() string { 24 | return fmt.Sprintf("%s: %s", a.Status, a.Message) 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/regfish/regfish.toml: -------------------------------------------------------------------------------- 1 | Name = "Regfish" 2 | Description = '''''' 3 | URL = "https://regfish.de/" 4 | Code = "regfish" 5 | Since = "v4.20.0" 6 | 7 | Example = ''' 8 | REGFISH_API_KEY="xxxxxxxxxxxxxxxxxxxxx" \ 9 | lego --email you@example.com --dns regfish -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | REGFISH_API_KEY = "API key" 15 | [Configuration.Additional] 16 | REGFISH_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | REGFISH_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | REGFISH_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | REGFISH_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://regfish.readme.io/" 23 | GoClient = "https://github.com/regfish/regfish-dnsapi-go" 24 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/invalid_field.conf: -------------------------------------------------------------------------------- 1 | key "example.com" { 2 | algorithm; 3 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 4 | }; 5 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/invalid_key.conf: -------------------------------------------------------------------------------- 1 | key { 2 | algorithm hmac-sha256; 3 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 4 | }; 5 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/mising_algo.conf: -------------------------------------------------------------------------------- 1 | key "example.com" { 2 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 3 | }; 4 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/missing_secret.conf: -------------------------------------------------------------------------------- 1 | key "example.com" { 2 | algorithm hmac-sha256; 3 | }; 4 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/sample.conf: -------------------------------------------------------------------------------- 1 | key "example.com" { 2 | algorithm hmac-sha256; 3 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 4 | }; 5 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/text_after.conf: -------------------------------------------------------------------------------- 1 | key "example.com" { 2 | algorithm hmac-sha256; 3 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 4 | }; 5 | 6 | key "example.org" { 7 | algorithm hmac-sha512; 8 | secret "v6CkK3gop6HXj4+dcWiLXLGSYKVY5J1cTMjDsdl/Ah9B8aWfTgjwFBoHHyiHWSyvwWPDuEIRs2Pqm8nedca4+g=="; 9 | }; 10 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/fixtures/text_before.conf: -------------------------------------------------------------------------------- 1 | foo { 2 | bar example; 3 | }; 4 | 5 | key "example.com" { 6 | algorithm hmac-sha256; 7 | secret "TCG5A6/lOHUGbW0e/9RYYbzWDFMlj1pIxCvybLBayBg="; 8 | }; 9 | -------------------------------------------------------------------------------- /providers/dns/rfc2136/internal/readme.md: -------------------------------------------------------------------------------- 1 | # TSIG Key File 2 | 3 | How to generate example: 4 | 5 | ```console 6 | $ docker run --rm -it -v $(pwd):/app -w /app alpine sh 7 | /app # apk add bind 8 | /app # tsig-keygen example.com > sample1.conf 9 | /app # tsig-keygen -a hmac-sha512 example.com > sample2.conf 10 | ``` 11 | -------------------------------------------------------------------------------- /providers/dns/rimuhosting/rimuhosting.toml: -------------------------------------------------------------------------------- 1 | Name = "RimuHosting" 2 | Description = '''''' 3 | URL = "https://rimuhosting.com" 4 | Code = "rimuhosting" 5 | Since = "v0.3.5" 6 | 7 | Example = ''' 8 | RIMUHOSTING_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns rimuhosting -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | RIMUHOSTING_API_KEY = "User API key" 15 | [Configuration.Additional] 16 | RIMUHOSTING_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | RIMUHOSTING_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | RIMUHOSTING_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | RIMUHOSTING_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://rimuhosting.com/dns/dyndns.jsp" 23 | -------------------------------------------------------------------------------- /providers/dns/safedns/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type AddRecordResponse struct { 4 | Data struct { 5 | ID int `json:"id"` 6 | } `json:"data"` 7 | Meta struct { 8 | Location string `json:"location"` 9 | } 10 | } 11 | 12 | type Record struct { 13 | Name string `json:"name"` 14 | Type string `json:"type"` 15 | Content string `json:"content"` 16 | TTL int `json:"ttl"` 17 | } 18 | 19 | type APIError struct { 20 | Message string `json:"message"` 21 | } 22 | 23 | func (a APIError) Error() string { 24 | return a.Message 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/safedns/safedns.toml: -------------------------------------------------------------------------------- 1 | Name = "UKFast SafeDNS" 2 | Description = '''''' 3 | URL = "https://www.ukfast.co.uk/dns-hosting.html" 4 | Code = "safedns" 5 | Since = "v4.6.0" 6 | 7 | Example = ''' 8 | SAFEDNS_AUTH_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns safedns -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | SAFEDNS_AUTH_TOKEN = "Authentication token" 15 | [Configuration.Additional] 16 | SAFEDNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | SAFEDNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | SAFEDNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | SAFEDNS_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://developers.ukfast.io/documentation/safedns" 23 | -------------------------------------------------------------------------------- /providers/dns/scaleway/scaleway.toml: -------------------------------------------------------------------------------- 1 | Name = "Scaleway" 2 | Description = '''''' 3 | URL = "https://developers.scaleway.com/" 4 | Code = "scaleway" 5 | Since = "v3.4.0" 6 | 7 | Example = ''' 8 | SCW_SECRET_KEY=xxxxxxx-xxxxx-xxxx-xxx-xxxxxx \ 9 | lego --email you@example.com --dns scaleway -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | SCW_SECRET_KEY = "Secret key" 15 | SCW_PROJECT_ID = "Project to use (optional)" 16 | [Configuration.Additional] 17 | SCW_ACCESS_KEY = "Access key" 18 | SCW_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)" 19 | SCW_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 20 | SCW_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 21 | 22 | [Links] 23 | API = "https://developers.scaleway.com/en/products/domain/dns/api/" 24 | -------------------------------------------------------------------------------- /providers/dns/selectel/selectel.toml: -------------------------------------------------------------------------------- 1 | Name = "Selectel" 2 | Description = '''''' 3 | URL = "https://kb.selectel.com/" 4 | Code = "selectel" 5 | Since = "v1.2.0" 6 | 7 | Example = ''' 8 | SELECTEL_API_TOKEN=xxxxx \ 9 | lego --email you@example.com --dns selectel -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | SELECTEL_API_TOKEN = "API token" 15 | [Configuration.Additional] 16 | SELECTEL_BASE_URL = "API endpoint URL" 17 | SELECTEL_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | SELECTEL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 19 | SELECTEL_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 20 | SELECTEL_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://kb.selectel.com/23136054.html" 24 | -------------------------------------------------------------------------------- /providers/dns/selfhostde/internal/readme.md: -------------------------------------------------------------------------------- 1 | # SelfHost.(de|eu) 2 | 3 | SelfHost doesn't provide an official API documentation and there are no endpoints for create a TXT record or delete a TXT record. 4 | 5 | ## More 6 | 7 | The documentation found at https://kirk.selfhost.de/cgi-bin/selfhost?p=document&name=api (PDF) describes the DynDNS/ddns API endpoint and is not used by our client. 8 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/dns_record-remove.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 0, 3 | "message": "" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/dns_record-store.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 0, 3 | "title": "", 4 | "message": "Record DNS aggiunto con successo", 5 | "data": { 6 | "id": "2255674" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/domain-details.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 0, 3 | "message": "", 4 | "data": { 5 | "id": 123, 6 | "domain_name": "example.com", 7 | "domain_name_ascii": "example.com" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 2, 3 | "title": "", 4 | "message": "Token di autorizzazione non valido", 5 | "data": null 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/purchase-details.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 0, 3 | "message": "", 4 | "data": { 5 | "ID": 123, 6 | "name": "example", 7 | "domain_id": 456 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/shellrent/internal/fixtures/purchase.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": 0, 3 | "message": "", 4 | "data": [ 5 | 2018, 6 | 10039, 7 | 10128 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/shellrent/shellrent.toml: -------------------------------------------------------------------------------- 1 | Name = "Shellrent" 2 | Description = '''''' 3 | URL = "https://www.shellrent.com/" 4 | Code = "shellrent" 5 | Since = "v4.16.0" 6 | 7 | Example = ''' 8 | SHELLRENT_USERNAME=xxxx \ 9 | SHELLRENT_TOKEN=yyyy \ 10 | lego --email you@example.com --dns shellrent -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | SHELLRENT_USERNAME = "Username" 16 | SHELLRENT_TOKEN = "Token" 17 | [Configuration.Additional] 18 | SHELLRENT_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)" 19 | SHELLRENT_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 300)" 20 | SHELLRENT_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 21 | SHELLRENT_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://api.shellrent.com/section/api2" 25 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/add_record.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "message": "success", 4 | "record": { 5 | "id": 123456789 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/bad_auth_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 400, 3 | "message": "Invalid account authorization" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/bad_zone_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 404, 3 | "message": "Unknown or invalid product reference" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/get_records.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "message": "success", 4 | "records": [ 5 | { 6 | "record_id": 1, 7 | "name": "@", 8 | "ttl": 3600, 9 | "data": "ns1.simply.com", 10 | "type": "NS", 11 | "priority": 0 12 | }, 13 | { 14 | "record_id": 2, 15 | "name": "@", 16 | "ttl": 3600, 17 | "data": "ns2.simply.com", 18 | "type": "NS", 19 | "priority": 0 20 | }, 21 | { 22 | "record_id": 3, 23 | "name": "@", 24 | "ttl": 3600, 25 | "data": "ns3.simply.com", 26 | "type": "NS", 27 | "priority": 0 28 | }, 29 | { 30 | "record_id": 4, 31 | "name": "@", 32 | "ttl": 3600, 33 | "data": "ns4.simply.com", 34 | "type": "NS", 35 | "priority": 0 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/invalid_record_id_error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 404, 3 | "message": "Unknown DNS record" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/simply/internal/fixtures/success.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": 200, 3 | "message": "success" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/simply/simply.toml: -------------------------------------------------------------------------------- 1 | Name = "Simply.com" 2 | Description = '''''' 3 | URL = "https://www.simply.com/en/domains/" 4 | Code = "simply" 5 | Since = "v4.4.0" 6 | 7 | Example = ''' 8 | SIMPLY_ACCOUNT_NAME=xxxxxx \ 9 | SIMPLY_API_KEY=yyyyyy \ 10 | lego --email you@example.com --dns simply -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | SIMPLY_ACCOUNT_NAME = "Account name" 16 | SIMPLY_API_KEY = "API key" 17 | [Configuration.Additional] 18 | SIMPLY_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)" 19 | SIMPLY_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 300)" 20 | SIMPLY_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 21 | SIMPLY_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://www.simply.com/en/docs/api/" 25 | -------------------------------------------------------------------------------- /providers/dns/sonic/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type APIResponse struct { 4 | Message string `json:"message"` 5 | Result int `json:"result"` 6 | } 7 | 8 | // Record holds the Sonic API representation of a Domain Record. 9 | type Record struct { 10 | UserID string `json:"userid"` 11 | APIKey string `json:"apikey"` 12 | Hostname string `json:"hostname"` 13 | Value string `json:"value"` 14 | TTL int `json:"ttl"` 15 | Type string `json:"type"` 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/spaceship/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "detail": "^$", 3 | "data": [ 4 | { 5 | "field": "name", 6 | "details": "The domain name contains invalid characters" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/spaceship/internal/fixtures/get-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "type": "A", 5 | "name": "@", 6 | "ttl": 3600, 7 | "group": { 8 | "type": "custom" 9 | } 10 | } 11 | ], 12 | "total": 100 13 | } 14 | -------------------------------------------------------------------------------- /providers/dns/stackpath/internal/identity.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "context" 5 | "net/http" 6 | 7 | "golang.org/x/oauth2/clientcredentials" 8 | ) 9 | 10 | const defaultAuthURL = "https://gateway.stackpath.com/identity/v1/oauth2/token" 11 | 12 | func createOAuthClient(ctx context.Context, clientID, clientSecret string) *http.Client { 13 | config := &clientcredentials.Config{ 14 | TokenURL: defaultAuthURL, 15 | ClientID: clientID, 16 | ClientSecret: clientSecret, 17 | } 18 | 19 | return config.Client(ctx) 20 | } 21 | -------------------------------------------------------------------------------- /providers/dns/technitium/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "zone": { 4 | "name": "example.com", 5 | "type": "Primary", 6 | "internal": false, 7 | "dnssecStatus": "SignedWithNSEC", 8 | "disabled": false 9 | }, 10 | "addedRecord": { 11 | "disabled": false, 12 | "name": "example.com", 13 | "type": "A", 14 | "ttl": 3600, 15 | "rData": { 16 | "ipAddress": "3.3.3.3" 17 | }, 18 | "dnssecStatus": "Unknown", 19 | "lastUsedOn": "0001-01-01T00:00:00" 20 | } 21 | }, 22 | "status": "ok" 23 | } 24 | -------------------------------------------------------------------------------- /providers/dns/technitium/internal/fixtures/delete-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": {}, 3 | "status": "ok" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/technitium/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "status": "error", 3 | "errorMessage": "error message", 4 | "stackTrace": "application stack trace", 5 | "innerErrorMessage": "inner exception message" 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/internal/fixtures/createDomainDNSRecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "dns_record": { 3 | "type": "TXT", 4 | "id": 123, 5 | "data": { 6 | "priority": 0, 7 | "subdomain": "example.com", 8 | "value": "w6uP8Tcg6K2QR905Rms8iXTlksL6OD1KOWBxTK7wxPI" 9 | } 10 | }, 11 | "response_id": "15095f25-aac3-4d60-a788-96cb5136f186" 12 | } 13 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/internal/fixtures/error_bad_request.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "status_code": 400, 4 | "message": "Value must be a number conforming to the specified constraints", 5 | "error_code": "bad_request", 6 | "response_id": "15095f25-aac3-4d60-a788-96cb5136f186" 7 | 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/internal/fixtures/error_unauthorized.json: -------------------------------------------------------------------------------- 1 | { 2 | "status_code": 401, 3 | "message": "Unauthorized", 4 | "error_code": "unauthorized", 5 | "response_id": "15095f25-aac3-4d60-a788-96cb5136f186" 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/internal/readme.md: -------------------------------------------------------------------------------- 1 | There is an [official API client](https://github.com/timeweb-cloud/sdk-go) but this client is completely broken: 2 | - the code is generated and the module name is `github.com/GIT_USER_ID/GIT_REPO_ID` 3 | - the code contains redeclared constants 4 | - Even with fixes to the module name and the redeclared constants, the module doesn't compile. 5 | 6 | https://github.com/timeweb-cloud/sdk-go/pull/1 7 | 8 | So, for now, this API client is unusable. 9 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type DNSRecord struct { 6 | ID int `json:"id,omitempty"` 7 | Type string `json:"type,omitempty"` 8 | Value string `json:"value,omitempty"` 9 | SubDomain string `json:"subdomain,omitempty"` 10 | } 11 | 12 | type CreateRecordResponse struct { 13 | DNSRecord *DNSRecord `json:"dns_record,omitempty"` 14 | } 15 | 16 | type ErrorResponse struct { 17 | StatusCode int `json:"status_code,omitempty"` 18 | ErrorCode string `json:"error_code,omitempty"` 19 | Message string `json:"message,omitempty"` 20 | ResponseID string `json:"response_id,omitempty"` 21 | } 22 | 23 | func (a ErrorResponse) Error() string { 24 | return fmt.Sprintf("%d: %s (%s) [%s]", a.StatusCode, a.Message, a.ErrorCode, a.ResponseID) 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/timewebcloud/timewebcloud.toml: -------------------------------------------------------------------------------- 1 | Name = "Timeweb Cloud" 2 | Description = '''''' 3 | URL = "https://timeweb.cloud/" 4 | Code = "timewebcloud" 5 | Since = "v4.20.0" 6 | 7 | Example = ''' 8 | TIMEWEBCLOUD_AUTH_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns timewebcloud -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | TIMEWEBCLOUD_AUTH_TOKEN = "Authentication token" 15 | [Configuration.Additional] 16 | TIMEWEBCLOUD_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | TIMEWEBCLOUD_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | TIMEWEBCLOUD_HTTP_TIMEOUT = "API request timeout in seconds (Default: 10)" 19 | 20 | [Links] 21 | API = "https://timeweb.cloud/api-docs" 22 | -------------------------------------------------------------------------------- /providers/dns/transip/fixtures/private.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-acme/lego/476f9ed9100ed25d7a4c37eb6946d7831e3a9e09/providers/dns/transip/fixtures/private.key -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/DELETE_dns-records_done.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "303030", 4 | "type": "queue-job", 5 | "attributes": { 6 | "job_type": "dns-record", 7 | "status": "done" 8 | }, 9 | "relationships": { 10 | "owner": { 11 | "data": { 12 | "id": "505050", 13 | "type": "customer" 14 | } 15 | } 16 | }, 17 | "links": { 18 | "self": "https://api.variomedia.de/queue-jobs/303030", 19 | "object": "https://api.variomedia.de/dns-records/212121" 20 | } 21 | }, 22 | "links": { 23 | "self": "https://api.variomedia.de/queue-jobs/303030" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/DELETE_dns-records_pending.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "303030", 4 | "type": "queue-job", 5 | "attributes": { 6 | "status": "pending" 7 | }, 8 | "links": { 9 | "queue-job": "https://api.variomedia.de/queue-jobs/303030" 10 | } 11 | }, 12 | "links": { 13 | "self": "https://api.variomedia.de/dns-records/212121" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/GET_dns-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "20202020", 4 | "type": "dns-record", 5 | "links": { 6 | "self": "https://api.variomedia.de/dns-records/20202020" 7 | }, 8 | "attributes": { 9 | "record_type": "TXT", 10 | "fqdn": "my-test-record.example.com", 11 | "fqdn_ace": "my-test-record.example.com", 12 | "name": "my-test-record", 13 | "name_ace": "my-test-record", 14 | "domain": "example.com", 15 | "data": "test", 16 | "ttl": 300 17 | } 18 | }, 19 | "links": { 20 | "self": "https://api.variomedia.de/dns-records" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/GET_queue-jobs.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "id": "171717", 4 | "type": "queue-job", 5 | "links": { 6 | "self": "https://api.variomedia.de/queue-jobs/171717", 7 | "object": "https://api.variomedia.de/dns-records/212121" 8 | }, 9 | "attributes": { 10 | "job_type": "dns-record", 11 | "status": "done" 12 | }, 13 | "relationships": { 14 | "owner": { 15 | "data": { 16 | "id": "505050", 17 | "type": "customer" 18 | } 19 | } 20 | } 21 | }, 22 | "links": { 23 | "self": "https://api.variomedia.de/queue-jobs/171717" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/POST_dns-records.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "type": "queue-job", 4 | "id": "18181818", 5 | "attributes": { 6 | "status": "pending" 7 | }, 8 | "links": { 9 | "queue-job": "https://api.variomedia.de/queue-jobs/18181818", 10 | "dns-record": "https://api.variomedia.de/dns-records/19191919" 11 | } 12 | }, 13 | "links": { 14 | "self": "https://api.variomedia.de/dns-records" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/variomedia/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "errors": [ 3 | { 4 | "status": "401", 5 | "title": "The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.", 6 | "id": "unauthorized" 7 | } 8 | ], 9 | "links": { 10 | "self": "https://api.variomedia.de/dns-records" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /providers/dns/vegadns/vegadns.toml: -------------------------------------------------------------------------------- 1 | Name = "VegaDNS" 2 | Description = '''''' 3 | URL = "https://github.com/shupp/VegaDNS-API" 4 | Code = "vegadns" 5 | Since = "v1.1.0" 6 | 7 | Example = '''''' 8 | 9 | [Configuration] 10 | [Configuration.Credentials] 11 | SECRET_VEGADNS_KEY = "API key" 12 | SECRET_VEGADNS_SECRET = "API secret" 13 | VEGADNS_URL = "API endpoint URL" 14 | [Configuration.Additional] 15 | VEGADNS_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 60)" 16 | VEGADNS_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 720)" 17 | VEGADNS_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 10)" 18 | 19 | [Links] 20 | API = "https://github.com/shupp/VegaDNS-API" 21 | GoClient = "https://github.com/OpenDNS/vegadns2client" 22 | 23 | -------------------------------------------------------------------------------- /providers/dns/vercel/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type Record struct { 6 | ID string `json:"id,omitempty"` 7 | Slug string `json:"slug,omitempty"` 8 | Name string `json:"name,omitempty"` 9 | Type string `json:"type,omitempty"` 10 | Value string `json:"value,omitempty"` 11 | TTL int `json:"ttl,omitempty"` 12 | } 13 | 14 | // CreateRecordResponse represents a response from Vercel's API after making a DNS record. 15 | type CreateRecordResponse struct { 16 | UID string `json:"uid"` 17 | Updated int `json:"updated,omitempty"` 18 | } 19 | 20 | type APIErrorResponse struct { 21 | Error *APIError `json:"error"` 22 | } 23 | 24 | type APIError struct { 25 | Code string `json:"code"` 26 | Message string `json:"message"` 27 | } 28 | 29 | func (a APIError) Error() string { 30 | return fmt.Sprintf("%s: %s", a.Code, a.Message) 31 | } 32 | -------------------------------------------------------------------------------- /providers/dns/vercel/vercel.toml: -------------------------------------------------------------------------------- 1 | Name = "Vercel" 2 | Description = '''''' 3 | URL = "https://vercel.com" 4 | Code = "vercel" 5 | Since = "v4.7.0" 6 | 7 | Example = ''' 8 | VERCEL_API_TOKEN=xxxxxx \ 9 | lego --email you@example.com --dns vercel -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | VERCEL_API_TOKEN = "Authentication token" 15 | [Configuration.Additional] 16 | VERCEL_TEAM_ID = "Team ID (ex: team_xxxxxxxxxxxxxxxxxxxxxxxx)" 17 | VERCEL_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 5)" 18 | VERCEL_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 19 | VERCEL_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 20 | VERCEL_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://vercel.com/docs/rest-api#endpoints/dns" 24 | -------------------------------------------------------------------------------- /providers/dns/versio/internal/fixtures/README.md: -------------------------------------------------------------------------------- 1 | 2 | Note: the snippets from the API documentation are wrong: 3 | invalid field type (ex: prio, TTL), and JSON format contains errors. 4 | 5 | So the files inside the fixtures have been partially adapted to fit the reality. 6 | -------------------------------------------------------------------------------- /providers/dns/versio/internal/fixtures/get-domain-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "code": 401, 4 | "message": "You are not authorized to access this resource. Did you supply the correct credentials and have you IP (xxxx:xxxx:xxx:xxxx:xxxx:xxxx:xxxx:xxxx) whitelisted for API use?" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/versio/internal/fixtures/update-domain-error.json: -------------------------------------------------------------------------------- 1 | { 2 | "error": { 3 | "code": 401, 4 | "message": "You are not authorized to access this resource. Did you supply the correct credentials and have you IP (xxxx:xxxx:xxx:xxxx:xxxx:xxxx:xxxx:xxxx) whitelisted for API use?" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/versio/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type DomainInfoResponse struct { 6 | DomainInfo DomainInfo `json:"domainInfo"` 7 | } 8 | 9 | type DomainInfo struct { 10 | DNSRecords []Record `json:"dns_records"` 11 | } 12 | 13 | type Record struct { 14 | Type string `json:"type,omitempty"` 15 | Name string `json:"name,omitempty"` 16 | Value string `json:"value,omitempty"` 17 | Priority int `json:"prio,omitempty"` 18 | TTL int `json:"ttl,omitempty"` 19 | } 20 | 21 | type ErrorResponse struct { 22 | Message ErrorMessage `json:"error"` 23 | } 24 | 25 | type ErrorMessage struct { 26 | Code int `json:"code,omitempty"` 27 | Message string `json:"message,omitempty"` 28 | } 29 | 30 | func (e ErrorMessage) Error() string { 31 | return fmt.Sprintf("%d: %s", e.Code, e.Message) 32 | } 33 | -------------------------------------------------------------------------------- /providers/dns/versio/versio_mock_test.go: -------------------------------------------------------------------------------- 1 | package versio 2 | 3 | const tokenResponseMock = ` 4 | { 5 | "access_token":"699dd4ff-e381-46b8-8bf8-5de49dd56c1f", 6 | "token_type":"bearer", 7 | "expires_in":3600 8 | } 9 | ` 10 | 11 | const tokenFailToFindZoneMock = `{"error":{"code":401,"message":"ObjectDoesNotExist|Domain not found"}}` 12 | 13 | const tokenFailToCreateTXTMock = `{"error":{"code":400,"message":"ProcessError|DNS record invalid type _acme-challenge.example.eu. TST"}}` 14 | -------------------------------------------------------------------------------- /providers/dns/vinyldns/fixtures/recordSetsListAll-empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "maxItems": 100, 3 | "nameSort": "ASC", 4 | "recordNameFilter": "_acme-challenge.host", 5 | "recordSets": [] 6 | } 7 | -------------------------------------------------------------------------------- /providers/dns/vinyldns/fixtures/recordSetsListAll.json: -------------------------------------------------------------------------------- 1 | { 2 | "maxItems": 100, 3 | "nameSort": "ASC", 4 | "recordNameFilter": "_acme-challenge.host", 5 | "recordSets": [ 6 | { 7 | "accessLevel": "Delete", 8 | "account": "", 9 | "created": "2021-03-04T00:51:43Z", 10 | "fqdn": "_acme-challenge.host.example.com.", 11 | "id": "30000000-0000-0000-0000-000000000000", 12 | "name": "_acme-challenge.host", 13 | "records": [ 14 | { 15 | "text": "O2UTPYgIzRNt5N27EVcNKDxv6goSF7ru3zi3chZXKUw" 16 | } 17 | ], 18 | "status": "Active", 19 | "ttl": 30, 20 | "type": "TXT", 21 | "updated": "2021-03-04T00:51:43Z", 22 | "zoneId": "00000000-0000-0000-0000-000000000000" 23 | } 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /providers/dns/vinyldns/fixtures/zoneByName.json: -------------------------------------------------------------------------------- 1 | { 2 | "zone": { 3 | "accessLevel": "Delete", 4 | "account": "system", 5 | "acl": { 6 | "rules": [] 7 | }, 8 | "adminGroupId": "40000000-0000-0000-0000-000000000000", 9 | "adminGroupName": "OpsTeam", 10 | "created": "2020-07-15T21:15:36Z", 11 | "email": "Ops@company.invalid", 12 | "id": "00000000-0000-0000-0000-000000000000", 13 | "latestSync": "2020-07-15T21:15:36Z", 14 | "name": "example.com.", 15 | "shared": false, 16 | "status": "Active", 17 | "updated": "2021-03-03T18:02:47Z" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /providers/dns/vkcloud/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type DNSZone struct { 4 | UUID string `json:"uuid,omitempty"` 5 | Tenant string `json:"tenant,omitempty"` 6 | SoaPrimaryDNS string `json:"soa_primary_dns,omitempty"` 7 | SoaAdminEmail string `json:"soa_admin_email,omitempty"` 8 | SoaSerial int `json:"soa_serial,omitempty"` 9 | SoaRefresh int `json:"soa_refresh,omitempty"` 10 | SoaRetry int `json:"soa_retry,omitempty"` 11 | SoaExpire int `json:"soa_expire,omitempty"` 12 | SoaTTL int `json:"soa_ttl,omitempty"` 13 | Zone string `json:"zone,omitempty"` 14 | Status string `json:"status,omitempty"` 15 | } 16 | 17 | type DNSTXTRecord struct { 18 | UUID string `json:"uuid,omitempty"` 19 | Name string `json:"name,omitempty"` 20 | DNS string `json:"dns,omitempty"` 21 | Content string `json:"content,omitempty"` 22 | TTL int `json:"ttl,omitempty"` 23 | } 24 | -------------------------------------------------------------------------------- /providers/dns/vscale/vscale.toml: -------------------------------------------------------------------------------- 1 | Name = "Vscale" 2 | Description = '''''' 3 | URL = "https://vscale.io/" 4 | Code = "vscale" 5 | Since = "v2.0.0" 6 | 7 | Example = ''' 8 | VSCALE_API_TOKEN=xxxxx \ 9 | lego --email you@example.com --dns vscale -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | VSCALE_API_TOKEN = "API token" 15 | [Configuration.Additional] 16 | VSCALE_BASE_URL = "API endpoint URL" 17 | VSCALE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | VSCALE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 19 | VSCALE_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 20 | VSCALE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://developers.vscale.io/documentation/api/v1/#api-Domains_Records" 24 | -------------------------------------------------------------------------------- /providers/dns/vultr/vultr.toml: -------------------------------------------------------------------------------- 1 | Name = "Vultr" 2 | Description = '''''' 3 | URL = "https://www.vultr.com/" 4 | Code = "vultr" 5 | Since = "v0.3.1" 6 | 7 | Example = ''' 8 | VULTR_API_KEY=xxxxx \ 9 | lego --email you@example.com --dns vultr -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | VULTR_API_KEY = "API key" 15 | [Configuration.Additional] 16 | VULTR_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | VULTR_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | VULTR_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 120)" 19 | VULTR_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://www.vultr.com/api/#dns" 23 | GoClient = "https://github.com/vultr/govultr" 24 | -------------------------------------------------------------------------------- /providers/dns/webnames/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "result": "ERROR", 3 | "details": "zone_manager_unavailable" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/webnames/internal/fixtures/ok.json: -------------------------------------------------------------------------------- 1 | { 2 | "result": "OK", 3 | "details": 1 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/webnames/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "encoding/json" 4 | 5 | type APIResponse struct { 6 | Result string `json:"result"` 7 | Details json.RawMessage `json:"details"` 8 | } 9 | -------------------------------------------------------------------------------- /providers/dns/wedos/internal/fixtures/dns-domain-commit.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "code": 1000, 4 | "result": "OK", 5 | "timestamp": 1291192534, 6 | "svTRID": "1291192534.6326.32542.1", 7 | "command": "dns-domain-commit" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/wedos/internal/fixtures/dns-row-add.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "code": 1000, 4 | "result": "OK", 5 | "timestamp": 1291210501, 6 | "svTRID": "1291210501.7672.19698.1", 7 | "command": "dns-row-add" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/wedos/internal/fixtures/dns-row-delete.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "code": 1000, 4 | "result": "OK", 5 | "timestamp": 1291370821, 6 | "svTRID": "1291370821.1702.7371.1", 7 | "command": "dns-row-delete" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/wedos/internal/fixtures/dns-row-update.json: -------------------------------------------------------------------------------- 1 | { 2 | "response": { 3 | "code": 1000, 4 | "result": "OK", 5 | "timestamp": 1291370821, 6 | "svTRID": "1291370821.1702.7371.1", 7 | "command": "dns-row-update" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/westcn/internal/fixtures/adddnsrecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "result": 200, 3 | "clientid": "54880064508339547956", 4 | "data": { 5 | "id": 123456 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /providers/dns/westcn/internal/fixtures/deldnsrecord.json: -------------------------------------------------------------------------------- 1 | { 2 | "result": 200, 3 | "clientid": "54880064508339547956" 4 | } 5 | -------------------------------------------------------------------------------- /providers/dns/westcn/internal/fixtures/error.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/go-acme/lego/476f9ed9100ed25d7a4c37eb6946d7831e3a9e09/providers/dns/westcn/internal/fixtures/error.json -------------------------------------------------------------------------------- /providers/dns/westcn/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import "fmt" 4 | 5 | type APIResponse[T any] struct { 6 | Result int `json:"result,omitempty"` 7 | ClientID string `json:"clientid,omitempty"` 8 | Message string `json:"msg,omitempty"` 9 | ErrorCode int `json:"errcode,omitempty"` 10 | Data T `json:"data,omitempty"` 11 | } 12 | 13 | func (a APIResponse[T]) Error() string { 14 | return fmt.Sprintf("%d: %s (%d)", a.ErrorCode, a.Message, a.Result) 15 | } 16 | 17 | type Record struct { 18 | Domain string `url:"domain,omitempty"` 19 | Host string `url:"host,omitempty"` 20 | Type string `url:"type,omitempty"` 21 | Value string `url:"value,omitempty"` 22 | TTL int `url:"ttl,omitempty"` // 60~86400 seconds 23 | Priority int `url:"level,omitempty"` 24 | } 25 | 26 | type RecordID struct { 27 | ID int `json:"id,omitempty"` 28 | } 29 | -------------------------------------------------------------------------------- /providers/dns/westcn/westcn.toml: -------------------------------------------------------------------------------- 1 | Name = "West.cn/西部数码" 2 | Description = '''''' 3 | URL = "https://www.west.cn" 4 | Code = "westcn" 5 | Since = "v4.21.0" 6 | 7 | Example = ''' 8 | WESTCN_USERNAME="xxx" \ 9 | WESTCN_PASSWORD="yyy" \ 10 | lego --email you@example.com --dns westcn -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | WESTCN_USERNAME = "Username" 16 | WESTCN_PASSWORD = "API password" 17 | [Configuration.Additional] 18 | WESTCN_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 10)" 19 | WESTCN_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 120)" 20 | WESTCN_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 60)" 21 | WESTCN_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://www.west.cn/CustomerCenter/doc/domain_v2.html" 25 | -------------------------------------------------------------------------------- /providers/dns/yandex/yandex.toml: -------------------------------------------------------------------------------- 1 | Name = "Yandex PDD" 2 | Description = ''' 3 | ''' 4 | URL = "https://pdd.yandex.com" 5 | Code = "yandex" 6 | Since = "v3.7.0" 7 | 8 | Example = ''' 9 | YANDEX_PDD_TOKEN= \ 10 | lego --email you@example.com --dns yandex -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | YANDEX_PDD_TOKEN = "Basic authentication username" 16 | [Configuration.Additional] 17 | YANDEX_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 18 | YANDEX_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 19 | YANDEX_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 21600)" 20 | YANDEX_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 21 | 22 | [Links] 23 | API = "https://yandex.com/dev/domain/doc/concepts/api-dns.html" 24 | -------------------------------------------------------------------------------- /providers/dns/yandex360/internal/fixtures/add-record.json: -------------------------------------------------------------------------------- 1 | { 2 | "recordID": 789465, 3 | "name": "foo", 4 | "text": "_acme-challenge", 5 | "ttl": 60, 6 | "type": "txtxtxt" 7 | } 8 | -------------------------------------------------------------------------------- /providers/dns/yandex360/internal/fixtures/delete-record.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /providers/dns/yandex360/internal/fixtures/error.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 123, 3 | "details": [ 4 | { 5 | "@type": "foo" 6 | } 7 | ], 8 | "message": "bar" 9 | } 10 | -------------------------------------------------------------------------------- /providers/dns/zoneee/internal/fixtures/create-txt-record.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource_url": "string", 4 | "destination": "server.example.com", 5 | "id": "123", 6 | "name": "prefix.example.com", 7 | "delete": true, 8 | "modify": true 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /providers/dns/zoneee/internal/fixtures/get-txt-records.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource_url": "string", 4 | "destination": "server.example.com", 5 | "id": "123", 6 | "name": "prefix.example.com", 7 | "delete": true, 8 | "modify": true 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /providers/dns/zoneee/internal/types.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | type TXTRecord struct { 4 | // Identifier (identificator) 5 | ID string `json:"id,omitempty"` 6 | // Hostname 7 | Name string `json:"name"` 8 | // TXT content value 9 | Destination string `json:"destination"` 10 | // Can this record be deleted 11 | Delete bool `json:"delete,omitempty"` 12 | // Can this record be modified 13 | Modify bool `json:"modify,omitempty"` 14 | // API url to get this entity 15 | ResourceURL string `json:"resource_url,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /providers/dns/zoneee/zoneee.toml: -------------------------------------------------------------------------------- 1 | Name = "Zone.ee" 2 | Description = '''''' 3 | URL = "https://www.zone.ee/" 4 | Code = "zoneee" 5 | Since = "v2.1.0" 6 | 7 | Example = ''' 8 | ZONEEE_API_USER=xxxxx \ 9 | ZONEEE_API_KEY=yyyyy \ 10 | lego --email you@example.com --dns zoneee -d '*.example.com' -d example.com run 11 | ''' 12 | 13 | [Configuration] 14 | [Configuration.Credentials] 15 | ZONEEE_API_USER = "API user" 16 | ZONEEE_API_KEY = "API key" 17 | [Configuration.Additional] 18 | ZONEEE_ENDPOINT = "API endpoint URL" 19 | ZONEEE_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 5)" 20 | ZONEEE_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 300)" 21 | ZONEEE_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 22 | 23 | [Links] 24 | API = "https://api.zone.eu/v2" 25 | -------------------------------------------------------------------------------- /providers/dns/zonomi/zonomi.toml: -------------------------------------------------------------------------------- 1 | Name = "Zonomi" 2 | Description = '''''' 3 | URL = "https://zonomi.com" 4 | Code = "zonomi" 5 | Since = "v3.5.0" 6 | 7 | Example = ''' 8 | ZONOMI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \ 9 | lego --email you@example.com --dns zonomi -d '*.example.com' -d example.com run 10 | ''' 11 | 12 | [Configuration] 13 | [Configuration.Credentials] 14 | ZONOMI_API_KEY = "User API key" 15 | [Configuration.Additional] 16 | ZONOMI_POLLING_INTERVAL = "Time between DNS propagation check in seconds (Default: 2)" 17 | ZONOMI_PROPAGATION_TIMEOUT = "Maximum waiting time for DNS propagation in seconds (Default: 60)" 18 | ZONOMI_TTL = "The TTL of the TXT record used for the DNS challenge in seconds (Default: 3600)" 19 | ZONOMI_HTTP_TIMEOUT = "API request timeout in seconds (Default: 30)" 20 | 21 | [Links] 22 | API = "https://zonomi.com/app/dns/dyndns.jsp" 23 | -------------------------------------------------------------------------------- /providers/http/memcached/README.md: -------------------------------------------------------------------------------- 1 | # Memcached http provider 2 | 3 | Publishes challenges into memcached where they can be retrieved by nginx. Allows 4 | specifying multiple memcached servers and the responses will be published to all 5 | of them, making it easier to verify when your domain is hosted on a cluster of 6 | servers. 7 | 8 | Example nginx config: 9 | 10 | ``` 11 | location /.well-known/acme-challenge/ { 12 | set $memcached_key "$uri"; 13 | memcached_pass 127.0.0.1:11211; 14 | } 15 | ``` 16 | -------------------------------------------------------------------------------- /registration/user.go: -------------------------------------------------------------------------------- 1 | package registration 2 | 3 | import ( 4 | "crypto" 5 | ) 6 | 7 | // User interface is to be implemented by users of this library. 8 | // It is used by the client type to get user specific information. 9 | type User interface { 10 | GetEmail() string 11 | GetRegistration() *Resource 12 | GetPrivateKey() crypto.PrivateKey 13 | } 14 | -------------------------------------------------------------------------------- /registration/user_test.go: -------------------------------------------------------------------------------- 1 | package registration 2 | 3 | import ( 4 | "crypto" 5 | "crypto/rsa" 6 | ) 7 | 8 | type mockUser struct { 9 | email string 10 | regres *Resource 11 | privatekey *rsa.PrivateKey 12 | } 13 | 14 | func (u mockUser) GetEmail() string { return u.email } 15 | func (u mockUser) GetRegistration() *Resource { return u.regres } 16 | func (u mockUser) GetPrivateKey() crypto.PrivateKey { return u.privatekey } 17 | --------------------------------------------------------------------------------