Skip to content

Revert "Remove certificates" #33

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

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/renew-certificate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Renew Certificate
on:
workflow_dispatch:
pull_request:
paths:
- ".github/workflows/renew-certificate.yml"
- "local-certs/certificate-domains"
- "local-certs/certificate-regions"
- "local-certs/generate-domains.py"
- "local-certs/generate-certificate.sh"
branches:
- master
push:
paths:
- ".github/workflows/renew-certificate.yml"
- "local-certs/certificate-domains"
- "local-certs/certificate-regions"
- "local-certs/generate-domains.py"
- "local-certs/generate-certificate.sh"
branches:
- master
schedule:
# * is a special character in YAML so you have to quote this string
- cron: '0 6 1 * *'

env:
git_user_name: localstack[bot]
git_user_email: localstack-bot@users.noreply.github.com

permissions:
contents: write

jobs:
renew-certificate:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Python
id: setup-python
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Certbot
run: |
python -m pip install --upgrade pip wheel setuptools
pip install certbot certbot-plugin-gandi
- name: Generate certificate
working-directory: "local-certs"
env:
CERTBOT_ARGS: "${{ github.ref != 'refs/heads/master' && '--staging' || '' }}"
DNS_API_KEY: "${{ secrets.DNS_API_KEY }}"
CERTBOT_EMAIL: ${{ env.git_user_email }}
run: |
./generate-certificate.sh
- name: Commit certificate
working-directory: "local-certs"
if: github.ref == 'refs/heads/master'
run: |
git config user.name ${{ env.git_user_name }}
git config user.email ${{ env.git_user_email }}
git add server.key
expiry_date=$(date --date="$(openssl x509 -enddate -noout -in server.key | cut -d= -f 2)" --utc --iso-8601)
git commit -m "update local certificate keys (new expiry date: $expiry_date)"
git push

4 changes: 4 additions & 0 deletions local-certs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
gandi.ini
config/
logs/
work/
20 changes: 20 additions & 0 deletions local-certs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Certificate renewal
The current certificate for `localhost.localstack.cloud` and several of its subdomains are stored in `server.key`.

The file contains both certificate and private key.

### Limitations
Please make sure to conform to the [LetsEncrypt Rate Limits](https://letsencrypt.org/docs/rate-limits/).

Most notably, do not rerequest the certficate for the same set of domain names more than 5 times a week, for new domain names more than 50 times a week and no more than 100 names in total per certificate.


### Domain lists

* `certificate-domains` contains a list (newline separated) with all domains the certificate should be valid for. It allows `{region}` as placeholder, to generate domains for multiple regions.
* `certificate-regions` contains a list (newline separated) of all regions which will be substituted for the `{region}` placeholder.


### Timeline

The certificate renewal will happen every time the domain/region list are updated, or every month.
15 changes: 15 additions & 0 deletions local-certs/certificate-domains
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
localhost.localstack.cloud
*.localhost.localstack.cloud
*.amplifyapp.localhost.localstack.cloud
*.cloudfront.localhost.localstack.cloud
*.elb.localhost.localstack.cloud
*.execute-api.localhost.localstack.cloud
*.opensearch.localhost.localstack.cloud
*.{region}.opensearch.localhost.localstack.cloud
*.s3-website.localhost.localstack.cloud
*.s3.localhost.localstack.cloud
*.scm.localhost.localstack.cloud
*.dkr.ecr.{region}.localhost.localstack.cloud
*.lambda-url.{region}.localhost.localstack.cloud
sqs.{region}.localhost.localstack.cloud
*.snowflake.localhost.localstack.cloud
6 changes: 6 additions & 0 deletions local-certs/certificate-regions
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
eu-central-1
eu-west-1
us-east-1
us-east-2
us-west-1
us-west-2
26 changes: 26 additions & 0 deletions local-certs/generate-certificate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
set -euo pipefail

# generate comma separated list of all domains to request a cert for
certificate_domains=$(python generate-domains.py)
echo "Generating certificate for domains ${certificate_domains}"

# create credentials file
echo "dns_gandi_api_key=${DNS_API_KEY}" > gandi.ini
chmod 600 gandi.ini

# request certificate
set -x
certbot -n --agree-tos --email ${CERTBOT_EMAIL} ${CERTBOT_ARGS} --authenticator dns-gandi --dns-gandi-credentials gandi.ini --key-type rsa --work-dir=$PWD/work --config-dir=$PWD/config --logs-dir=$PWD/logs -d $certificate_domains certonly
set +x

# remove credentials to avoid accidental leakage
rm gandi.ini

# concatinate private key + cert into single file to match current structure
echo "Concatinating certificate and key into single file"
cat config/live/localhost.localstack.cloud/privkey.pem config/live/localhost.localstack.cloud/fullchain.pem > server.key

# display certificate information
echo "Certificate information"
openssl x509 -in server.key -text -noout
32 changes: 32 additions & 0 deletions local-certs/generate-domains.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env python3

"""
This file generates a comma-separated list of domains,
by replacing the occurences of "{region}" in the domains
in "certificate-domains" by the regions in "certificate-regions"
"""


REGION_PLACEHOLDER = "{region}"


def generate_domains(domain_list: list[str], region_list: list[str]) -> list[str]:
result = []
for domain in domain_list:
if REGION_PLACEHOLDER in domain:
result += [domain.replace(REGION_PLACEHOLDER, region) for region in region_list]
else:
result.append(domain)
return result

def main():
with open("certificate-domains", mode="rt") as f:
domain_list = f.read().splitlines()
with open("certificate-regions", mode="rt") as f:
region_list = f.read().splitlines()
expanded_list = generate_domains(domain_list, region_list)
print(",".join(expanded_list), end="")


if __name__ == "__main__":
main()
119 changes: 119 additions & 0 deletions local-certs/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkPpgky1WMi9DO
ujPv3icBhHTV/tKeAWl+7ZuM0BkQMhWHCz2MYtOCIbL1jbH41UOmKmNjHglbNO06
sxdWbMuwgpY/nE9fUEW3AYxsoK/PKB/IpJ4LmuCLeHt4RlqXG8BPeSX6UeTP08/8
yRToaZTgCNjrP30uk3FSQDIf6wsxKhQMM88MEQOQXkRGS0B7Cfaz2fFmXiKeFYAo
JUYwsS0zVpPwqFVJtH8nEHG17Szezqj1KWRYbIxHSoMOpU06ogFDT6EF/gHtR3N6
ggafd6De3KlKkHthbBARskdTuAK0TUV4MfaA+IRElDMxdCl2x9rHRSxKBVySYMwI
Hd0FYHX/AgMBAAECggEADhK8954ioO3UAPqse5el8PfYCQQSKO7HCtSyOOEV3LDl
7lHUvsQzCln32xl+j+s6JjFIndQTiiihUR/KVqHw3Bl8ZUvv8yNOLe2oiiBEoDP4
cTlFv4nQRrMWpUol9f+vPUAMtIOy3unvzuGt9HIjiwTHDXU9tTF2Cs2sXdbGeTpW
ELL2SG1FXMLH08a66eIundAXMbtu06N8Mb36oDfx2rE/F77lozUmvoNWZ9W9BUW3
6zK+VRG6MO5TqaBN4BhKQ8gxr9w/ovh6z9aKEgHtvhE8c1Jjnt19vG6yy1A/VI8j
hSjIFZUIi/PE6VZCqs05uE7bb0ut9+5+yWBYbCaj3QKBgQDbITMAwAjTProm7eYk
GzIKegckRddv5Q06FfujOIoEpjnauXNCS3UHbkusDxr1WWnYOIabyQ/aUMaVffY6
VB+vZat8bV8T8sN3c4Zqkyoq5M7V8Z64A3vxrUbIwArAqh48/lS78D0Y60ItXkVD
VIK/LQ/zQ3x6UklD4Ev9WdRXxQKBgQC/4UTS+Y+G0iW9ig+CsRO7/m98vZJGW0n5
Skvm7qUGGmhurfEnOsDB+i8Qf9wMNj3xW+P5GNpkeo969XU48sPElcAog6c6Dhz3
HLCHtrArpULX/qoZ7VphRgP/xePjhYvqTlBT33rt2HODcChys7NuF6+GSld/9RQO
pXRhtdju8wKBgQDVvWNXZvj0vGmtET37l/9Oksqmie1jOoOVVd32zm5prI4gF+Yi
EyIa1m2/bZh5GvcQLcq25/6rj0C0joH/URD67+u+WZx1A8W/nRLOn69w2XAa5SxR
Byz9hmvV4uRaG1WVXurdyq59wPPy9tIOo79IpLa7LOedFOhb6cuVWuqxlQKBgF/F
iXugUpIhe/Lh4SIDTm1L7sudN1BkqkSCX+YxAS9NqQhtS2ugOKvZOvqKRwPVYw+A
JQak8ASs48akk1DMYwhREmtmYuZoOu7gZAApID94qidzFeYBAVaCAub8F+XtN0vI
sPFcH1ht7CITriyqIwn1SofFvWzBn7Q7wx4uDMwfAoGAe4IanzZZgk2lIopbtUb5
LuhH+22O+LUU3iZmftgQpAmVcwYy4DP8Sa8IgsH3Xn6QGlKKVVl17FEcuGev50/c
SqZeazLX6Zf/JoDEGPX25SBgeTGj+vV7NvMi/qSFmW0CuW2uFb64F2vAyu4wsix5
KvSSF8+a+Xqp5EXGFQNsj+4=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIILDzCCCfegAwIBAgISA8X5/0JomSBgXTptip67SBc9MA0GCSqGSIb3DQEBCwUA
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
EwNSMTAwHhcNMjQwODI3MDgxMTQzWhcNMjQxMTI1MDgxMTQyWjAlMSMwIQYDVQQD
Expsb2NhbGhvc3QubG9jYWxzdGFjay5jbG91ZDCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAKQ+mCTLVYyL0M66M+/eJwGEdNX+0p4BaX7tm4zQGRAyFYcL
PYxi04IhsvWNsfjVQ6YqY2MeCVs07TqzF1Zsy7CClj+cT19QRbcBjGygr88oH8ik
ngua4It4e3hGWpcbwE95JfpR5M/Tz/zJFOhplOAI2Os/fS6TcVJAMh/rCzEqFAwz
zwwRA5BeREZLQHsJ9rPZ8WZeIp4VgCglRjCxLTNWk/CoVUm0fycQcbXtLN7OqPUp
ZFhsjEdKgw6lTTqiAUNPoQX+Ae1Hc3qCBp93oN7cqUqQe2FsEBGyR1O4ArRNRXgx
9oD4hESUMzF0KXbH2sdFLEoFXJJgzAgd3QVgdf8CAwEAAaOCCCkwggglMA4GA1Ud
DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T
AQH/BAIwADAdBgNVHQ4EFgQUjL+KDrAll1/D9srF4e6/GwekaA0wHwYDVR0jBBgw
FoAUu7zDR6XkvKnGw6RyDBCNojXhyOgwVwYIKwYBBQUHAQEESzBJMCIGCCsGAQUF
BzABhhZodHRwOi8vcjEwLm8ubGVuY3Iub3JnMCMGCCsGAQUFBzAChhdodHRwOi8v
cjEwLmkubGVuY3Iub3JnLzCCBi4GA1UdEQSCBiUwggYhgicqLmFtcGxpZnlhcHAu
bG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCJyouY2xvdWRmcm9udC5sb2NhbGhv
c3QubG9jYWxzdGFjay5jbG91ZIIxKi5ka3IuZWNyLmV1LWNlbnRyYWwtMS5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLmV1LXdlc3QtMS5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMS5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLWVhc3QtMi5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMS5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIuKi5ka3IuZWNyLnVzLXdlc3QtMi5sb2Nh
bGhvc3QubG9jYWxzdGFjay5jbG91ZIIgKi5lbGIubG9jYWxob3N0LmxvY2Fsc3Rh
Y2suY2xvdWSCNCouZXUtY2VudHJhbC0xLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv
Y2Fsc3RhY2suY2xvdWSCMSouZXUtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0
LmxvY2Fsc3RhY2suY2xvdWSCKCouZXhlY3V0ZS1hcGkubG9jYWxob3N0LmxvY2Fs
c3RhY2suY2xvdWSCNCoubGFtYmRhLXVybC5ldS1jZW50cmFsLTEubG9jYWxob3N0
LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC5ldS13ZXN0LTEubG9jYWxo
b3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTEubG9j
YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy1lYXN0LTIu
bG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13ZXN0
LTEubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoubGFtYmRhLXVybC51cy13
ZXN0LTIubG9jYWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCHCoubG9jYWxob3N0Lmxv
Y2Fsc3RhY2suY2xvdWSCJyoub3BlbnNlYXJjaC5sb2NhbGhvc3QubG9jYWxzdGFj
ay5jbG91ZIInKi5zMy13ZWJzaXRlLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vk
gh8qLnMzLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgiAqLnNjbS5sb2NhbGhv
c3QubG9jYWxzdGFjay5jbG91ZIImKi5zbm93Zmxha2UubG9jYWxob3N0LmxvY2Fs
c3RhY2suY2xvdWSCMSoudXMtZWFzdC0xLm9wZW5zZWFyY2gubG9jYWxob3N0Lmxv
Y2Fsc3RhY2suY2xvdWSCMSoudXMtZWFzdC0yLm9wZW5zZWFyY2gubG9jYWxob3N0
LmxvY2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0xLm9wZW5zZWFyY2gubG9jYWxo
b3N0LmxvY2Fsc3RhY2suY2xvdWSCMSoudXMtd2VzdC0yLm9wZW5zZWFyY2gubG9j
YWxob3N0LmxvY2Fsc3RhY2suY2xvdWSCGmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNs
b3VkgitzcXMuZXUtY2VudHJhbC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3Vk
gihzcXMuZXUtd2VzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMu
dXMtZWFzdC0xLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtZWFz
dC0yLmxvY2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0xLmxv
Y2FsaG9zdC5sb2NhbHN0YWNrLmNsb3VkgihzcXMudXMtd2VzdC0yLmxvY2FsaG9z
dC5sb2NhbHN0YWNrLmNsb3VkMBMGA1UdIAQMMAowCAYGZ4EMAQIBMIIBBAYKKwYB
BAHWeQIEAgSB9QSB8gDwAHYASLDja9qmRzQP5WoC+p0w6xxSActW3SyB2bu/qznY
hHMAAAGRkxmXAAAABAMARzBFAiAekzpZ4BDa1pqeUT7RmPK/m+MY8KMNabKFg/AW
lAdDBQIhAOXsXbLaXnUbLXDr4Sx5p6VXFMHJ8d4Iyleny0QzvZMWAHYAdv+IPwq2
+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGRkxmXUwAABAMARzBFAiAb8ttM
ztUxiVtgiF0R9WZ8Bmo7q75rLd+q+IOuVcSySwIhAJjmKMGXopkCr5HT3p1WT3MP
1thDnNBYWL+0G0wKK1/OMA0GCSqGSIb3DQEBCwUAA4IBAQCmo2uic9k6jUNJluPS
07aZVZZtI8a3yV1/swTNucYWg0YcF5Wbv5d2LH1QXeLThVrMRow4uI/GMkOmiQYb
WJC9i3YdUf1rlBsi+/oQuXxGOh4l23ZhCjB+Ntp7XP69Sdg0qmd0v6qP6vrdsCRJ
q5HD26LR5Gw55DgApomVpdQa9AYgoF2aeKZbJ9RG1M6Fu4LoC5d4hw3QfYGSJd85
qttWgU+2dAGb70FhQO1dGQZwlFCSWEn0RtOVXhstw6TspP3i9lqsLyhPvWxs0TDX
H1mKmInXK+uo7B0YT/n2oZ9TVjqyuHQ9t30VFS4Ixslr/n7UlLhUV2msflQgUAa3
uaDS
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL
YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a
/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4
FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR
mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3
DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo
zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd
u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9
1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0
GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh
1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ
QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N
4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz
rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei
RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx
KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=
-----END CERTIFICATE-----
Loading