@cloud-cli/le 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.prettierrc ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "printWidth": 120,
3
+ "tabWidth": 2,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": true,
7
+ "trailingComma": "all",
8
+ "bracketSpacing": true
9
+ }
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ ## LE
2
+
3
+ Lets Encrypt API
4
+
5
+ #### Usage
6
+
7
+ As a module:
8
+
9
+ ```ts
10
+ import le from '@cloud-cli/le';
11
+
12
+ le.start({ port: 4567 });
13
+
14
+ le.certificateExists({ domain: 'example.com' });
15
+ le.createCertificate({ domain: 'example.com', useWildcard: true });
16
+ le.removeCertificate({ domain: 'example.com' };
17
+
18
+ ```
19
+
20
+ With Cloudy CLI:
21
+
22
+ ```ts
23
+ import le from '@cloud-cli/le';
24
+ import { cli } from '@cloud-cli/cy';
25
+
26
+ cli.add('le', le);
27
+ ```
28
+
29
+ **start() options**
30
+
31
+ | Property | Type | Default |
32
+ | -------- | ------ | ----------- |
33
+ | `host` | String | '127.0.0.1' |
34
+ | `port` | Number | |
35
+
36
+ #### HTTP API
37
+
38
+ **Create a certificate**
39
+
40
+ ```
41
+ POST /certificates
42
+
43
+ {
44
+ "domain": "example.com",
45
+ "useWildcard": true,
46
+ }
47
+
48
+ ```
49
+
50
+ **Delete a certificate**
51
+
52
+ ```
53
+ DELETE /certificates/example.com
54
+ ```
55
+
56
+ **Check if a certificate exists**
57
+
58
+ ```
59
+ HEAD /certificates/example.com
60
+ ```
@@ -0,0 +1,21 @@
1
+ /// <reference types="node" />
2
+ export interface Certificate {
3
+ rootDomain: string;
4
+ certificate: string;
5
+ key: string;
6
+ }
7
+ export interface CertificateOptions {
8
+ domain: string;
9
+ }
10
+ export interface CreateCertificateOptions extends CertificateOptions {
11
+ useWildcard: boolean;
12
+ additionalOptions?: string[];
13
+ }
14
+ export declare class CertificateManager {
15
+ private readonly domainPattern;
16
+ certificateExists({ domain }: CertificateOptions): boolean;
17
+ createCertificate({ domain, useWildcard, additionalOptions }: CreateCertificateOptions): "OK" | import("child_process").SpawnSyncReturns<string>;
18
+ removeCertificate({ domain }: CertificateOptions): void;
19
+ getCertificateList(): string[];
20
+ private isValidDomain;
21
+ }
@@ -0,0 +1,42 @@
1
+ import { spawnSync as sh } from 'child_process';
2
+ import { existsSync, readdirSync, rmdirSync, statSync } from 'fs';
3
+ import { join } from 'path';
4
+ const certificatesFolder = process.env.LE_CERTS_DIR || join('/etc', 'letsencrypt', 'live');
5
+ export class CertificateManager {
6
+ constructor() {
7
+ this.domainPattern = /^[a-z0-9-.]+$/i;
8
+ }
9
+ certificateExists({ domain }) {
10
+ if (!this.isValidDomain(domain)) {
11
+ throw new Error('A domain is required');
12
+ }
13
+ return existsSync(join(certificatesFolder, domain));
14
+ }
15
+ createCertificate({ domain, useWildcard, additionalOptions }) {
16
+ if (!this.isValidDomain(domain)) {
17
+ throw new Error('Invalid domain: ' + domain);
18
+ }
19
+ const path = join(certificatesFolder, domain);
20
+ if (existsSync(path)) {
21
+ return 'OK';
22
+ }
23
+ const domains = [domain, useWildcard ? '*.' + domain : ''].filter(Boolean);
24
+ const domainsWithPrefix = domains.map((domain) => `-d${domain}`);
25
+ additionalOptions = (additionalOptions || []).map((option) => `--'${option}'`);
26
+ return sh('certbot', ['certonly', ...additionalOptions, ...domainsWithPrefix]);
27
+ }
28
+ removeCertificate({ domain }) {
29
+ const path = join(certificatesFolder, domain);
30
+ if (existsSync(path)) {
31
+ rmdirSync(path, { recursive: true });
32
+ }
33
+ }
34
+ getCertificateList() {
35
+ return readdirSync(certificatesFolder, { encoding: 'utf-8' }).filter((file) => {
36
+ return statSync(join(certificatesFolder, file)).isDirectory();
37
+ });
38
+ }
39
+ isValidDomain(domain) {
40
+ return domain && String(domain).length <= 253 && this.domainPattern.test(domain);
41
+ }
42
+ }
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { CertificateOptions, CreateCertificateOptions } from './certificate-manager.js';
3
+ export interface LetsEncryptConfiguration {
4
+ host?: string;
5
+ port: number;
6
+ }
7
+ declare const _default: {
8
+ createCertificate(certificate: CreateCertificateOptions): "OK" | import("child_process").SpawnSyncReturns<string>;
9
+ removeCertificate(options: CertificateOptions): void;
10
+ listCertificates(): string[];
11
+ certificateExists(options: CertificateOptions): boolean;
12
+ };
13
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { CertificateManager } from './certificate-manager.js';
2
+ const manager = new CertificateManager();
3
+ export default {
4
+ createCertificate(certificate) {
5
+ return manager.createCertificate(certificate);
6
+ },
7
+ removeCertificate(options) {
8
+ return manager.removeCertificate(options);
9
+ },
10
+ listCertificates() {
11
+ return manager.getCertificateList();
12
+ },
13
+ certificateExists(options) {
14
+ return manager.certificateExists(options);
15
+ },
16
+ };
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@cloud-cli/le",
3
+ "version": "1.0.0",
4
+ "description": "Reverse Proxy API/module",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "scripts": {
9
+ "test": "echo true",
10
+ "xtest": "./node_modules/.bin/ts-node ./node_modules/jasmine/bin/jasmine --config=./jasmine.json",
11
+ "tdd": "./node_modules/.bin/nodemon -w src -e ts -x ./node_modules/.bin/ts-node ./node_modules/jasmine/bin/jasmine --config=./jasmine.json",
12
+ "coverage": "./node_modules/.bin/nyc -r html -e .ts -x \"src/**/*.spec.ts\" npm run test",
13
+ "build": "rm -rf ./dist/* && tsc --project ./tsconfig.json",
14
+ "start": "node dist/index.js"
15
+ },
16
+ "keywords": [
17
+ "cloudy"
18
+ ],
19
+ "license": "MIT",
20
+ "author": "Darlan Alves <me@darlanalv.es>",
21
+ "devDependencies": {
22
+ "@types/jasmine": "^3.6.3",
23
+ "@types/node": "^14.14.31",
24
+ "jasmine": "^3.6.4",
25
+ "nodemon": "^2.0.7",
26
+ "nyc": "^15.1.0",
27
+ "ts-node": "^9.1.1",
28
+ "typescript": "^4.1.3"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/cloud-cli/le.git"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "@cloud-cli/gw": "^1.5.0"
39
+ }
40
+ }