Skip to content

Commit

Permalink
Merge pull request #81 from NethServer/feat-7305-2
Browse files Browse the repository at this point in the history
Use TLS-ALPN-01 challenge

Refs NethServer/dev#7305
  • Loading branch information
DavidePrincipi authored Feb 19, 2025
2 parents 0b55c82 + fddda2a commit 7de5b7f
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 38 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,10 @@ Output (expanded format):
This action allows setting an ACME server that traefik will use to request the HTTPS certificates.
The default ACME server used is Let's Encrypt.

The action takes 1 parameter:
- `url`: ACME server URL
The action parameters are:
- `url`: ACME server URL (required)
- `email`: Email address for Let's Encrypt account and notifications (optional)
- `challenge`: one of `HTTP-01`, `TLS-ALPN-01` (optional)

Example:
```
Expand All @@ -326,7 +328,7 @@ api-cli run get-acme-server --agent module/traefik1

Output:
```
{"url": "https://acme-staging-v02.api.letsencrypt.org/directory"}
{"url": "https://acme-staging-v02.api.letsencrypt.org/directory", "email":"", "challenge":"HTTP-01"}
```

## upload-certificate
Expand Down
7 changes: 0 additions & 7 deletions imageroot/actions/create-module/05set_env
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,5 @@
import agent
import os

log_level = os.environ.get('LOG_LEVEL', 'INFO')
acme_server_url = os.environ.get('ACME_SERVER_URL', 'https://acme-v02.api.letsencrypt.org/directory')
le_email = os.environ.get('LE_EMAIL',"")
uuid = os.popen("uuidgen")

agent.set_env('LOG_LEVEL', log_level)
agent.set_env('ACME_SERVER_URL', acme_server_url)
agent.set_env('LE_EMAIL', le_email)
agent.set_env('API_PATH', uuid.read())
10 changes: 5 additions & 5 deletions imageroot/actions/create-module/10expandconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defaultEntryPoints:
file: {}
log:
level: $LOG_LEVEL
level: INFO
accessLog: {}
Expand All @@ -39,12 +39,12 @@ tls:
certificatesResolvers:
acmeServer:
acme:
email: ${LE_EMAIL}
caServer: ${ACME_SERVER_URL}
email: null
caServer: https://acme-v02.api.letsencrypt.org/directory
storage: /etc/traefik/acme/acme.json
httpChallenge:
entryPoint: http
tlsChallenge: false
entryPoint: https
tlsChallenge: {}
ping:
manualRouting: true
Expand Down
34 changes: 31 additions & 3 deletions imageroot/actions/get-acme-server/20readconfig
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
#!/usr/bin/env python3

#
# Copyright (C) 2023 Nethesis S.r.l.
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import agent
import json
import sys
import os
import conf_helpers

res = { "url": os.getenv('ACME_SERVER_URL') }
def main():
curconf = conf_helpers.parse_yaml_config("traefik.yaml")
try:
url = curconf['certificatesResolvers']['acmeServer']['acme']["caServer"]
except KeyError:
url = "https://acme-v02.api.letsencrypt.org/directory"
try:
email = curconf['certificatesResolvers']['acmeServer']['acme']["email"] or ""
except KeyError:
email = ""
try:
if curconf['certificatesResolvers']['acmeServer']['acme']['httpChallenge']['entryPoint'] == "https":
challenge = "TLS-ALPN-01"
elif curconf['certificatesResolvers']['acmeServer']['acme']['httpChallenge']['entryPoint'] == "http":
challenge = "HTTP-01"
else:
challenge = "HTTP-01"
except KeyError:
challenge = "HTTP-01"
response = {
"url": url,
"email": email,
"challenge": challenge,
}
json.dump(response, fp=sys.stdout)

print(json.dumps(res))
if __name__ == "__main__":
main()
34 changes: 31 additions & 3 deletions imageroot/actions/get-acme-server/validate-output.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,51 @@
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "get-acme-server output",
"$id": "http://schema.nethserver.org/traefik/get-acme-eserver-output.json",
"description": "Get the URL of the ACME server",
"description": "Get ACME configuration",
"examples": [
{
"challenge": "HTTP-01",
"email": "[email protected]",
"url": "https://acme-staging-v02.api.letsencrypt.org/directory"
},
{
"url": "https://acme-staging-v02.api.letsencrypt.org/directory"
}
],
"type": "object",
"required": ["url"],
"required": [
"challenge",
"email",
"url"
],
"additionalProperties": false,
"properties": {
"email": {
"oneOf": [
{
"type": "string",
"format": "email",
"description": "Address for expiration notifications"
},
{
"const": ""
}
]
},
"challenge": {
"type": "string",
"enum": [
"TLS-ALPN-01",
"HTTP-01"
]
},
"url": {
"type": "string",
"format": "uri",
"title": "Url of the ACME server",
"examples": [
"https://acme-staging-v02.api.letsencrypt.org/directory"
]
}
}
}
}
30 changes: 26 additions & 4 deletions imageroot/actions/set-acme-server/20writeconfig
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
#!/usr/bin/env python3

#
# Copyright (C) 2023 Nethesis S.r.l.
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

import agent
import json
import sys
import os
import conf_helpers
import agent

data = json.load(sys.stdin)
def main():
request = json.load(sys.stdin)
curconf = conf_helpers.parse_yaml_config("traefik.yaml")
curconf['certificatesResolvers']['acmeServer'].setdefault("acme", {
"caServer": "https://acme-v02.api.letsencrypt.org/directory",
"storage": "/etc/traefik/acme/acme.json",
"email": "",
"httpChallenge": {"entryPoint": "http"},
"tlsChallenge": False,
})
curconf['certificatesResolvers']['acmeServer']['acme']["caServer"] = request["url"]
curconf['certificatesResolvers']['acmeServer']['acme']["email"] = request.get("email", "")
if request.get("challenge") == "HTTP-01":
curconf['certificatesResolvers']['acmeServer']['acme']['httpChallenge']['entryPoint'] = 'http'
curconf['certificatesResolvers']['acmeServer']['acme']['tlsChallenge'] = False
elif request.get("challenge") == "TLS-ALPN-01":
curconf['certificatesResolvers']['acmeServer']['acme']['httpChallenge']['entryPoint'] = 'https'
curconf['certificatesResolvers']['acmeServer']['acme']['tlsChallenge'] = {}
# Changes to Traefik static configuration require a full container restart:
conf_helpers.write_yaml_config(curconf, "traefik.yaml")
agent.run_helper("systemctl", "--user", "restart", "traefik.service").check_returncode()

agent.set_env("ACME_SERVER_URL", data["url"])
if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion imageroot/actions/set-acme-server/30expandconfig

This file was deleted.

9 changes: 9 additions & 0 deletions imageroot/actions/set-acme-server/30expandconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

#
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

# Placeholder, see bug NethServer/dev#7058
exit 0
10 changes: 3 additions & 7 deletions imageroot/actions/set-acme-server/30restart_service
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
#!/bin/bash

#
# Copyright (C) 2023 Nethesis S.r.l.
# Copyright (C) 2025 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-3.0-or-later
#

set -e

exec 1>&2 # Send any output to stderr, to not alter the action response protocol

#restart the traefik service
systemctl --user restart traefik
# Placeholder, see bug NethServer/dev#7058
exit 0
36 changes: 31 additions & 5 deletions imageroot/actions/set-acme-server/validate-input.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "set-acme-server input",
"$id": "http://schema.nethserver.org/traefik/delete-route-input.json",
"description": "Set the URL of the ACME server",
"$id": "http://schema.nethserver.org/traefik/set-acme-server-input.json",
"description": "Set ACME configuration",
"examples": [
{
"challenge": "HTTP-01",
"email": "[email protected]",
"url": "https://acme-staging-v02.api.letsencrypt.org/directory"
},
{
"url": "https://acme-staging-v02.api.letsencrypt.org/directory"
}
],
"type": "object",
"required": ["url"],
"required": [
"url"
],
"additionalProperties": false,
"properties": {
"email": {
"oneOf": [
{
"type": "string",
"format": "email",
"description": "Address for expiration notifications"
},
{
"const": ""
}
]
},
"challenge": {
"type": "string",
"enum": [
"TLS-ALPN-01",
"HTTP-01"
]
},
"url": {
"type": "string",
"format": "uri",
"title": "Url of the ACME server",
"examples": [
"https://acme-staging-v02.api.letsencrypt.org/directory"
]
}
]
}
}
}
Empty file modified imageroot/actions/set-certificate/21waitsync
100644 → 100755
Empty file.

0 comments on commit 7de5b7f

Please sign in to comment.