Skip to content
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

Domain server ACME client with custom Web UI. #1540

Merged
merged 65 commits into from
May 31, 2022

Conversation

namark
Copy link
Contributor

@namark namark commented Dec 17, 2021

Based on #1456

  • HTTP API for acme client status checks and file uploads.
  • Web UI for acme client configuration (same as settings section but more convenient)
  • Web UI file uploads
  • Web UI look and feel improvements
  • Web UI status checks
  • ACME External Account Binding and ZeroSSL specific account handling
  • ZeroSSL REST API support (currently the only way to do certificate automation for IP addresses)

This PR includes some functional improvements to the ACME client, and a custom interactive WEB UI for configuring it. The UI is written in plain JS and HTML to be independent of the rest of the settings panel, and to make it easier to convert to any other framework. It's available under SSL/ACME Configuration in the settings panel, or directly under http://localhost:40100/ssl-acme-client/. It communicates through HTTP with domain server using the settings.json API and a new API for uploading files and interacting with the ACME client; and with ACME server to retrieve some server specific information like terms of service, or authentication information. The UI has two major sections "Automatic Management" and "Certificate Paths".

Under certificate paths the directory and file names for certificate, its key and optional trusted authority list can be specified and local files selected for upload. All settings are submitted and files uploaded using the "Save Settings" button at the bottom. There is also a "Reset Certificate" button that will simply delete the certificate and its key (useful when automatic management is enabled to force a new certificate to be generated).

The bulk of the functionality of the client is in the automatic management, where, once enabled, the following settings should become visible:

  • CA directory - this the ACME directory URL of the certificate authority. There are 4 defaults to select from, Let's Encrypt production, Let's Encrypt staging, ZeroSSL ACME, and ZeroSSL REST (which is not an ACME protocol), as well as an option to specify a custom URL. Once Selected the UI will request basic information from the directory and update the the rest of the elements accordingly.
  • Authentication method - this is the method of authentication with the certificate issuer. Account Key option is the simplest, and requires no additional configuration. This is the only option for Let's Encrypt, but not available for ZeroSSL. ID and MAC key are the standard for authentication with ACME protocol and all servers that require extra authentication must provide these. ZeroSSL Email and ZeroSSL API key are convenience features, that allow retrieving the standard ID and MAC key using ZeroSSL user email or API key.
  • Challenge completion method - ACME server might require proof of ownership of the domain, which is achieved by completing some automatic challenges. There are various options available in general, using DNS records, HTTP endpoints, or TLS handshake, but domain server ACME client currently only supports automation for HTTP. With the default Server option the client will attempt to host the challenge data on required HTTP endpoints on port 80 (required by ACME standard), once it receives the challenges from the server. If you already have a site hosted on port 80, to avoid downtime and allow automatic renewal you can choose the Files option, in which case the client will save the challenges as files in configurable per domain directories. For debugging and testing purposes Manual option can be selected where the client will display the challenges it got and wait for a couple of minutes before proceeding, for them to be completed manually.
  • Account key - Similar to in Certificate Paths section you can use this interface to configure the path of and upload the private key used for communicating with the ACME server. This is optional and will be generated automatically if not provided.
  • Domains - Here you can specify a list of domains to generate the certificate for, and optionally directories where to save ACME challenges if challenge completion method is set to Files.

Once everything is configures and settings are saved with automation enabled, the ACME client will attempt to create a certificate, or if one already exists - schedule a renewal. The Status checkbox will show a text area with JSON formatted status of the process. The "Restart Client" button will restart the ACME client without restarting the whole server. In combination with the "Reset Certificate" button it can be used to manually force the certificate to be regenerated. It can also be useful to manually retry a failed renewal.

Renewals are schedule at 2/3 of the expiry duration of the certificate (typical duration is 90 days, so they will be scheduled 30 days in advance). If the renewal (or certificate generation in general) fails it will be scheduled to repeat in 24 hours.

Even if automation is disabled the ACME client will perform renewal checks every 24 hours and notify other subsystems of the domain server (currently just WebRTCSignalling server) if the certificate was renewed. This allows the user to use third party clients for automation (assuming certificate paths properly configured).

Note on Certificates for IP addresses: In the Domains section IP addresses(both v4 and v6) can be specified instead of domain names. Generating certificates for IP addresses is an extension of the ACME standard that this client implementation supports, but neither Let's Encrypt not ZeroSSL do unfortunately. This might change in the future, but in the meanwhile ZeroSSL REST API is available as CA directory option for that use case, even though it's not an actual ACME directory endpoint.

Some testing scenarios

These assume domain server (and assignment clients) are set up on a public server with port 80 available for HTTP hosting and that the Web SDK example is built and hosted locally.

Generating a certificate for a domain name:

  1. In the domain server web panel navigate to SSL/ACME Configuration.
  2. In Automatic Management section set the Enable checkbox, new settings should appear.
  3. In the Domains section enter the domain name of the server.
  4. At the very bottom set the Status checkbox, a text-area should appear that will contain the current status of the acme client in JSON format.
  5. Press the Save Settings button at the bottom.
  6. Wait for directory, account and certificate fields of the status JSON to have their status fields set to "ok".
  7. Navigate back to previous menu (Back to settings menu link at the top), Under Settings -> Networking/WebRTC check the two boxes "Enable WebRTC Client Connections" and "Enable WebRTC WebSocket SSL" and Save. Wait for domain server to restart.
  8. Open the WebSDK example page, in the IP address field enter the domain name with wss:// protocol (default is ws:// protocol) and 40102 port, for example wss://example.com:40102
  9. Wait for Status to become connected and make sure there are no errors in the dev console. Can also test some basic web sdk functionality here like audio.

Generating a certificate for an IP:

  1. Register an account with ZeroSSL.
  2. In the domain server web panel navigate to SSL/ACME Configuration.
  3. In CA directory drop-down select ZeroSSL REST.
  4. In the Authentication method dropd-own ZeroSSL API key should now be selected, next to it enter the API key of your ZeroSSL account, that should be available on the developer page there.
  5. In the Domains section enter the IP address of the server.
  6. Go through points 4-9 of the above scenario.

General coding style changes (incomplete)
API changed to support asynchronous operation with callbacks (incomplete)
Error handling improvements (incomplete)
Curl replaced with Qt (complete)
successfully ordering a certificate and receiving an http challenge.
API changed to support asynchronous operation with callbacks (complete)
Curl replaced with Qt (complete)
General coding style changes (incomplete)
Error handling improvements (incomplete)

A certificate successfully generated by manually completing the http
challenge.
along with a short self-check before continuing with verification.
Certificate files and client key stored in application data path by
default,
Trusted CA file is made optional.
with simple directory url configuration functionality.
Also reporting status on errors and HTTP API enabled regardless of
"enabled" setting.
@namark namark mentioned this pull request Feb 13, 2022
3 tasks
domain-server/resources/describe-settings.json Outdated Show resolved Hide resolved
domain-server/resources/web/ssl-acme-client/index.html Outdated Show resolved Hide resolved
domain-server/resources/web/ssl-acme-client/index.html Outdated Show resolved Hide resolved
domain-server/resources/web/ssl-acme-client/index.html Outdated Show resolved Hide resolved
domain-server/resources/web/ssl-acme-client/index.html Outdated Show resolved Hide resolved
domain-server/resources/web/ssl-acme-client/js/api.js Outdated Show resolved Hide resolved
domain-server/src/DomainServerAcmeClient.cpp Outdated Show resolved Hide resolved
}

void operator()(acme_lw::Response) const {
// TODO: check content
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

domain-server/src/DomainServerAcmeClient.cpp Outdated Show resolved Hide resolved
setError(status["certificate"], "invalid", {
{"message", message}
});
// TODO: report a proper error, IO error, bad certificate etc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

@namark
Copy link
Contributor Author

namark commented Apr 20, 2022

The two TODOs @ctrlaltdavid pointed out are not critical, they're just meant to improve diagnostics of some rare errors, so I think it's fine to merge. I'll address them over time, whenever I come back to this to do something more substantial.

@ctrlaltdavid ctrlaltdavid added CR Approved At least one code reviewer has approved the PR. needs testing (QA) The PR is ready for testing and removed needs CR (code review) labels Apr 25, 2022
@digisomni digisomni added this to the 2022.1.2 Selene Release milestone Apr 26, 2022
@namark namark changed the title Domain server ACME client custom WEB UI Domain server ACME client with custom Web UI. May 1, 2022
@vircadia-build-notifier

@Gigabyte5671
Copy link
Member

Tested the second scenario (Generating a certificate for an IP) on Windows 11 Build 22621. Worked correctly.

@digisomni digisomni added QA Approved The PR has been tested successfully. and removed needs testing (QA) The PR is ready for testing labels May 31, 2022
@digisomni digisomni merged commit 4cc2f15 into vircadia:master May 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
allow-build-upload Allows the upload of a build for non white-listed users CR Approved At least one code reviewer has approved the PR. QA Approved The PR has been tested successfully. rebuild rebuild through the GithubActions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

SSL cert management should have automation (ACME) and ability to upload custom certs through web.
5 participants