Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DNS provider for Lima-City #2248

Merged
merged 24 commits into from
Aug 29, 2024
Merged

Add DNS provider for Lima-City #2248

merged 24 commits into from
Aug 29, 2024

Conversation

ldez
Copy link
Member

@ldez ldez commented Aug 27, 2024

  • adds a description to your PR
  • have a homogeneous design with the other providers
  • add tests (units)
  • add tests ("live")
  • add a provider descriptor
  • generate CLI help, documentation, and readme.
  • be able to do: (and put the output of this command to a comment)
    make build
    rm -rf .lego
    
    LIMACITY_API_KEY=yyyy \
    ./dist/lego -m your@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
    Note the wildcard domain is important.
  • pass the linter
  • do go mod tidy

Ping @feroxib, can you run the command (with your domain, email, and credentials)?

-> #2248

Closes #2247

@feroxib
Copy link

feroxib commented Aug 27, 2024

Ping @ldez have a bit of trouble here

steps:
cloned https://github.com/ldez/lego.git

cd ./lego
make build
rm -rf .lego
LIMACITY_API_KEY=yyyy \
./dist/lego -m your@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run 

and got

2024/08/27 14:17:56 No key found for account my@email.com. Generating a P256 key.
2024/08/27 14:17:56 Saved key to /home/me/Downloads/lego/.lego/accounts/acme-staging-v02.api.letsencrypt.org/my@email.com/keys/my@email.com.key
2024/08/27 14:17:57 unrecognized DNS provider: limacity

please let me know if i did something wrong because i dont see it xD

@feroxib
Copy link

feroxib commented Aug 27, 2024

also double checked the api key and its registered as dns.admin, domain.admin

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

Do you check out my branch?

git switch feat/lima-city 

@feroxib
Copy link

feroxib commented Aug 27, 2024

oh wow yeah i kinda never realized that taking the clone url on github doesnt actually give you the branch youre checking out in the browser...
sorry for that

@feroxib
Copy link

feroxib commented Aug 27, 2024

LIMACITY_API_KEY=<redacted_api_key> ./dist/lego -m my@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
2024/08/27 14:34:09 No key found for account my@email.com. Generating a P256 key.
2024/08/27 14:34:09 Saved key to /home/me/Documents/git/lego/.lego/accounts/acme-staging-v02.api.letsencrypt.org/my@email.com/keys/my@email.com.key
2024/08/27 14:34:10 Please review the TOS at https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf
Do you accept the TOS? Y/n
y
2024/08/27 14:34:12 [INFO] acme: Registering account for my@email.com
!!!! HEADS UP !!!!

Your account credentials have been saved in your Let's Encrypt
configuration directory at "/home/me/Documents/git/lego/.lego/accounts".

You should make a secure backup of this folder now. This
configuration directory will also contain certificates and
private keys obtained from Let's Encrypt so making regular
backups of this folder is ideal.
2024/08/27 14:34:13 [INFO] [*.example.com, example.com] acme: Obtaining bundled SAN certificate
2024/08/27 14:34:15 [INFO] [*.example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13756805883
2024/08/27 14:34:15 [INFO] [example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13756805893
2024/08/27 14:34:15 [INFO] [*.example.com] acme: use dns-01 solver
2024/08/27 14:34:15 [INFO] [example.com] acme: Could not find solver for: tls-alpn-01
2024/08/27 14:34:15 [INFO] [example.com] acme: Could not find solver for: http-01
2024/08/27 14:34:15 [INFO] [example.com] acme: use dns-01 solver
2024/08/27 14:34:15 [INFO] [*.example.com] acme: Preparing to solve DNS-01
2024/08/27 14:34:15 [INFO] [example.com] acme: Preparing to solve DNS-01
2024/08/27 14:34:15 [INFO] [*.example.com] acme: Cleaning DNS-01 challenge
2024/08/27 14:34:15 [WARN] [*.example.com] acme: cleaning up failed: liara: unknown domain ID for '_acme-challenge.example.com.' '7xxxxxx-Fxxxxxxxxxxxxxxxx_zxxxxxxxxxxxxxxx' 
2024/08/27 14:34:15 [INFO] [example.com] acme: Cleaning DNS-01 challenge
2024/08/27 14:34:15 [WARN] [example.com] acme: cleaning up failed: liara: unknown domain ID for '_acme-challenge.example.com.' 'exxxxxxxxxxxx-x-xx_gxxxxxxxxxxxxxxx-Rxxxxxxxxxx' 
2024/08/27 14:34:16 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13756805883
2024/08/27 14:34:17 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13756805893
2024/08/27 14:34:17 Could not obtain certificates:
        error: one or more domains had a problem:
[*.example.com] [*.example.com] acme: error presenting token: limacity: get domains: unable to unmarshal response: [status code: 200] body: {"domains":[{"id":2****,"mode":"CREATE","tld":"com","domain":"example","in_subscription":false,"auto_renew":false,"status":"ok","unicode_fqdn":"example.com","registered_at":"1970-01-01T00:00:00+00:00","registered_until":"2000-01-01T00:00:00+00:00","renew_price":00.01}]} error: json: cannot unmarshal number into Go struct field Domain.domains.id of type string
[example.com] [example.com] acme: error presenting token: limacity: get domains: unable to unmarshal response: [status code: 200] body: {"domains":[{"id":2****,"mode":"CREATE","tld":"com","domain":"example","in_subscription":false,"auto_renew":false,"status":"ok","unicode_fqdn":"example.com","registered_at":"1970-01-01T00:00:00+00:00","registered_until":"2000-01-01T00:00:00+00:00","renew_price":00.01}]} error: json: cannot unmarshal number into Go struct field Domain.domains.id of type string

@feroxib
Copy link

feroxib commented Aug 27, 2024

idk what this error
unable to unmarshal response
exactly means but it looks like the json error
cannot unmarshal number into go struct field
is the underlying one right?

to clarify the values that i redacted

  • id: some integer in the range of the 20000
  • mode: string
  • tld: string
  • domain: string
  • in_subscription: bool
  • auto_renew: bool
  • status: string?
  • unicode_fqdn: string
  • registered at: date
  • registered until: date
  • renew_price: float

hope that helps

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

I fixed the problem, can you try again?

@feroxib
Copy link

feroxib commented Aug 27, 2024

2024/08/27 15:07:38 Could not obtain certificates:
        error: one or more domains had a problem:
[*.example.com] [*.example.com] acme: error presenting token: limacity: add record: unexpected status code: [status code: 400] body: {"status":400,"error":"Bad Request"}
[example.com] [example.com] acme: error presenting token: limacity: add record: unexpected status code: [status code: 400] body: {"status":400,"error":"Bad Request"}

@feroxib
Copy link

feroxib commented Aug 27, 2024

whats the deal with error presenting token?

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

I fixed the problem, can you try again?

@feroxib
Copy link

feroxib commented Aug 27, 2024

almost got it xD

LIMACITY_API_KEY=<api-key> ./dist/lego -m my@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
2024/08/27 15:26:33 [INFO] [*.example.com, example.com] acme: Obtaining bundled SAN certificate
2024/08/27 15:26:35 [INFO] [*.example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757327693
2024/08/27 15:26:35 [INFO] [example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757327703
2024/08/27 15:26:35 [INFO] [*.example.com] acme: use dns-01 solver
2024/08/27 15:26:35 [INFO] [example.com] acme: Could not find solver for: tls-alpn-01
2024/08/27 15:26:35 [INFO] [example.com] acme: Could not find solver for: http-01
2024/08/27 15:26:35 [INFO] [example.com] acme: use dns-01 solver
2024/08/27 15:26:35 [INFO] [*.example.com] acme: Preparing to solve DNS-01
2024/08/27 15:26:36 [INFO] [example.com] acme: Preparing to solve DNS-01
2024/08/27 15:26:36 [INFO] [*.example.com] acme: Trying to solve DNS-01
2024/08/27 15:26:36 [INFO] [*.example.com] acme: Checking DNS record propagation. [nameservers=127.0.0.53:53]
2024/08/27 15:26:38 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2024/08/27 15:26:38 [INFO] [*.example.com] acme: Waiting for DNS record propagation.
..........
2024/08/27 15:27:37 [INFO] [*.example.com] acme: Waiting for DNS record propagation.
2024/08/27 15:27:39 [INFO] [example.com] acme: Trying to solve DNS-01
2024/08/27 15:27:39 [INFO] [example.com] acme: Checking DNS record propagation. [nameservers=127.0.0.53:53]
2024/08/27 15:27:41 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2024/08/27 15:27:41 [INFO] [example.com] acme: Waiting for DNS record propagation.
..........
2024/08/27 15:28:40 [INFO] [example.com] acme: Waiting for DNS record propagation.
2024/08/27 15:28:42 [INFO] [*.example.com] acme: Cleaning DNS-01 challenge
2024/08/27 15:28:42 [WARN] [*.example.com] acme: cleaning up failed: limacity: get records: unable to unmarshal response: [status code: 200] body: {"records":[...............,{"id":2******,"name":"example.com","subdomain":false,"type":"TXT","content":"\"w**************\"","priority":null,"ttl":3600},{"id":2*****,"name":"example.com","subdomain":false,"type":"TXT","content":"\"1*****************\"","priority":null,"ttl":3600}]} error: json: cannot unmarshal number into Go struct field Record.records.id of type string 
2024/08/27 15:28:42 [INFO] [example.com] acme: Cleaning DNS-01 challenge
2024/08/27 15:28:42 [WARN] [example.com] acme: cleaning up failed: limacity: get records: unable to unmarshal response: [status code: 200] body: {"records":[.................,{"id":2******,"name":"example.com","subdomain":false,"type":"TXT","content":"\"w**************\"","priority":null,"ttl":3600},{"id":2*****,"name":"example.com","subdomain":false,"type":"TXT","content":"\"1*****************\"","priority":null,"ttl":3600}]} error: json: cannot unmarshal number into Go struct field Record.records.id of type string 
2024/08/27 15:28:43 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757327693
2024/08/27 15:28:43 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757327703
2024/08/27 15:28:43 Could not obtain certificates:
        error: one or more domains had a problem:
[*.example.com] propagation: time limit exceeded: last error: NS ns3.lima-city.de. did not return the expected TXT record [fqdn: _acme-challenge.example.com., value: \"w**************]: none
[example.com] propagation: time limit exceeded: last error: NS ns1.lima-city.de. did not return the expected TXT record [fqdn: _acme-challenge.example.com., value: \"1****************]: none

so what i checked in addition.
the entries in the provider dashboard are txt records directly registered with example.com

but as i understand should be _acme-challenge.example.com

why idk tho...

@feroxib
Copy link

feroxib commented Aug 27, 2024

btw thank you for showing me that 3x ` creates code blocks

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

I think it's a propagation issue, can you try to add LIMACITY_PROPAGATION_TIMEOUT=120 (for 2 minutes)?

LIMACITY_PROPAGATION_TIMEOUT=120 LIMACITY_API_KEY=<api-key> ./dist/lego -m my@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

Wait there is also a type error, I will fix that.

@feroxib
Copy link

feroxib commented Aug 27, 2024

image

shouldnt they be under _acme-challenge.example.com?

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

FYI I wrote the implementation only based on the API doc, which contains no explanation of what exactly is an endpoint, some endpoints are missing, and the schema can be wrong.

For example, the JSONSchema inside the API documentation says that:

{
  "required": ["errors", "status"],
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "example": "invalid_resource",
      "isRequired": true
    },
    "errors": {
      "type": "object",
      "description": "An object containing all validation errors. The parameter name is the key, the value is an array of strings",
      "example": {"name": ["muss ausgefüllt werden"]},
      "isRequired": true
    }
  }
}
  • status -> string
  • errors -> object

From your logs:

{"status":400,"error":"Bad Request"}
  • status -> integer
  • error -> string

Another example is the endpoint to get records:

{
  "required": ["records"],
  "type": "object",
  "properties": {
    "records": {
      "type": "array",
      "items": {
        "required": ["content", "id", "name", "subdomain", "ttl", "type"],
        "type": "object",
        "properties": {
          "id": {"type": "string", "example": "1234"},
          "name": {"type": "string", "example": "example.com"},
          "subdomain": {"type": "string"},
          "type": {"type": "string", "example": "NS"},
          "content": {"type": "string", "example": "ns1.lima-city.de"},
          "ttl": {"type": "integer", "example": 3600}
        }
      }
    }
  }
}

id -> string

From your logs:

{"records":[.................,{"id":2******,"name":"example.com","subdomain":false,"type":"TXT","content":"\"w**************\"","priority":null,"ttl":3600},{"id":2*****,"name":"example.com","subdomain":false,"type":"TXT","content":"\"1*****************\"","priority":null,"ttl":3600}]} 

id -> int

I think that Lima City should improve its API and its documentation.

@feroxib
Copy link

feroxib commented Aug 27, 2024

fully agree xD

@feroxib
Copy link

feroxib commented Aug 27, 2024

thank you for doing all that work
hope you like coffee ;)

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

I fixed all the ID types, let's go try again 😄

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

Another example, with the endpoint to add records:

{
  "required": ["nameserver_record"],
  "type": "object",
  "properties": {
    "nameserver_record": {
      "required": ["content", "name", "subdomain", "ttl", "type"],
      "type": "object",
      "properties": {
        "name": {"type": "string", "example": "example.com"},
        "type": {"type": "string", "example": "NS"},
        "content": {"type": "string", "example": "ns1.lima-city.de"},
        "ttl": {"type": "integer", "example": 3600},
        "priority": {"type": "string", "example": "10"}
      }
    }
  }
}

required says "content", "name", "subdomain", "ttl", "type" but subdomain is not defined inside the properties...

I don't know if subdomain really exists, and how it works.

So I'm sorry to be forced to do this try-and-fix cycle.

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

WTF, from your logs:

{"records":[.................,{"id":2******,"name":"example.com","subdomain":false,"type":"TXT","content":"\"w**************\"","priority":null,"ttl":3600},{"id":2*****,"name":"example.com","subdomain":false,"type":"TXT","content":"\"1*****************\"","priority":null,"ttl":3600}]}

subdomain is a boolean???

@feroxib
Copy link

feroxib commented Aug 27, 2024

yes it looks like its a boolean

testing didnt work rn either.

i still get entries at lima-city registered under example.com not _acme-challenge.example.com as should be therefore the check for the txt value fails ig?

@feroxib
Copy link

feroxib commented Aug 27, 2024

in addition to that i tested editing the entry to _acme-challenge.example.com and kept the value the same. all while the script was in its wait interval but still no luck

@ldez
Copy link
Member Author

ldez commented Aug 27, 2024

I tried something to fix the subdomain, but I don't know if it's the right approach 🤷

@feroxib
Copy link

feroxib commented Aug 27, 2024

still no certs ...

but we have a partial success...

i now get txt-records with _acme-challenge.example.com and the correct value as logged in terminal

logs to come

@feroxib
Copy link

feroxib commented Aug 27, 2024

 LIMACITY_API_KEY=the-key ./dist/lego -m my@email.com --dns limacity -d *.example.com -d example.com -s https://acme-staging-v02.api.letsencrypt.org/directory run
2024/08/27 16:21:44 [INFO] [*.example.com, example.com] acme: Obtaining bundled SAN certificate
2024/08/27 16:21:46 [INFO] [*.example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757873233
2024/08/27 16:21:46 [INFO] [example.com] AuthURL: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757873243
2024/08/27 16:21:46 [INFO] [*.example.com] acme: use dns-01 solver
2024/08/27 16:21:46 [INFO] [example.com] acme: Could not find solver for: tls-alpn-01
2024/08/27 16:21:46 [INFO] [example.com] acme: Could not find solver for: http-01
2024/08/27 16:21:46 [INFO] [example.com] acme: use dns-01 solver
2024/08/27 16:21:46 [INFO] [*.example.com] acme: Preparing to solve DNS-01
2024/08/27 16:21:46 [INFO] [example.com] acme: Preparing to solve DNS-01
2024/08/27 16:21:46 [INFO] [*.example.com] acme: Trying to solve DNS-01
2024/08/27 16:21:46 [INFO] [*.example.com] acme: Checking DNS record propagation. [nameservers=127.0.0.53:53]
2024/08/27 16:21:48 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2024/08/27 16:21:48 [INFO] [*.example.com] acme: Waiting for DNS record propagation.
.................
2024/08/27 16:22:47 [INFO] [*.example.com] acme: Waiting for DNS record propagation.
2024/08/27 16:22:49 [INFO] [example.com] acme: Trying to solve DNS-01
2024/08/27 16:22:49 [INFO] [example.com] acme: Checking DNS record propagation. [nameservers=127.0.0.53:53]
2024/08/27 16:22:51 [INFO] Wait for propagation [timeout: 1m0s, interval: 2s]
2024/08/27 16:22:51 [INFO] [example.com] acme: Waiting for DNS record propagation.
................
2024/08/27 16:23:51 [INFO] [example.com] acme: Waiting for DNS record propagation.
2024/08/27 16:23:53 [INFO] [*.example.com] acme: Cleaning DNS-01 challenge
2024/08/27 16:23:53 [WARN] [*.example.com] acme: cleaning up failed: limacity: get records: unable to unmarshal response: [status code: 200] body: {"records":[...........,{"id":29****,"name":"_acme-challenge.example.com","subdomain":"_acme-challenge","type":"TXT","content":"\"4C4F1p0SM3yNH7hfE6FmSpnH0MWHEEB6_57fI5KJLY0\"","priority":null,"ttl":3600},{"id":2951569,"name":"_acme-challenge.example.com","subdomain":"_acme-challenge","type":"TXT","content":"\"VqVgPrcjYiFI8vbuJ5AIrV6v1j2WZBYBw5QNst_lKvw\"","priority":null,"ttl":3600}]} error: json: cannot unmarshal string into Go struct field Record.records.subdomain of type bool 
2024/08/27 16:23:53 [INFO] [example.com] acme: Cleaning DNS-01 challenge
2024/08/27 16:23:53 [WARN] [example.com] acme: cleaning up failed: limacity: get records: unable to unmarshal response: [status code: 200] body: {"records":[...........,{"id":29****,"name":"_acme-challenge.example.com","subdomain":"_acme-challenge","type":"TXT","content":"\"4C4F1p0SM3yNH7hfE6FmSpnH0MWHEEB6_57fI5KJLY0\"","priority":null,"ttl":3600},{"id":2951569,"name":"_acme-challenge.example.com","subdomain":"_acme-challenge","type":"TXT","content":"\"VqVgPrcjYiFI8vbuJ5AIrV6v1j2WZBYBw5QNst_lKvw\"","priority":null,"ttl":3600}]} error: json: cannot unmarshal string into Go struct field Record.records.subdomain of type bool 
2024/08/27 16:23:53 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757873233
2024/08/27 16:23:53 [INFO] Deactivating auth: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/13757873243
2024/08/27 16:23:53 Could not obtain certificates:
        error: one or more domains had a problem:
[*.example.com] propagation: time limit exceeded: last error: NS ns2.lima-city.de. did not return the expected TXT record [fqdn: _acme-challenge.example.com., value: 4C4F1p0SM3yNH7hfE6FmSpnH0MWHEEB6_57fI5KJLY0]: 
[example.com] propagation: time limit exceeded: last error: NS ns1.lima-city.de. did not return the expected TXT record [fqdn: _acme-challenge.example.com., value: VqVgPrcjYiFI8vbuJ5AIrV6v1j2WZBYBw5QNst_lKvw]: 

@feroxib
Copy link

feroxib commented Aug 27, 2024

so i guess subdomain is no bool...
but if empty uses false instead of something more natural like null...

@ldez ldez removed the state/need-user-tests Need users to test functionality label Aug 29, 2024
@ldez ldez added this to the v4.18 milestone Aug 29, 2024
@ldez
Copy link
Member Author

ldez commented Aug 29, 2024

We made it!!!

It was a long journey, but a great victory 🎉

@ldez ldez marked this pull request as ready for review August 29, 2024 22:55
@feroxib
Copy link

feroxib commented Aug 29, 2024

We made it!!!

It was a long journey, but a great victory 🎉

thank you so much for your patience!

it was great work and a great first experience for me too "working" on some open-source project.

please feel free to reach out in the future if needed!

Thank you!

@ldez
Copy link
Member Author

ldez commented Aug 29, 2024

please feel free to reach out in the future if needed!

I will not hesitate.
It was a "fun" experience 😸
I'm so glad I gave you the opportunity to work on open-source and that you enjoyed it.

@feroxib
Copy link

feroxib commented Aug 29, 2024

please feel free to reach out in the future if needed!

I will not hesitate. It was a "fun" experience 😸 I'm so glad I gave you the opportunity to work on open-source and that you enjoyed it.

Wont be the last!

sent something your way ;)

Have a nice evening

@ldez ldez merged commit 7062e8c into go-acme:master Aug 29, 2024
4 checks passed
@ldez ldez deleted the feat/lima-city branch August 29, 2024 23:20
@feroxib
Copy link

feroxib commented Aug 29, 2024

@dmke haha nice! i didnt expect this to happen this late.

thank you so very much too!
youre both awsome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

Support for provider: lima-city
3 participants