-
Notifications
You must be signed in to change notification settings - Fork 446
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
feat: add auto-tls service #2798
base: main
Are you sure you want to change the base?
Conversation
Adds an optional service that requests a Let's Encrypt-style TLS certificate when publicly dialable addresses are detected. This will allow transports such as WebSockets to upgrade themselves to be the secure version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just looking through the initial impl
packages/auto-tls/src/auto-tls.ts
Outdated
const response = await this.clientAuth.authenticatedFetch(`https://${this.forgeEndpoint}/v1/_acme-challenge`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify({ | ||
value: keyAuthorization, | ||
addresses | ||
}), | ||
...options | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is @libp2p/http-fetch
and not native fetch, but native fetch, if provided a bad forgeEndpoint
, would throw. Will @libp2p/http-fetch
?
should we catch that thrown error?
packages/auto-tls/src/auto-tls.ts
Outdated
this.clientAuth = new ClientAuth(this.privateKey) | ||
this.started = false | ||
this.fetching = false | ||
this.fetchCertificates = debounce(this._fetchCertificates.bind(this), init.delay ?? 5000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have 3 different fetchCertificate functions going on here.
fetchCertificates
- debounced _fetchCertificates defined in constructor_fetchCertificates
- function which guards against multiple fetch calls and ensures certs are not fetched if not appropriatefetchCertificate
- private method on class which does the actual work of fetching a certificate (i.e. called by_fetchCertificates
), and calls _fetchCertificate after renewalTimeout
I think the _fetchCertificates
and the debounced version make sense, but I think it could help clarify things a bit for future devs if we use better names to differentiate between all of these functions.
/** | ||
* How long before the expiry of the certificate to renew it in ms | ||
* | ||
* @default 60000 | ||
*/ | ||
renewThreshold?: number |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This situation is a little different than domain cert renewal, but cert renewal should allow for resolving any errors that pop up when a renewal is attempted. Should we set the renewal time to a full day or week before expiry instead of only one minute?
packages/interface/src/index.ts
Outdated
'certificate:provision': CustomEvent<TLSCertificate> | ||
|
||
/** | ||
* This event notifies listeners that a TLS certificate is available for use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* This event notifies listeners that a TLS certificate is available for use | |
* This event notifies listeners that a new TLS certificate is available for use |
const crypto = new Crypto() | ||
x509.cryptoProvider.set(crypto) | ||
|
||
type CertificateEvent = 'certificate:provision' | 'certificate:renew' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type CertificateEvent = 'certificate:provision' | 'certificate:renew' | |
type CertificateEvent = 'certificate:provision' | 'certificate:renew' | `certificate:load` |
add event for loading a cert during startup?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about doing something like this but it wasn't clear to me what the actual difference between certificate:provision
and certificate:load
would be, they both just mean "a certificate is available and one wasn't before", whereas certificate:renew
means "a certificate is available but you may need to undo what you did before to start using it".
@@ -0,0 +1,5 @@ | |||
describe('auto-tls', () => { | |||
it('should fetch a TLS certificate', async () => { | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure you are aware, but a callout here for some tests. Some I can think of:
- invalid forgeEndpoint expectations
- certifical renewal time
- certificate loading on startup (not implemented yet)
- event emitting
- triggering fetch of cert only on certain listening maddrs
Adds an optional service that requests a Let's Encrypt-style TLS certificate when publicly dialable addresses are detected.
This will allow transports such as WebSockets to upgrade themselves to be the secure version.
Change checklist