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

Handling multiple certificates for same domain #345

Closed
HFalch opened this issue May 12, 2021 · 6 comments
Closed

Handling multiple certificates for same domain #345

HFalch opened this issue May 12, 2021 · 6 comments
Assignees
Labels
enhancement New feature or request

Comments

@HFalch
Copy link

HFalch commented May 12, 2021

First of all, thanks a lot for creating and maintaining this project. It was the ticket for me to get started with ACME in a Windows environment without having to introduce Linux into it, and with the scriptability of a PowerShell module to boot rather than a GUI or "black box" closed source tool.

With that said, there is one little thing I'd wish was handled better. As the title says, it's what happens when you request different certificates for the same domain. Since any given request is placed into a folder corresponding to the first - main - domain listed for a request, making two different ones with the same main domain causes the first one to be overwritten.

There are ways to work around this. Specifying different home folders for each request is one, but that also creates two separate ACME accounts unless you do some manual hacky stuff on top to reuse the same account between both home folders. Putting a different domain first in the list to become the main domain is perhaps the simplest and least hacky way, but requires carefully keeping track of domains and ordering of them in requests and still can't handle the (admittedly very corner) case of two separate certificates for a single domain.

Just to clarify why this has become an issue in the first place, it's because I don't generate the certificates on the servers that use them. They are all generated on one single isolated system and pushed out to the systems and services via script. This is partially for security, and partially for technical reasons, as some certificates have to be installed on multiple systems and activated only once all of them have a copy. Not just the same domain(s), it has to be the same exact certificate. This leads to a lot of different certificates being generated on the same server, some of them with overlapping domains and SANs.

I'm not entirely sure what the best way to handle this would be, but the first idea I had was to simply use FriendlyName instead of MainDomain as the folder name if one is specified and only use MainDomain if not.
Combined with the recently added "Folder" property in Get-PAOrder output, that would make it easier to keep certificates separate and easier to find both manually and by script, while retaining simplicity and ease of use for those who just generate a single cert and/or don't specify FriendlyName.
Minor issue, but worth considering?

@rmbolger rmbolger self-assigned this May 12, 2021
@rmbolger rmbolger added the enhancement New feature or request label May 12, 2021
@rmbolger
Copy link
Owner

Thanks so much for bringing this up, @HFalch. It's another thing I had actually been thinking about recently, and not only with orders, but for basically everything in the config hierarchy. The idea I have in my head is basically a Name or FriendlyName property on Servers, Accounts, and Orders that is optional on creation and editable using the various Set functions. And that name would then become the folder name on disk for that object.

My goal is to implement it in such a way that it's not a breaking change and I don't have to move the code to a 5.x version quite yet. But I won't likely start working on it until after I sort out the revocation improvements in #343.

@rmbolger
Copy link
Owner

Just wanted to mention I haven't forgotten about this. Got a bit side tracked with work and some plugin pull requests. But it's still on my radar to implement sooner rather than later.

@rmbolger
Copy link
Owner

I thought I'd throw out a progress update for this partially as a way to say I'm still working on it, but also as a way to organize my thoughts. The friendly-names branch is where I've been working on code that will allow renaming Servers, Accounts, and Orders. At the moment, I've got a rough version working for Servers and Accounts and I'm just starting to work on Orders.

The tricky part of this is that I'm still really trying to implement it in such a way that it can be included in 4.6 as a feature addition rather than breaking changes that would necessitate a 5.0 release. But that means sacrificing a bit of how I want the parameters to work so that no one's scripts break. I'm hoping it will still be a good foundation which will lead nicely into a 5.0 release where I can revamp the parameter sets to be a bit more intuitive and drop some legacy architectural assumptions.

Servers

Returned PAServer objects now have a Name and Folder. The Name is essentially the folder name on the filesystem and the Folder is the full path to that folder. What's cool is that these properties are dynamic and not actually saved with the dir.json file. So if you move your config to a different location, those properties will reflect the new location as well without any additional futzing.

Set-PAServer has 3 new params: Name, NewName, and NoSwitch. The Name param can be used to switch to a particular server based on the Name rather than needing to specify a DirectoryUrl like usual. If you do specify a DirectoryUrl, the Name parameter is ignored unless it's the first time you've used that ACME server in which case it will use the Name value as the new name of the server reference. If you don't specify a Name, the default name will continue to be based on the DirectoryUrl value unless you used a shortcut like LE_PRD in which case the name will be the shortcut. So Set-PAServer LE_PROD on a fresh install would create a new server named LE_PROD using the appropriate DirectoryUrl. Or you could do Set-PAServer LE_PROD -Name 'staging' to set an explicit name.

The NewName parameter is for changing the name of an existing server. So when you first upgrade from 4.5, you'd be able to Set-PAServer -NewName 'letsencrypt' to change the name (and folder name) of your existing LE_PROD server. The NoSwitch parameter ultimately a result of some refactoring I did under the hood, but also serves as a convenience feature if you want to modify server settings without changing the active server.

Get-PAServer and Remove-PAServer have a Name parameter to use as an alternative to DirectoryUrl for finding a specific server. But the Name parameter is ignored if DirectoryUrl is specified. In 5.0, the priority and position of these params will likely be swapped so Name becomes the primary parameter.

The other limitation on servers that will stay for 4.6 is that you can only have one instance of a given ACME server (one unique DirectoryUrl) per config root. This might change in 5.0, but I'm not positive. I still have to weigh the flexibility benefits over the additional code complication.

Accounts

PAAccount objects already had an id value that was being generated from the account object URL. For 4.6, it will remain but be repurposed as effectively a name property that works just like servers. There's a new dynamic Folder property as well. All of the functions that have an ID param now have "Name" as a parameter alias.

You set an explicit ID with New-PAAccount and Set-PAAccount currently has a "NewName" property that I'm still debating whether I should make it "NewID" and make the other a parameter alias. But that feels like purposefully adding a future breaking change just to make things more consistent in the current version.

I don't think anything has functionally changed with Remove-PAAccount.

Orders

I haven't really started making code changes for Orders yet because I'm still mulling over how things should work. The main point of the change is to be able to have more than one order with the same set of domains (or at least the same primary domain). But if we think about existing code that would be calling Get-PAOrder, it's only going to specify a MainDomain parameter at best. So what do we do? Return all orders that match and potentially break the script because it assumes it will only ever get a single result? Return only a single result? If so, which one? Random or more specifically whichever one PowerShell happens to return first? Most recent based on order expiration? Something else?

I'm definitely leaning towards some form of only returning one result because that's more or less the "contract" users of the function are used to. In 5.0 it won't matter because I'll likely get rid of the MainDomain param and Name will become the main method of getting a specific order and Names will need to be unique per account.

@rmbolger
Copy link
Owner

Decided I didn't want to hold up the release of 4.6 any longer, so this will have to wait for 4.7. Still working on it though. It's getting close. Trying to add a bunch more tests to make sure I don't break anything.

@rmbolger
Copy link
Owner

Changes are now live in the main branch pending a full release. Feel free to test it if you're feeling adventurous. But make a backup of your existing config if you think you might back rev after customizing any object names. There's a bit more testing and a couple more things I'm hoping to add before shipping 4.7.0.

@rmbolger
Copy link
Owner

4.7.0 has been released

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants