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

acme-dns: allow the HTTP storage server to create the CNAME #2437

Merged
merged 6 commits into from
Feb 16, 2025

Conversation

ldez
Copy link
Member

@ldez ldez commented Feb 15, 2025

This allows the HTTP storage server to control the CNAME creation.

if the Put returns a 201, lego expects the CNAME to be created automatically by the server.

Closes #2436

@skippyprime
Copy link

I think the HTTP 201 Created logic needs to be moved to the Put function. The save function won’t have the context of which domain it is responding to.

@ldez
Copy link
Member Author

ldez commented Feb 15, 2025

The Save will be always called because of the file implementation, so an implementation of the Save is required.

@ldez
Copy link
Member Author

ldez commented Feb 15, 2025

🤔 I can skip the Save but it will be weird.

@skippyprime
Copy link

skippyprime commented Feb 15, 2025

The reason I suggested the check in Put vs Save is because when we have multiple domain challenges. On the first domain challenge, everything works as intended 1. Put the domain + acme dns data and then 2. Save would create the single CNAME record.

When 2+ domains are registered, the Save would have to iterate all domain challenges stored and attempt to create the CNAME because it doesn’t have the context on Save to know which CNAME needs created. If the Save had the domain attempting a minimum this wouldn’t be an issue.

@ldez
Copy link
Member Author

ldez commented Feb 15, 2025

Can you check the updated implementation?

@ldez
Copy link
Member Author

ldez commented Feb 15, 2025

When I created the initial HTTP storage implementation the Save I wondered if I should skip the step.

My thinking was that if a DNS provider doesn't provide an API usable by lego, there is no possibility to automate the CNAME process.

So, I'm interested in more details about your context/use case, could you give me more details?
This is a reason why it is important to create an issue before creating a PR.

@skippyprime
Copy link

I think the logic in HTTP response is way better than the environment variable approach.

While we know that there are only 2 storage implementations and the HTTP Save is a no-op, we could still call save to keep the client logic clean. You could do:

cnameCreated := errors.Is(internal.ErrCNAMECreated)

// call save and check for error

if !cnameCreated {
  // return error
}

return nil

Sorry for any errors in code above, on a phone.

@ldez

This comment was marked as outdated.

@ldez
Copy link
Member Author

ldez commented Feb 15, 2025

I think I understand your suggestion, your snippet was a bit confusing, sorry.

Could you answer my previous question? #2437 (comment)

@ldez ldez added this to the unreleased milestone Feb 15, 2025
@ldez ldez marked this pull request as ready for review February 15, 2025 20:46
@ldez ldez requested a review from dmke February 15, 2025 20:49
@skippyprime
Copy link

The use case is for a generic ingress service for local development.

I end up working on a number of different projects (typically a mix of related micro-services or isolated projects) that either I need to access from the host browser or the services need to communicate directly. Since most of these are separate git repos, it is ideal for them to be loosely coupled so they can run independently or together. Rather than juggling lots of different exposed ports, it is preferred to use standard ports (80, 443) and depend of SNI or Host matching to route traffic to the correct services.

I am releasing an open source service kit (traefik + coredns + stepca + acme-dns) that developers can run locally to dynamically add routes to traefik, allow traefik to automatically obtain certificates (HTTP-01 and DNS-01 challenges). The DNS challenges were required to support wildcard certificates.

The acme-dns HTTP storage layer was the piece that is making this possible. I wrote a simple HTTP storage server that will save the acme-dns accounts in the same format as though you are using the file storage backend. It will take care of registering the CNAME with coredns before it returns the HTTP 201 Created to the Put request.

@ldez ldez force-pushed the feat/acme-dns-cname-created branch from 7ba881f to 906a485 Compare February 15, 2025 22:56
@ldez
Copy link
Member Author

ldez commented Feb 16, 2025

Your stack is interesting.

It will take care of registering the CNAME with coredns before it returns the HTTP 201 Created to the Put request.

How do you create the CNAMEs? (coredns has no API to add/remove records)
Is it a global forward?

Copy link
Member

@dmke dmke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a little bike shedding :)

@ldez ldez requested a review from dmke February 16, 2025 10:52
@ldez ldez merged commit b16da88 into go-acme:master Feb 16, 2025
7 checks passed
@ldez ldez deleted the feat/acme-dns-cname-created branch February 16, 2025 15:12
@skippyprime
Copy link

I found one other missed expectation that acme-dns would always return ErrCNAMERequired. https://github.com/go-acme/lego/blob/master/providers/dns/acmedns/acmedns.go#L178

The result of register(...) is returned without checking if the error is set. This causes the UpdateTXTRecord to never be called when the CNAME is created by the HTTP storage server. Do you want me to open a PR to propose a fix?

@ldez
Copy link
Member Author

ldez commented Feb 17, 2025

I will fix that.

I just created a release 😢

@ldez
Copy link
Member Author

ldez commented Feb 17, 2025

#2443

@skippyprime
Copy link

So close. Sorry, I was testing this last night and couldn't figure out what was preventing the solve. Realized this morning after looking through the debug logs.

Sorry I missed this on the first pass.

@dmke
Copy link
Member

dmke commented Feb 17, 2025

Don't worry, I didn't catch that in my review as well.

@ldez
Copy link
Member Author

ldez commented Feb 17, 2025

I made a mistake and 2 pairs of eyes didn't detect it, so the conclusion: we are human or bad AIs 😸

We were able to create quickly a bug-fix release, so everything is right.

@ldez
Copy link
Member Author

ldez commented Feb 17, 2025

I'm still interested in your stack: #2437 (comment)

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.

3 participants