Octopus and Let's Encrypt with many sites

Jacob K's Avatar

Jacob K

10 Dec, 2017 02:50 PM

I have a scenario where i'm not at all sure how to handle things, and i figured i'd reach out for some advice.

At my workplace we have 26 different sites in IIS. Theses sites are using 6 different domains and quite a few subdomains for many of them. With most of these sites we want, and have, SSL using Let's Encrypt which works perfectly. It is, however, a bit difficult to manage when Octopus needs to deploy everything (which is the new variable in this puzzle)

Right now we're using Certify to get all the certificates - and there's a lot because of how Certify does it. It's basically 1 certificate per. IIS site (even though multiple sites do share domain names). So we're talking 20+ different certificates with whatever bindings the individual sites have as SAN additions. This is absolute hell to manage with octopus as i have to specify different certificates for different tenants under the same deployment (we have the same code deployed multiple times for different languages) and reference a thumbprint that changes whenever the certificates renew which is quite often with Let's Encrypt.

I hope this lengthy post isn't too confusing, and that someone can give me some on advice on how to handle this.

My ideal solution would be to manage the Let's Encrypt certificates from Octopus, but i don't really see how.

  1. Support Staff 1 Posted by Lawrence Wilson on 11 Dec, 2017 08:46 AM

    Lawrence Wilson's Avatar

    Hi Jacob,
    Thanks for reaching out! I could imagine it would be an enormous task to update the SSL thumbprints each time your certificates get renewed. One option which comes to mind could be to insert a new step at the beginning of your deployment. With the new step you could make a request out to lets encrypt to generate a new lets encrypt certificate and install it into the local certificates store. While in this step, you could save various details about the newly installed certificate, like it's thumbprint as a variable made available to subsequent steps in your deployment. Please see our Fun with variables blog for more details.

    When you're ready to configure the bindings further down in your deployment you could reference the thumbprint variable you just created. While I haven't personally tested the Lets Encrypt - Createt SSL Certificate community step template, it's possible this might be able to help you!

    I look forward to hearing if this helps you out!

    Kind regards,
    Lawrence.

  2. 2 Posted by Jacob K on 11 Dec, 2017 12:49 PM

    Jacob K's Avatar

    Hi Lawrence,
    When you say "make a request out to lets encrypt" do you mean using the Lets Encrypt - Create SSL Certificate community step and then passing on the variables? Because i don't see a way to pass on variables from the step itself?

  3. Support Staff 3 Posted by Lawrence Wilson on 13 Dec, 2017 06:04 AM

    Lawrence Wilson's Avatar

    Hi Jacob,
    Thanks for keeping in touch! I had a brief look at the script source of the Lets Encrypt - Create SSL Certificate and while it currently doesn't have the ability to save the Octopus variable for the certificate thumbprint you're welcome to view the source code and add that functionality in, you can then import your own version of this template into your Octopus server. Please check out our documentation for more information on Importing step templates from the community

    One possible way to do this would be to download the step template, then modify the PowerShell script to include this line towards the bottom:

    Set-OctopusVariable CertificateThumbprint $certificate.Thumbprint
    

    Then, in a different step, along the same process you would be able to reference the thumbprint using the variable:

    $CertificateThumbprint = $OctopusParameters["Octopus.Action[LetsEncrypt].Output.CertificateThumbprint"]
    

    I hope you have found this helpful! please let me know if you have any further questions.

    Kind regards,
    Lawrence.

  4. 4 Posted by Jacob K on 13 Dec, 2017 10:56 AM

    Jacob K's Avatar

    Thanks again, for some great feedback. I actually got it working last night - without the ekstra community step.

    On each of our servers i use letsencrypt-win-simple to generate a SAN certificate for all sites with all domains and subdomains, so that i'll only have to deal with 1 certificate per. server. Using the app also let's you test configs before actually issuing certificates - keeping you from reaching that weekly limit. When the certificate has been issued it creates a task to renew the certificate every X days.

    The certificate is put in in Web Hosting instead of Person which means that i can fairly safely assume that it's the only available certificate (this is important later).

    In octopus i have a PowerShell script:

    $Thumbprint = (Get-ChildItem -Path cert:\LocalMachine\WebHosting | Where-Object {$_.Subject -match "CN"}).Thumbprint;
    Write-Host "Using certificate with thumbprint: $Thumbprint"
    Set-OctopusVariable -name "SSL_Thumbprint" -value "$Thumbprint"
    

    The script assumes, from before, that there's only a single certificate and fetches the thumbprint to put it in the variable SSL_Thumbprint for octopus to use for my bindings in the next step.

    And well.. it works perfectly and should hopefully not break when the certificates are renewed, but i guess we'll see.

    Thank you for take time to help me, and getting me on track with to solve my problem. It's much appreciated.

  5. Support Staff 5 Posted by Lawrence Wilson on 14 Dec, 2017 11:41 AM

    Lawrence Wilson's Avatar

    Hi Jacob,
    Thank you for letting us know how you went with setting this up. I'm happy to have provided insight here and you're very welcome!

    Kind regards,
    Lawrence.

  6. 6 Posted by octopus.com on 19 Jan, 2018 12:33 AM

    octopus.com's Avatar

    Massive thanks to Jacob for getting me on the right direction. However I just spent ages failing to communicate the certificate thumbprint through to the IIS binding.

    I needed this in the binding:
    #{Octopus.Action[GrabSANCertThumbprint].Output.SSLThumbprint}

    Where:
    GrabSANCertThumbprint is the NAME of the step with Jacob's script (thanks Jacob!) that finds and interrogates the certificate.

    SSLThumbprint is the name of the Octopus variable I created in that script.

    Hope this helps.
    - Richard

  7. 7 Posted by Jacob K on 21 Jan, 2018 06:15 PM

    Jacob K's Avatar

    You're absolutely right, Richard. That is a very valid step to add to this whole mess, and exactly what i have in my next step as well.
    I'm glad to have helped and i appreciate that you could improve on my writeup.

    I always stive to not have things end like this https://xkcd.com/979/ :-)

  8. 8 Posted by octopus.com on 21 Jan, 2018 08:14 PM

    octopus.com's Avatar

    Nice nod to xkcd.

    Only one thing worse. That same thread; with one response; from the OP; saying "DW - I solved it."

    Well done to the OP but HOW????

  9. 9 Posted by nick on 05 Mar, 2018 12:53 PM

    nick's Avatar

    Does anyone know how to modify this to get the most *recent* certificate? It seems that LetsEncrypt now keeps the previous certificate there, meaning two thumbprints are returned.

    Thanks,
    Nick

  10. 10 Posted by octopus.com on 05 Mar, 2018 05:35 PM

    octopus.com's Avatar

    I have seen this, but *only* when I intervene manually.

    For example, if I add a new site, then I manually run through the cert wizard to get a new one. That process leaves two certs there and I have to manually remove the old one.

    I am as sure as I can be that the Let's Encrypt automated renewal does not leave two certs.

  11. 11 Posted by nick on 06 Mar, 2018 09:31 AM

    nick's Avatar

    [superseded by comment below]

  12. 12 Posted by nick on 15 Mar, 2018 12:26 PM

    nick's Avatar

    Here's my finished/working script, which finds the most recent matching (i.e. expiring furthest in the future) certificate for a given domain name:

    Firstly, in a step named: GetSSLThumbprint

    $url = $OctopusParameters["<YourDomainNameVariable>"]
    
    $Thumbprint = (Get-ChildItem -Path cert:\LocalMachine\Webhosting `
     | Where-Object {$_.Subject -match $url} `
     | Sort-Object -Property NotAfter -Descending   `
     | Select-Object -first 1).Thumbprint 
    
    Write-Host "Using certificate with thumbprint: $Thumbprint"
    
    Set-OctopusVariable -name "SSLThumbprint" -value $Thumbprint
    

    Then in IIS binding:

    #{Octopus.Action[GetSSLThumbprint].Output.SSLThumbprint}
    
  13. 13 Posted by Shyam on 05 Sep, 2018 06:02 AM

    Shyam's Avatar

    Hi Team,

    From the above discussion. I have understood that we have to generate SSL Certificate manually and Octopus will get the SSL Thumbprint while deployment and it will add the binding through #{Octopus.Action[GetSSLThumbprint].Output.SSLThumbprint}.
    Let me know if I am wrong and second thing is what we have to do for renewing the SSL? By manually?

    Thanks,
    Shyam

  14. 14 Posted by nick on 05 Sep, 2018 09:52 AM

    nick's Avatar

    Hi Shyam,

    For renewal, I just use Lets Encrypt Windows Client and it's built in
    Task Scheduler based renewals:

    https://github.com/PKISharp/win-acme

    Nick

  15. 15 Posted by stormrider01 on 05 Dec, 2018 02:50 PM

    stormrider01's Avatar

    Nick, thanks for the GetSSLThumbprint script. In my case I'm using the CertifyTheWeb.com gui client, and it's putting the certs into cert:\LocalMachine\My, but the approach is great for sites that might go 90 days without a redeployment.

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac