Skip to content

Fix domain handling to work with the latest API version#18

Open
gailingmic wants to merge 1 commit intoionos-cloud:mainfrom
gailingmic:gailingmic-patch-1
Open

Fix domain handling to work with the latest API version#18
gailingmic wants to merge 1 commit intoionos-cloud:mainfrom
gailingmic:gailingmic-patch-1

Conversation

@gailingmic
Copy link

Hello everyone,

i noticed that this plugin no longer worked because of an API change on your side.
I updated the _find_zone_id call by searching with the root domain instead of the subdomain to reflect that change.

Sincerely,
Michell

Fixed the _find_zone_id call by searching with the root domain instead of the subdomain
@zak905
Copy link
Contributor

zak905 commented Dec 9, 2025

Hi @gailingmic, thanks! I am looking into this asap.

@zak905
Copy link
Contributor

zak905 commented Dec 9, 2025

I tested the plug-in with a top level domain (e.g certbot-demo.de), and it worked ok. Do you have an example of an input that triggers the failure ?

Ps: the API did not change since the last release.

@gailingmic
Copy link
Author

gailingmic commented Dec 10, 2025

Hi :)

i cant provide you the exact Input but i can tell you how to replicate the issue.

Setup a domain (example.de) on DCD Cloud DNS & create A Record for test.example.de. If you now try to request the zone via the API you dont get items returned as you can see here:

GET https://dns.de-fra.ionos.com/zones?filter.zoneName=test.example.de HTTP/1.1
HTTP/1.1 200 OK
Date: Wed, 10 Dec 2025 13:12:46 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 329
Connection: close
Ionos-Request-Id: <REDACTED>
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Ratelimit-Burst: 200
X-Ratelimit-Limit: 3000
X-Ratelimit-Remaining: 0

{
  "id": "<REDACTED>",
  "type": "collection",
  "href": "https://dns.de-fra.ionos.com/zones?filter.zoneName=test.example.de\u0026limit=100\u0026offset=0",
  "items": [],
  "offset": 0,
  "limit": 100,
  "_links": {
    "self": "https://dns.de-fra.ionos.com/zones?filter.zoneName=test.example.de\u0026limit=100\u0026offset=0"
  }
}

if you now only query for the root domain you obviously get the zone correctly.

GET https://dns.de-fra.ionos.com/zones?filter.zoneName=example.de HTTP/1.1
HTTP/1.1 200 OK
Date: Wed, 10 Dec 2025 13:00:11 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1149
Connection: close
Ionos-Request-Id: <REDACTED>
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Ratelimit-Burst: 200
X-Ratelimit-Limit: 3000
X-Ratelimit-Remaining: 0

{
  "id": "<REDACTED>",
  "type": "collection",
  "href": "https://dns.de-fra.ionos.com/zones?filter.zoneName=example.de\u0026limit=100\u0026offset=0",
  "items": [
    {
      "id": "<REDACTED>",
      "type": "zone",
      "href": "https://dns.de-fra.ionos.com/zones/<REDACTED>",
      "metadata": {
        "createdBy": "ionos:iam:cloud:<REDACTED>:users/<REDACTED>",
        "createdByUserId": "<REDACTED>",
        "createdDate": "2025-12-00T00:00:00.000000Z",
        "lastModifiedBy": "ionos:iam:cloud:<REDACTED>:users/<REDACTED>",
        "lastModifiedByUserId": "<REDACTED>",
        "lastModifiedDate": "2025-12-00T00:00:00.000000Z",
        "resourceURN": "ionos:public-dns:de-fra:31891827:zones/<REDACTED>",
        "nameservers": [
          "ns-ic.ui-dns.com",
          "ns-ic.ui-dns.de",
          "ns-ic.ui-dns.org",
          "ns-ic.ui-dns.biz"
        ],
        "state": "AVAILABLE"
      },
      "properties": {
        "description": "Example Domain",
        "enabled": true,
        "zoneName": "example.de"
      }
    }
  ],
  "offset": 0,
  "limit": 100,
  "_links": {
    "self": "https://dns.de-fra.ionos.com/zones?filter.zoneName=example.de\u0026limit=100\u0026offset=0"
  }
}

If you have a different way to send some informations your way please let me know. I can provide you with the exact example then.

Sincerely,
Michell

@gailingmic
Copy link
Author

Hello @zak905
To give a bit more context:
The example in the README.md

certbot certonly \
  --authenticator dns-ionos \
  --dns-ionos-credentials /path/to/credentials.ini \
  --dns-ionos-propagation-seconds 60 \
  --agree-tos \
  --rsa-key-size 4096 \
  -d 'example.com'

calls the function IONOSClient.add_txt_record(self, domain: str, record_name: str, record_content: str) wich results in self._find_zone_id(domain) see here being called with example.com as the argument. This will obviously work because example.com is the FQDN and root domain for this example.

BUT if you want to generate a cert for test.example.com it will fail because it will try to call self._find_zone_id(domain) with test.example.com as its argument wich isnt the root domain but its FQDN... That is the reason why im removing everything but the last 2 parts of the FQDN to get the root domain. see here

Hope that clears it up a little :)

@zak905
Copy link
Contributor

zak905 commented Dec 17, 2025

Hi @gailingmic, sorry for the late response. I tested generating a certificate for a second level domain (test-cerbot.example.com) in two ways:

  • creating an A record with the name test-certbot under the zone example.com, as you suggested. For this case, the current plugin does not work indeed. After I switched to your branch, the issuance worked.
  • creating a separate zone for the SLD (curl -H "Authorization: Bearer $TOKEN" --json '{"properties":{"zoneName":"test-certbot.example", "enabled": true}}' -v https://dns.de-fra.ionos.com/zones). With this approach, it works.

On the overall, your change looks good, and works for both cases. I am thinking if there are any additional cases we should also cover. For example, if the root zone is example.co.de, ".".join(domain.split(".")[-2:]) would return co.de

@gailingmic
Copy link
Author

Oh youre completely right... i totally forgot co.uk etc. ill push a fixed version later today

@dernapo
Copy link

dernapo commented Dec 17, 2025

@gailingmic I didn't test it yet, but it may work if you create a zone for test.example.com, instead of record "test" for the zone example.com

Precondition: example.com is a zone managed by ionos and resolving with ionos name servers

@gailingmic
Copy link
Author

@gailingmic I didn't test it yet, but it may work if you create a zone for test.example.com, instead of record "test" for the zone example.com

Precondition: example.com is a zone managed by ionos and resolving with ionos name servers

It should work but i feel this is quite excessive especially when youre creating many domains. But the more i think about this issue the more im leaning towards ionos needing to add an API endpoint / filter option to get the zone based on the FQDN provided.
Otherwise one would have to bruteforce it by removing one part of the domain until it works. And im not entirely sure if thats the desired way of going about it. 😬

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants