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

Create an ES6 Class from lets-encrypt-acme-client.js #4

Merged
merged 3 commits into from
Dec 20, 2024
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
58 changes: 50 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,36 @@ Automatically Create and Renew `LetsEncrypt! SSL Certificates`, including `Wildc

### Getting Started

This most recent version of this package is implemented in [`SSL Server`](https://github.com/FirstTimeEZ/server-ssl) and you can use that to understand how it works if the `jsdoc` isn't enough information.
```javascript
import LetsEncryptDaemon from 'lets-encrypt-acme-client';
```

### Wild Card Certificates
#### Simple Usage Example

You can generate `Wild Card Certificates` if you are using a supported `DNS Provider`
Create a `LetsEncryptDaemon` and then start the `Daemon`

```javascript
const daemon = new LetsEncryptDaemon();
await daemon.startLetsEncryptDaemon(...); // You can only start this once, it will configure itself to run again.
daemon.checkChallengesMixin(...); // You must check the HTTP-01 Challenges for each LetsEncryptDaemon
```

#### Complete Example Usage

This most recent version of this package is implemented in [`SSL Server`](https://github.com/FirstTimeEZ/server-ssl)

You can use [`SSL Server`](https://github.com/FirstTimeEZ/server-ssl) to understand how it works if the `jsdoc` isn't enough information.

--------

### Wild Card Certificates

| Supported DNS Providers |
|-------------------------|
| Cloud Flare |

You can generate `Wild Card Certificates` if you are using a supported `DNS Provider`

```
let dnsProvider = {
name: "Cloud Flare",
Expand All @@ -28,11 +48,21 @@ let dnsProvider = {

### LetsEncrypt! Daemon

`LetsEncryptDaemon` is the default exported class

```javascript
const daemon = new LetsEncryptDaemon();
```

### Daemon

The `Daemon` runs periodically to `Create` or `Renew` the `Certificate`

### Jsdoc

```javascript
/**
* Starts the LetsEncrypt! Daemon to Manage the SSL Certificate for the Server
* Starts the LetsEncrypt! Daemon to Manage a SSL Certificate
*
* @param {Array<string>} fqdns - The fully qualified domain names as a SAN (e.g., ["example.com", "www.example.com"]), You must use a `dnsProvider` if you include a wild card
* @param {string} sslPath - The path where your acme account, keys and generated certificate will be stored or loaded from
Expand All @@ -50,7 +80,12 @@ The `Daemon` runs periodically to `Create` or `Renew` the `Certificate`
* @note
* If you start this more than once nothing will happen
*/
export async function startLetsEncryptDaemon(fqdns, sslPath, certificateCallback, optGenerateAnyway = false, optStaging = false, dnsProvider = undefined)
```

#### Usage

```javascript
await daemon.startLetsEncryptDaemon(fqdns, sslPath, certificateCallback, optGenerateAnyway = false, optStaging = false, dnsProvider = undefined)
```

### HTTP Mixin for `HTTP-01`
Expand All @@ -59,17 +94,24 @@ export async function startLetsEncryptDaemon(fqdns, sslPath, certificateCallback

This is not required if you are using a `DNS Provider`

### Jsdoc

```javascript
/**
* Node.js Middleware function to check and respond to ACME HTTP-01 challenges inside the HTTP Server.
* Node.js Middleware function to check and respond to ACME HTTP-01 challenges issued by this LetsEncryptDaemon inside the HTTP Server.
*
* @example
* createServerHTTP(async (req, res) => {
* if (STATE.optLetsEncrypt && await checkChallengesMixin(req, res)) { return; }
* if (STATE.optLetsEncrypt && checkChallengesMixin(req, res)) { return; }
* // normal request redirect etc
* }).listen(80);
*/
export async function checkChallengesMixin(req, res)
```

#### Usage

```javascript
if (daemon.checkChallengesMixin(req, res)) { return; } // Inside the HTTP Server
```

--------
Expand Down
64 changes: 64 additions & 0 deletions ext/ext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Copyright © 2024 FirstTimeEZ
* https://github.com/FirstTimeEZ
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* Checks if the given certificate text is valid.
* A valid certificate text starts with "-----BEGIN CERTIFICATE-----"
* and ends with "-----END CERTIFICATE-----" (with or without a newline).
*
* @param {string} certificateText - The certificate text to validate.
* @returns {boolean} True if the certificate text is valid, false otherwise.
*/
export function checkCertificateTextValid(certificateText) {
return certificateText.startsWith("-----BEGIN CERTIFICATE-----") && (certificateText.endsWith("-----END CERTIFICATE-----\n") || certificateText.endsWith("-----END CERTIFICATE-----") || certificateText.endsWith("-----END CERTIFICATE----- "));
}

/**
* Checks if the given private key is valid.
* A valid private key starts with "-----BEGIN PRIVATE KEY-----"
* and ends with "-----END PRIVATE KEY-----" (with or without a newline).
*
* @param {string} privateKey - The private key to validate.
* @returns {boolean} True if the private key is valid, false otherwise.
*/
export function checkPrivateKeyValid(privateKey) {
return privateKey.startsWith("-----BEGIN PRIVATE KEY-----") && (privateKey.endsWith("-----END PRIVATE KEY-----") || privateKey.endsWith("-----END PRIVATE KEY-----\n") || privateKey.endsWith("-----END PRIVATE KEY----- "))
}

/**
* Extracts challenges of a specific type from a list of authorizations.
* Each challenge is marked as unanswered and includes its associated domain
* and wildcard status.
*
* @param {Array} list - The list of authorizations containing challenges.
* @param {string} challengeType - The type of challenge to extract.
* @returns {Array} An array of challenges of the specified type.
*/
export function extractChallengeType(list, challengeType) {
const chals = [];

for (let index = 0; index < list.length; index++) {
const auth = list[index];

for (let i1 = 0; i1 < auth.get.challenges.length; i1++) {
const challenge = auth.get.challenges[i1];
challenge.type == challengeType && (challenge.answered = false, challenge.domain = auth.get.identifier.value, challenge.wildcard = auth.get.wildcard ? auth.get.wildcard : false, chals.push(challenge));
}
}

return chals;
}
Loading