Skip to content
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@ version.
| `HTTP_IDLE_TIMEOUT` | The maximum time in seconds that a client can be idle before the connection is closed. | 60 |
| `HTTP_READ_TIMEOUT` | The maximum time in seconds that a client can take to send the request headers. | 30 |
| `HTTP_WRITE_TIMEOUT` | The maximum time in seconds during which the client must read the response. | 30 |
| `ACME_DIRECTORY` | The URL of the ACME directory to use for SSL certificate provisioning. | `https://acme-v02.api.letsencrypt.org/directory` (Let's Encrypt production) |
| `EAB_KID` | The EAB key identifier to use when provisioning SSL certificates, if required. | None |
| `EAB_HMAC_KEY` | The Base64-encoded EAB HMAC key to use when provisioning SSL certificates, if required. | None |
| `DEBUG` | Set to `1` or `true` to enable debug logging. | Disabled |
25 changes: 17 additions & 8 deletions internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"os"
"strconv"
"time"

"golang.org/x/crypto/acme"
)

const (
Expand All @@ -20,8 +22,9 @@ const (
defaultMaxCacheItemSizeBytes = 1 * MB
defaultMaxRequestBody = 0

defaultStoragePath = "./storage/thruster"
defaultBadGatewayPage = "./public/502.html"
defaultACMEDirectoryURL = acme.LetsEncryptURL
defaultStoragePath = "./storage/thruster"
defaultBadGatewayPage = "./public/502.html"

defaultHttpPort = 80
defaultHttpsPort = 443
Expand All @@ -42,9 +45,12 @@ type Config struct {
XSendfileEnabled bool
MaxRequestBody int

SSLDomain string
StoragePath string
BadGatewayPage string
SSLDomain string
ACMEDirectoryURL string
EAB_KID string
EAB_HMACKey string
StoragePath string
BadGatewayPage string

HttpPort int
HttpsPort int
Expand Down Expand Up @@ -75,9 +81,12 @@ func NewConfig() (*Config, error) {
XSendfileEnabled: getEnvBool("X_SENDFILE_ENABLED", true),
MaxRequestBody: getEnvInt("MAX_REQUEST_BODY", defaultMaxRequestBody),

SSLDomain: getEnvString("SSL_DOMAIN", ""),
StoragePath: getEnvString("STORAGE_PATH", defaultStoragePath),
BadGatewayPage: getEnvString("BAD_GATEWAY_PAGE", defaultBadGatewayPage),
SSLDomain: getEnvString("SSL_DOMAIN", ""),
ACMEDirectoryURL: getEnvString("ACME_DIRECTORY", defaultACMEDirectoryURL),
EAB_KID: getEnvString("EAB_KID", ""),
EAB_HMACKey: getEnvString("EAB_HMAC_KEY", ""),
StoragePath: getEnvString("STORAGE_PATH", defaultStoragePath),
BadGatewayPage: getEnvString("BAD_GATEWAY_PAGE", defaultBadGatewayPage),

HttpPort: getEnvInt("HTTP_PORT", defaultHttpPort),
HttpsPort: getEnvInt("HTTPS_PORT", defaultHttpsPort),
Expand Down
2 changes: 2 additions & 0 deletions internal/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestConfig_override_defaults_with_env_vars(t *testing.T) {
usingEnvVar(t, "HTTP_READ_TIMEOUT", "5")
usingEnvVar(t, "X_SENDFILE_ENABLED", "0")
usingEnvVar(t, "DEBUG", "1")
usingEnvVar(t, "ACME_DIRECTORY", "https://acme-staging-v02.api.letsencrypt.org/directory")

c, err := NewConfig()
require.NoError(t, err)
Expand All @@ -37,6 +38,7 @@ func TestConfig_override_defaults_with_env_vars(t *testing.T) {
assert.Equal(t, 5*time.Second, c.HttpReadTimeout)
assert.Equal(t, false, c.XSendfileEnabled)
assert.Equal(t, slog.LevelDebug, c.LogLevel)
assert.Equal(t, "https://acme-staging-v02.api.letsencrypt.org/directory", c.ACMEDirectoryURL)
}

func TestConfig_override_defaults_with_env_vars_using_prefix(t *testing.T) {
Expand Down
32 changes: 29 additions & 3 deletions internal/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package internal

import (
"context"
"encoding/base64"
"fmt"
"log/slog"
"net"
"net/http"
"time"

"golang.org/x/crypto/acme"
"golang.org/x/crypto/acme/autocert"
)

Expand Down Expand Up @@ -68,10 +70,34 @@ func (s *Server) Stop() {
}

func (s *Server) certManager() *autocert.Manager {
client := &acme.Client{DirectoryURL: s.config.ACMEDirectoryURL}
binding := s.externalAccountBinding()

slog.Debug("SSL: initializing", "directory", client.DirectoryURL, "using_eab", binding != nil)

return &autocert.Manager{
Cache: autocert.DirCache(s.config.StoragePath),
HostPolicy: autocert.HostWhitelist(s.config.SSLDomain),
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache(s.config.StoragePath),
Client: client,
ExternalAccountBinding: binding,
HostPolicy: autocert.HostWhitelist(s.config.SSLDomain),
Prompt: autocert.AcceptTOS,
}
}

func (s *Server) externalAccountBinding() *acme.ExternalAccountBinding {
if s.config.EAB_KID == "" || s.config.EAB_HMACKey == "" {
return nil
}

key, err := base64.RawURLEncoding.DecodeString(s.config.EAB_HMACKey)
if err != nil {
slog.Error("Error decoding EAB_HMACKey", "error", err)
return nil
}

return &acme.ExternalAccountBinding{
KID: s.config.EAB_KID,
Key: key,
}
}

Expand Down