Closed jotasi closed 4 months ago
Hello,
I'm not sure to understand your problem.
As you can see we have dedicated tests on joinPath
:
https://github.com/go-acme/lego/blob/82e9a5e2a917e72870781d80d2de515c27208304/providers/dns/pdns/internal/client_test.go#L66
Your implementation will break everything.
And the tests seems to say the opposite of the behavior you described :thinking: . https://github.com/go-acme/lego/blob/82e9a5e2a917e72870781d80d2de515c27208304/providers/dns/pdns/internal/client_test.go#L74-L80
Hi,
Thanks for the quick reply!
Please find a bit more concrete explanation below.
There are four places where joinPath
is used (which just adds the path to the PDNS_API_URL
, potentially adding /api/v1
to the front if the provided path does not start with /api
and if the API version is not 0):
The problem is with the latter two usages. Here, the path that is passed to joinPath
is starting with zone.URL
, where zone
is the parsed return of the API call within GetHostedZone
(see second code block above). However, at least for my provider, the URL that is returned by querying, in my case, https://login.udmedia.de/dns/api/v1/servers/udmedia/zones/example.com.
is an absolute path to the host's root and thus also includes the relative path to the API again that is aready part of PDNS_API_URL
(i.e., starting with /dns
below rather than /api/v1/...
):
{
"id": "example.com.",
"url": "\/dns\/api\/v1\/servers\/udmedia\/zones\/example.com.",
"name": "example.com.",
"type": "Zone",
<snip>
When this path is then passed to joinPath
, this leads to URL with the duplicated /dns/api/v1/dns/api/v1
that I have listed in my original post.
My crude solution suggested above for the 3rd and 4th usage above (NOT replacing joinPath
for the first two) works for my case and should also work for the standard case, where the API endpoint sits at the URL root with API version 1 where the /api/v1
should already be part of zone.URL
.
However, there are also possibly less invasive solutions. If any of them sounds reasonable, please let me know and I can potentially flesh them out some more:
zone.URL
in the 3rd and 4th joinPath
calls above, one could recreated the relative URL analogously to the 2nd usage. With a relative URL, this should then work fine. From reading the PowerDNS API documentation, the URL sounds to be fixed and thus zone.URL
usage just saves some work but should hopefully be replaceable.zone.URL
should still be used, an environmental variable option (something like PDNS_ZONE_URL_ABSOLUTE=1
), whether it is known to contain the absolute URL to the URL's root, could be added and only if that is set, one could basically use my crude solution or try to retrospectively make the zone.URL
a relative path before using joinPath
by removing the path from PDNS_API_URL
from the start of the zone.URL
.
Welcome
What did you expect to see?
When requesting a first or renewing an existing certificate via DNS challenge and PowerDNS API with the API endpoint not being located at the URL root (e.g.,
https://login.udmedia.de/dns/api
instead ofhttps://login.udmedia.de/api
), the command should run through without an error.What did you see instead?
When requesting a first or renewing an existing certificate via DNS challenge and PDNS API with the API endpoint not being located at the URL root (e.g.,
https://login.udmedia.de/dns/api
instead ofhttps://login.udmedia.de/api
), the command fails with an error code 404, indicating that an unknown URL was queried.After debugging, this was pinpointed to the URL generated as
endpoint
for updating withinUpdateRecords
inproviders/dns/pdns/internal/client.go
not being the expectedhttps://login.udmedia.de/dns/api/v1/servers/udmedia/zones/example.com.
but insteadhttps://login.udmedia.de/dns/api/v1/dns/api/v1/servers/udmedia/zones/example.com.
(i.e., with duplicateddns/api/v1/
).The reason for that is that the URL of the host to which the path is appended by
joinPath
is already containing the/dns
but the URL of the zone that is returned by the provider's PDNS compatible API (determined viaGetHostedZone
) and AFAIU also by PowerDNS itself (tentative as I don't have a PowerDNS installation to try this out with but see, e.g., discussion here) is an absolute URL path also containing the starting/dns
. Therefore,/dns
of the Host URL is extended by a second/dns
from the Zone URL. Furthermore, injoinPath
for API version != 0, any path to add that is not starting with/api
(which is the case here as the path starts with/dns/api/...
) is also prepended by/api/v1
. This then results in the superfluous/api/v1/dns
being added between the host URL and the Zone URL path.This could be fixed by adding a second join function (e.g.,
joinAbsolutePath
) that removes any remaining path from the Host URL before joining and (as this seems unnecessary in that case to me, but please correct me there if this is actually needed for, e.g., earlier version of PowerDNS or the API) not trying to guess whether/api/v1
needs to be prepended to the URL path. The function could look somewhat like this:and could replace
joinPath
here and here.I can confirm that this fixes the issue at least for my provider. If helpful, I can provide a corresponding PR also including some tests of the new function. However, the caveat here is that I have limited experience with go and PowerDNS in general and don't want to inadvertently break something for someone else.
How do you use lego?
Binary
Reproduction steps
Try requesting a first or renewing an existing certificate via DNS challenge and PDNS API (API version v1) with the API endpoint not being located at the URL root (
PDNS_API_URL
containing a non-empty path, e.g.,https://login.udmedia.de/dns
instead ofhttps://login.udmedia.de
for an API endpoint athttps://login.udmedia.de/dns/api
instead ofhttps://login.udmedia.de/api
).The command used (and environment variables set (except for the API key), see Logs section.
(See also discussion #2122)
For my understanding of the origin of the error after debugging this, see section on "What did you see instead?".
Version of lego
Logs
Go environment (if applicable)