@sequencemedia/certificates 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/README.md +21 -0
- package/README.txt +19 -0
- package/babel.config.cjs +21 -0
- package/ca-and-certs.bat +16 -0
- package/ca-and-certs.mjs +101 -0
- package/ca-and-certs.sh +15 -0
- package/certs.bat +10 -0
- package/certs.mjs +101 -0
- package/certs.sh +11 -0
- package/package.json +45 -0
- package/scripts/bat/certificate-authority-crt.bat +2 -0
- package/scripts/bat/certificate-authority-key-pem.bat +5 -0
- package/scripts/bat/localhost-crt.bat +2 -0
- package/scripts/bat/localhost-csr.bat +5 -0
- package/scripts/js/config.mjs +29 -0
- package/scripts/js/ext.mjs +39 -0
- package/scripts/js/to-subj.mjs +16 -0
- package/scripts/sh/certificate-authority-crt.sh +5 -0
- package/scripts/sh/certificate-authority-key-pem.sh +18 -0
- package/scripts/sh/localhost-crt.sh +9 -0
- package/scripts/sh/localhost-csr.sh +16 -0
- package/where-am-i.mjs +8 -0
package/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# @sequencemedia/certificates
|
2
|
+
|
3
|
+
## Pre-requisites for Windows
|
4
|
+
|
5
|
+
Install the latest pre-built release of OpenSSL
|
6
|
+
|
7
|
+
### Install with an MSI
|
8
|
+
|
9
|
+
Get an MSI from the [Win32/Win64 OpenSSL Installation Project](https://slproweb.com/products/Win32OpenSSL.html) (e.g., [3.0.7](https://slproweb.com/download/Win64OpenSSL-3_0_7.msi))
|
10
|
+
|
11
|
+
### Or install with Chocolatey
|
12
|
+
|
13
|
+
```
|
14
|
+
choco install openssl
|
15
|
+
```
|
16
|
+
|
17
|
+
### Add OpenSSL to the `PATH`
|
18
|
+
|
19
|
+
An [article on Medium](https://medium.com/swlh/installing-openssl-on-windows-10-and-updating-path-80992e26f6a1) also refers to the [OpenSSL Installation Project](https://slproweb.com/products/Win32OpenSSL.html) and describes (with screenshots) how to add OpenSSL to the `PATH`
|
20
|
+
|
21
|
+
Once you have added OpenSSL to the `PATH`, open a console and at the command prompt enter `openssl version` to confirm the installation
|
package/README.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
https://betterprogramming.pub/how-to-create-trusted-ssl-certificates-for-your-local-development-13fd5aad29c6
|
2
|
+
|
3
|
+
https://www.section.io/engineering-education/how-to-get-ssl-https-for-localhost/
|
4
|
+
|
5
|
+
https://www.digicert.com/kb/ssl-support/openssl-quick-reference-guide.htm
|
6
|
+
|
7
|
+
https://www.ietf.org/rfc/rfc4514.txt
|
8
|
+
|
9
|
+
String X.500 AttributeType
|
10
|
+
------ --------------------------------------------
|
11
|
+
CN commonName (2.5.4.3)
|
12
|
+
L localityName (2.5.4.7)
|
13
|
+
ST stateOrProvinceName (2.5.4.8)
|
14
|
+
O organizationName (2.5.4.10)
|
15
|
+
OU organizationalUnitName (2.5.4.11)
|
16
|
+
C countryName (2.5.4.6)
|
17
|
+
STREET streetAddress (2.5.4.9)
|
18
|
+
DC domainComponent (0.9.2342.19200300.100.1.25)
|
19
|
+
UID userId (0.9.2342.19200300.100.1.1)
|
package/babel.config.cjs
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
const debug = require('debug')
|
2
|
+
|
3
|
+
const log = debug('@sequencemedia/certificates')
|
4
|
+
|
5
|
+
log('`localhost` is awake')
|
6
|
+
|
7
|
+
module.exports = {
|
8
|
+
compact: true,
|
9
|
+
comments: false,
|
10
|
+
presets: [
|
11
|
+
[
|
12
|
+
'@babel/env', {
|
13
|
+
targets: {
|
14
|
+
node: 'current'
|
15
|
+
},
|
16
|
+
useBuiltIns: 'usage',
|
17
|
+
corejs: 3
|
18
|
+
}
|
19
|
+
]
|
20
|
+
]
|
21
|
+
}
|
package/ca-and-certs.bat
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
@echo off
|
2
|
+
|
3
|
+
if defined 1 (
|
4
|
+
set SUBJ=%1
|
5
|
+
) else (
|
6
|
+
set SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
7
|
+
)
|
8
|
+
|
9
|
+
setlocal enableextensions
|
10
|
+
md certificates
|
11
|
+
endlocal
|
12
|
+
|
13
|
+
call scripts/bat/certificate-authority-key-pem.bat
|
14
|
+
call scripts/bat/certificate-authority-crt.bat
|
15
|
+
call scripts/bat/localhost-csr.bat
|
16
|
+
call scripts/bat/localhost-crt.bat
|
package/ca-and-certs.mjs
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
import debug from 'debug'
|
2
|
+
import os from 'node:os'
|
3
|
+
import ip from 'ip'
|
4
|
+
import {
|
5
|
+
exec
|
6
|
+
} from 'node:child_process'
|
7
|
+
import PATH from './where-am-i.mjs'
|
8
|
+
import config from './scripts/js/config.mjs'
|
9
|
+
import ext from './scripts/js/ext.mjs'
|
10
|
+
import toSubj from './scripts/js/to-subj.mjs'
|
11
|
+
|
12
|
+
const OPTIONS = {
|
13
|
+
maxBuffer: 1024 * 2000,
|
14
|
+
shell: true,
|
15
|
+
stdio: 'inherit'
|
16
|
+
}
|
17
|
+
|
18
|
+
const HOSTNAME = os.hostname()
|
19
|
+
const ADDRESS = ip.address()
|
20
|
+
const PLATFORM = os.platform()
|
21
|
+
|
22
|
+
const log = debug('@sequencemedia/certificates')
|
23
|
+
const info = debug('@sequencemedia/certificates:info')
|
24
|
+
const error = debug('@sequencemedia/certificates:error')
|
25
|
+
|
26
|
+
function bat (params) {
|
27
|
+
const command = `ca-and-certs.bat "${toSubj(params)}"`
|
28
|
+
|
29
|
+
info(command)
|
30
|
+
|
31
|
+
return (
|
32
|
+
new Promise((resolve, reject) => {
|
33
|
+
exec(command, { ...OPTIONS, cwd: PATH }, (e) => (!e) ? resolve() : reject(e))
|
34
|
+
})
|
35
|
+
)
|
36
|
+
}
|
37
|
+
|
38
|
+
function sh (params) {
|
39
|
+
const command = `./ca-and-certs.sh "${toSubj(params)}"`
|
40
|
+
|
41
|
+
info(command)
|
42
|
+
|
43
|
+
return (
|
44
|
+
new Promise((resolve, reject) => {
|
45
|
+
exec(command, { ...OPTIONS, cwd: PATH }, (e) => (!e) ? resolve() : reject(e))
|
46
|
+
})
|
47
|
+
)
|
48
|
+
}
|
49
|
+
|
50
|
+
log('`ca-and-certs` is awake')
|
51
|
+
|
52
|
+
async function app () {
|
53
|
+
try {
|
54
|
+
await ext(HOSTNAME, ADDRESS)
|
55
|
+
|
56
|
+
const {
|
57
|
+
country,
|
58
|
+
state,
|
59
|
+
locality,
|
60
|
+
organisation,
|
61
|
+
commonName,
|
62
|
+
emailAddress
|
63
|
+
} = config
|
64
|
+
|
65
|
+
info({
|
66
|
+
country,
|
67
|
+
state,
|
68
|
+
locality,
|
69
|
+
organisation,
|
70
|
+
commonName,
|
71
|
+
emailAddress
|
72
|
+
})
|
73
|
+
|
74
|
+
return (PLATFORM === 'win32')
|
75
|
+
? await bat({
|
76
|
+
country,
|
77
|
+
state,
|
78
|
+
locality,
|
79
|
+
organisation,
|
80
|
+
commonName,
|
81
|
+
emailAddress
|
82
|
+
})
|
83
|
+
: await sh({
|
84
|
+
country,
|
85
|
+
state,
|
86
|
+
locality,
|
87
|
+
organisation,
|
88
|
+
commonName,
|
89
|
+
emailAddress
|
90
|
+
})
|
91
|
+
} catch ({
|
92
|
+
code = 'N/A',
|
93
|
+
message = 'N/A'
|
94
|
+
}) {
|
95
|
+
error(code, message)
|
96
|
+
|
97
|
+
process.exit(1)
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
export default app()
|
package/ca-and-certs.sh
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [ -z "$1" ]
|
4
|
+
then
|
5
|
+
SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
6
|
+
else
|
7
|
+
SUBJ=$1
|
8
|
+
fi
|
9
|
+
|
10
|
+
mkdir certificates 2> /dev/null
|
11
|
+
|
12
|
+
source scripts/sh/certificate-authority-key-pem.sh
|
13
|
+
source scripts/sh/certificate-authority-crt.sh
|
14
|
+
source scripts/sh/localhost-csr.sh
|
15
|
+
source scripts/sh/localhost-crt.sh
|
package/certs.bat
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
@echo off
|
2
|
+
|
3
|
+
if defined 1 (
|
4
|
+
set SUBJ=%1
|
5
|
+
) else (
|
6
|
+
set SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
7
|
+
)
|
8
|
+
|
9
|
+
call scripts/bat/localhost-csr.bat
|
10
|
+
call scripts/bat/localhost-crt.bat
|
package/certs.mjs
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
import debug from 'debug'
|
2
|
+
import os from 'node:os'
|
3
|
+
import ip from 'ip'
|
4
|
+
import {
|
5
|
+
exec
|
6
|
+
} from 'node:child_process'
|
7
|
+
import PATH from './where-am-i.mjs'
|
8
|
+
import config from './scripts/js/config.mjs'
|
9
|
+
import ext from './scripts/js/ext.mjs'
|
10
|
+
import toSubj from './scripts/js/to-subj.mjs'
|
11
|
+
|
12
|
+
const OPTIONS = {
|
13
|
+
maxBuffer: 1024 * 2000,
|
14
|
+
shell: true,
|
15
|
+
stdio: 'inherit'
|
16
|
+
}
|
17
|
+
|
18
|
+
const HOSTNAME = os.hostname()
|
19
|
+
const ADDRESS = ip.address()
|
20
|
+
const PLATFORM = os.platform()
|
21
|
+
|
22
|
+
const log = debug('@sequencemedia/certificates')
|
23
|
+
const info = debug('@sequencemedia/certificates:info')
|
24
|
+
const error = debug('@sequencemedia/certificates:error')
|
25
|
+
|
26
|
+
function bat (params) {
|
27
|
+
const command = `certs.bat "${toSubj(params)}"`
|
28
|
+
|
29
|
+
info(command)
|
30
|
+
|
31
|
+
return (
|
32
|
+
new Promise((resolve, reject) => {
|
33
|
+
exec(command, { ...OPTIONS, cwd: PATH }, (e) => (!e) ? resolve() : reject(e))
|
34
|
+
})
|
35
|
+
)
|
36
|
+
}
|
37
|
+
|
38
|
+
function sh (params) {
|
39
|
+
const command = `./certs.sh "${toSubj(params)}"`
|
40
|
+
|
41
|
+
info(command)
|
42
|
+
|
43
|
+
return (
|
44
|
+
new Promise((resolve, reject) => {
|
45
|
+
exec(command, { ...OPTIONS, cwd: PATH }, (e) => (!e) ? resolve() : reject(e))
|
46
|
+
})
|
47
|
+
)
|
48
|
+
}
|
49
|
+
|
50
|
+
log('`certs` is awake')
|
51
|
+
|
52
|
+
async function app () {
|
53
|
+
try {
|
54
|
+
await ext(HOSTNAME, ADDRESS)
|
55
|
+
|
56
|
+
const {
|
57
|
+
country,
|
58
|
+
state,
|
59
|
+
locality,
|
60
|
+
organisation,
|
61
|
+
commonName,
|
62
|
+
emailAddress
|
63
|
+
} = config
|
64
|
+
|
65
|
+
info({
|
66
|
+
country,
|
67
|
+
state,
|
68
|
+
locality,
|
69
|
+
organisation,
|
70
|
+
commonName,
|
71
|
+
emailAddress
|
72
|
+
})
|
73
|
+
|
74
|
+
return (PLATFORM === 'win32')
|
75
|
+
? await bat({
|
76
|
+
country,
|
77
|
+
state,
|
78
|
+
locality,
|
79
|
+
organisation,
|
80
|
+
commonName,
|
81
|
+
emailAddress
|
82
|
+
})
|
83
|
+
: await sh({
|
84
|
+
country,
|
85
|
+
state,
|
86
|
+
locality,
|
87
|
+
organisation,
|
88
|
+
commonName,
|
89
|
+
emailAddress
|
90
|
+
})
|
91
|
+
} catch ({
|
92
|
+
code = 'N/A',
|
93
|
+
message = 'N/A'
|
94
|
+
}) {
|
95
|
+
error(code, message)
|
96
|
+
|
97
|
+
process.exit(1)
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
export default app()
|
package/certs.sh
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [ -z "$1" ]
|
4
|
+
then
|
5
|
+
SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
6
|
+
else
|
7
|
+
SUBJ=$1
|
8
|
+
fi
|
9
|
+
|
10
|
+
source scripts/sh/localhost-csr.sh
|
11
|
+
source scripts/sh/localhost-crt.sh
|
package/package.json
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
{
|
2
|
+
"name": "@sequencemedia/certificates",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "Generate root CA and self-signed certificates with OpenSSL",
|
5
|
+
"type": "module",
|
6
|
+
"author": {
|
7
|
+
"name": "Jonathan Perry for Sequence Media Limited",
|
8
|
+
"email": "sequencemedia@sequencemedia.net",
|
9
|
+
"url": "http://sequencemedia.net"
|
10
|
+
},
|
11
|
+
"license": "ISC",
|
12
|
+
"repository": {
|
13
|
+
"type": "git",
|
14
|
+
"url": "git+ssh://git@github.com/sequencemedia/certificate-authority.git"
|
15
|
+
},
|
16
|
+
"homepage": "https://github.com/sequencemedia/certificates#readme",
|
17
|
+
"bugs": {
|
18
|
+
"url": "https://github.com/sequencemedia/certificates/issues"
|
19
|
+
},
|
20
|
+
"scripts": {
|
21
|
+
"lint": "eslint . --ext cjs --ext mjs",
|
22
|
+
"lint:fix": "npm run lint -- --fix",
|
23
|
+
"ca-and-certs": "DEBUG=@sequencemedia/certificates:* node ca-and-certs.mjs",
|
24
|
+
"certs": "DEBUG=@sequencemedia/certificates:* node certs.mjs"
|
25
|
+
},
|
26
|
+
"dependencies": {
|
27
|
+
"debug": "^4.3.4",
|
28
|
+
"fs-extra": "^11.1.0",
|
29
|
+
"ip": "^1.1.8",
|
30
|
+
"nconf": "^0.12.0",
|
31
|
+
"os": "^0.1.2"
|
32
|
+
},
|
33
|
+
"devDependencies": {
|
34
|
+
"@babel/cli": "^7.20.7",
|
35
|
+
"@babel/core": "^7.20.12",
|
36
|
+
"@babel/eslint-parser": "^7.19.1",
|
37
|
+
"@babel/preset-env": "^7.20.2",
|
38
|
+
"core-js": "^3.27.1",
|
39
|
+
"eslint": "^8.31.0",
|
40
|
+
"eslint-config-standard": "^17.0.0",
|
41
|
+
"eslint-plugin-import": "^2.26.0",
|
42
|
+
"eslint-plugin-node": "^11.1.0",
|
43
|
+
"eslint-plugin-promise": "^6.1.1"
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
@echo off
|
2
|
+
if not defined SUBJ (
|
3
|
+
set SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
4
|
+
)
|
5
|
+
openssl req -x509 -nodes -new -sha512 -days 365 -newkey rsa:4096 -keyout certificates/certificate-authority.key -out certificates/certificate-authority.pem -subj %SUBJ%
|
@@ -0,0 +1,5 @@
|
|
1
|
+
@echo off
|
2
|
+
if not defined SUBJ (
|
3
|
+
set SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
4
|
+
)
|
5
|
+
openssl req -new -nodes -newkey rsa:4096 -keyout certificates/localhost.key -out certificates/localhost.csr -subj %SUBJ%
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import debug from 'debug'
|
2
|
+
import nconf from 'nconf'
|
3
|
+
|
4
|
+
const log = debug('@sequencemedia/certificates')
|
5
|
+
const error = debug('@sequencemedia/certificates:error')
|
6
|
+
|
7
|
+
log('`config` is awake')
|
8
|
+
|
9
|
+
try {
|
10
|
+
nconf
|
11
|
+
.argv()
|
12
|
+
.file('certificates.json')
|
13
|
+
.required([
|
14
|
+
'country',
|
15
|
+
'state',
|
16
|
+
'locality',
|
17
|
+
'organisation',
|
18
|
+
'commonName',
|
19
|
+
'emailAddress'
|
20
|
+
])
|
21
|
+
} catch ({
|
22
|
+
message = 'N/A'
|
23
|
+
}) {
|
24
|
+
error(message)
|
25
|
+
|
26
|
+
process.exit(1)
|
27
|
+
}
|
28
|
+
|
29
|
+
export default nconf.get()
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import debug from 'debug'
|
2
|
+
import {
|
3
|
+
join
|
4
|
+
} from 'node:path'
|
5
|
+
import {
|
6
|
+
ensureDir
|
7
|
+
} from 'fs-extra'
|
8
|
+
import {
|
9
|
+
writeFile
|
10
|
+
} from 'node:fs/promises'
|
11
|
+
import PATH from '../../where-am-i.mjs'
|
12
|
+
|
13
|
+
const CERTIFICATES = join(PATH, 'certificates')
|
14
|
+
const FILE = join(CERTIFICATES, 'localhost.ext')
|
15
|
+
|
16
|
+
const log = debug('@sequencemedia/certificates')
|
17
|
+
|
18
|
+
function getExt (hostname, address) {
|
19
|
+
return (`
|
20
|
+
authorityKeyIdentifier = keyid, issuer
|
21
|
+
basicConstraints = CA:FALSE
|
22
|
+
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
|
23
|
+
subjectAltName = @alt_names
|
24
|
+
|
25
|
+
[alt_names]
|
26
|
+
DNS.1 = localhost
|
27
|
+
IP.1 = 127.0.0.1
|
28
|
+
IP.2 = ::1
|
29
|
+
DNS.2 = ${hostname.toLowerCase()}
|
30
|
+
IP.3 = ${address}
|
31
|
+
`).trim().concat('\n')
|
32
|
+
}
|
33
|
+
|
34
|
+
log('`ext` is awake')
|
35
|
+
|
36
|
+
export default async function ext (hostname, address) {
|
37
|
+
await ensureDir(CERTIFICATES)
|
38
|
+
await writeFile(FILE, getExt(hostname, address))
|
39
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import debug from 'debug'
|
2
|
+
|
3
|
+
const log = debug('@sequencemedia/certificates')
|
4
|
+
|
5
|
+
log('`toSubj` is awake')
|
6
|
+
|
7
|
+
export default function toSubj ({
|
8
|
+
country,
|
9
|
+
state,
|
10
|
+
locality,
|
11
|
+
organisation,
|
12
|
+
commonName,
|
13
|
+
emailAddress
|
14
|
+
}) {
|
15
|
+
return `/C=${country}/ST=${state}/L=${locality}/O=${organisation}/CN=${commonName}/emailAddress=${emailAddress}`
|
16
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [ $# -eq 1 ]
|
4
|
+
then
|
5
|
+
SUBJ=$1
|
6
|
+
fi
|
7
|
+
|
8
|
+
if [ -z "$SUBJ" ]
|
9
|
+
then
|
10
|
+
SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
11
|
+
fi
|
12
|
+
|
13
|
+
openssl req -x509 -nodes -new -sha512 \
|
14
|
+
-days 365 \
|
15
|
+
-newkey rsa:4096 \
|
16
|
+
-keyout certificates/certificate-authority.key \
|
17
|
+
-out certificates/certificate-authority.pem \
|
18
|
+
-subj "$SUBJ"
|
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
openssl x509 -req -sha512 -days 365 \
|
4
|
+
-extfile certificates/localhost.ext \
|
5
|
+
-CA certificates/certificate-authority.crt \
|
6
|
+
-CAkey certificates/certificate-authority.key \
|
7
|
+
-CAcreateserial \
|
8
|
+
-in certificates/localhost.csr \
|
9
|
+
-out certificates/localhost.crt
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [ $# -eq 1 ]
|
4
|
+
then
|
5
|
+
SUBJ=$1
|
6
|
+
fi
|
7
|
+
|
8
|
+
if [ -z "$SUBJ" ]
|
9
|
+
then
|
10
|
+
SUBJ="/C=UK/ST=England/L=Greenwich/O=Sequence Media Limited/CN=Sequence Media/emailAddress=sequencemedia@sequencemedia.net"
|
11
|
+
fi
|
12
|
+
|
13
|
+
openssl req -new -nodes -newkey rsa:4096 \
|
14
|
+
-keyout certificates/localhost.key \
|
15
|
+
-out certificates/localhost.csr \
|
16
|
+
-subj "$SUBJ"
|