WIP: HTTP-01 solver that stores challenge tokens in FrostFS #4

Draft
potyarkin wants to merge 9 commits from potyarkin/lego:feature/http-01-frostfs-solver into tcl/http-01-frostfs-solver
Member

This PR is based on the latest Lego release (v4.19.2) and adds a new HTTP-01 solver (in addition to existing ones: s3, memcached, webroot).

New solver saves challenge tokens to FrostFS container which is expected to be exposed via FrostFS HTTP gateway on relevant domain(s) via /.well-known/acme-challenge path.

This will allow any user with valid FrostFS credentials to obtain a Let's Encrypt certificate for gateway domain. That's useful for:

  • Deploying multiple FrostFS HTTP gateways with the same domain name (CDN and similar scenarios)
  • Obtaining TLS certificates on machines which are not connectable from outer Internet but are able to make outgoing connections to FrostFS API and ACME API endpoints (e.g. machines behind NAT)

Security considerations:

  • Any user with write access to specified FrostFS container will be able to obtain TLS certificates for HTTP gateways' domain name. The container ACL must be configured accordingly
  • Read access to container is not as sensitive: ACME challenge tokens are public by design

Example reverse proxy config for Angie/Nginx:

# Extract file name from request URI
map $request_uri $request_basename {
    ~/(?<captured_request_basename>[^/?]*)(?:\?|$) $captured_request_basename;
}

...

# Proxy requests to HTTP gateway
location /.well-known/acme-challenge {
    proxy_pass http://frostfs-http-gateway.tld/get_by_attribute/$FROSTFS_CONTAINER/ACME/$request_basename;
}

Implementation details:

  • Tokens are saved to objects with __SYSTEM__EXPIRATION_EPOCH set to near future. This means that even if solver cleanup call fails the garbage will be automatically collected by FrostFS itself
  • FrostFS credentials are configured via Lego CLI args and/or corresponding environment variables (see cmd/flags.go)
  • Unit tests check that FrostFS client works but do not check the whole ACME API interaction end-to-end

TODO:

  • Add solver README
  • Troubleshoot token deletion bug (racy, likely upstream)
This PR is based on the latest Lego release ([v4.19.2](https://git.frostfs.info/TrueCloudLab/lego/releases/tag/v4.19.2)) and adds a new HTTP-01 solver (in addition to existing ones: [s3](https://git.frostfs.info/TrueCloudLab/lego/src/tag/v4.19.2/providers/http/s3), [memcached](https://git.frostfs.info/TrueCloudLab/lego/src/tag/v4.19.2/providers/http/memcached), [webroot](https://git.frostfs.info/TrueCloudLab/lego/src/tag/v4.19.2/providers/http/webroot)). New solver saves challenge tokens to FrostFS container which is expected to be exposed via FrostFS HTTP gateway on relevant domain(s) via `/.well-known/acme-challenge` path. This will allow any user with valid FrostFS credentials to obtain a Let's Encrypt certificate for gateway domain. That's useful for: - Deploying multiple FrostFS HTTP gateways with the same domain name (CDN and similar scenarios) - Obtaining TLS certificates on machines which are not connectable from outer Internet but are able to make outgoing connections to FrostFS API and ACME API endpoints (e.g. machines behind NAT) Security considerations: - Any user with write access to specified FrostFS container will be able to obtain TLS certificates for HTTP gateways' domain name. The container ACL must be configured accordingly - Read access to container is not as sensitive: ACME challenge tokens are public by design Example reverse proxy config for Angie/Nginx: ``` # Extract file name from request URI map $request_uri $request_basename { ~/(?<captured_request_basename>[^/?]*)(?:\?|$) $captured_request_basename; } ... # Proxy requests to HTTP gateway location /.well-known/acme-challenge { proxy_pass http://frostfs-http-gateway.tld/get_by_attribute/$FROSTFS_CONTAINER/ACME/$request_basename; } ``` Implementation details: - Tokens are saved to objects with `__SYSTEM__EXPIRATION_EPOCH` set to near future. This means that even if solver cleanup call fails the garbage will be automatically collected by FrostFS itself - FrostFS credentials are configured via Lego CLI args and/or corresponding environment variables (see `cmd/flags.go`) - Unit tests check that FrostFS client works but do not check the whole ACME API interaction end-to-end TODO: - [ ] Add solver README - [ ] Troubleshoot token deletion bug (racy, likely upstream)
potyarkin added 9 commits 2024-10-17 09:03:37 +00:00
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Ephemeral keys worked fine while keys loaded from filesystem would
generate invalid signatures. This was caused by destroying private key
material during calls to Wallet.Close() and Account.Close(). Since these
calls do nothing except wiping the private key, we omit them now.
Responsibility for private key security is delegated to caller of getKey()

Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Current reverse proxy configs assume that token is a valid filename
with no nesting levels. It's better to reject unsupported tokens early

Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
Signed-off-by: Vitaliy Potyarkin <v.potyarkin@yadro.com>
potyarkin referenced this pull request from a commit 2024-11-12 14:04:36 +00:00
Author
Member

I suggest to leave this PR in a "WIP" status indefinitely:

  • There is little to no demand for this feature as part of Lego binary, even from us. We've moved onto using Lego as a library in our custom certificate management tool - solving ACME challenges is the smallest of its features.
  • Most of the code in this PR is either FrostFS client or Lego CLI boilerplate. The solver itself is trivial in comparison.

Maintaining a patch set on top of a moving target (upstream Lego releases) seems pointless if no one will be using it. When/if such need will arise we will be able to quickly implement the solver on top of the latest Lego / FrostFS using this PR as a blueprint.

I suggest to leave this PR in a "WIP" status indefinitely: - There is little to no demand for this feature as part of Lego binary, even from us. We've moved onto using Lego as a library in our [custom certificate management tool](https://git.frostfs.info/potyarkin/frostfs-gw-cert) - solving ACME challenges is the smallest of its features. - Most of the code in this PR is either FrostFS client or Lego CLI boilerplate. [The solver](https://git.frostfs.info/TrueCloudLab/lego/pulls/4/files#diff-3f2baaa6872e8e2af128604f9d36c6d0b0afc120) itself is trivial in comparison. Maintaining a patch set on top of a moving target (upstream Lego releases) seems pointless if no one will be using it. When/if such need will arise we will be able to quickly implement the solver on top of the latest Lego / FrostFS using this PR as a blueprint.
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u feature/http-01-frostfs-solver:potyarkin-feature/http-01-frostfs-solver
git checkout potyarkin-feature/http-01-frostfs-solver

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git checkout tcl/http-01-frostfs-solver
git merge --no-ff potyarkin-feature/http-01-frostfs-solver
git checkout potyarkin-feature/http-01-frostfs-solver
git rebase tcl/http-01-frostfs-solver
git checkout tcl/http-01-frostfs-solver
git merge --ff-only potyarkin-feature/http-01-frostfs-solver
git checkout potyarkin-feature/http-01-frostfs-solver
git rebase tcl/http-01-frostfs-solver
git checkout tcl/http-01-frostfs-solver
git merge --no-ff potyarkin-feature/http-01-frostfs-solver
git checkout tcl/http-01-frostfs-solver
git merge --squash potyarkin-feature/http-01-frostfs-solver
git checkout tcl/http-01-frostfs-solver
git merge --ff-only potyarkin-feature/http-01-frostfs-solver
git checkout tcl/http-01-frostfs-solver
git merge potyarkin-feature/http-01-frostfs-solver
git push origin tcl/http-01-frostfs-solver
Sign in to join this conversation.
No description provided.