vestauth 0.2.5 → 0.3.2
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 +1 -1
- package/package.json +5 -2
- package/src/cli/actions/agent/curl.js +34 -0
- package/src/cli/actions/agent/headers.js +22 -0
- package/src/cli/actions/primitives/headers.js +23 -0
- package/src/cli/actions/primitives/keypair.js +2 -0
- package/src/cli/actions/primitives/keypairOld.js +24 -0
- package/src/cli/actions/{agent/hello.js → provider/challenge.js} +4 -6
- package/src/cli/actions/provider/verify.js +38 -0
- package/src/cli/commands/agent.js +22 -14
- package/src/cli/commands/primitives.js +13 -1
- package/src/cli/commands/provider.js +28 -0
- package/src/cli/vestauth.js +2 -4
- package/src/lib/agent.js +2 -2
- package/src/lib/helpers/agentAuth.js +1 -0
- package/src/lib/helpers/agentHeaders.js +25 -0
- package/src/lib/helpers/agentInit.js +2 -2
- package/src/lib/helpers/edPrivateKeyObject.js +7 -0
- package/src/lib/helpers/epoch.js +12 -0
- package/src/lib/helpers/execute.js +12 -0
- package/src/lib/helpers/executeCommand.js +115 -0
- package/src/lib/helpers/findUrl.js +10 -0
- package/src/lib/helpers/headers.js +38 -0
- package/src/lib/helpers/keypair.js +35 -19
- package/src/lib/helpers/keypairOld.js +34 -0
- package/src/lib/helpers/providerChallenge.js +7 -0
- package/src/lib/helpers/signatureParams.js +19 -0
- package/src/lib/helpers/thumbprint.js +10 -0
- package/src/lib/helpers/verifyAgent.js +2 -2
- package/src/lib/helpers/webBotAuthSignature.js +28 -0
- package/src/lib/main.js +4 -0
- package/src/lib/primitives.js +4 -0
- package/src/lib/provider.js +5 -0
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vestauth",
|
|
3
|
-
"version": "0.2
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "auth for agents–from the creator of dotenvx",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vestauth"
|
|
@@ -42,7 +42,10 @@
|
|
|
42
42
|
"@noble/secp256k1": "^1.7.2",
|
|
43
43
|
"commander": "^11.1.0",
|
|
44
44
|
"eciesjs": "^0.4.16",
|
|
45
|
-
"
|
|
45
|
+
"execa": "^5.1.1",
|
|
46
|
+
"http-message-sig": "^0.2.0",
|
|
47
|
+
"undici": "7.11.0",
|
|
48
|
+
"web-bot-auth": "^0.1.2"
|
|
46
49
|
},
|
|
47
50
|
"devDependencies": {
|
|
48
51
|
"@yao-pkg/pkg": "^5.14.2",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const { logger } = require('./../../../shared/logger')
|
|
2
|
+
const agent = require('./../../../lib/agent')
|
|
3
|
+
const execute = require('./../../../lib/helpers/execute')
|
|
4
|
+
const findUrl = require('./../../../lib/helpers/findUrl')
|
|
5
|
+
|
|
6
|
+
async function curl () {
|
|
7
|
+
const commandArgs = this.args
|
|
8
|
+
logger.debug(`process command [${commandArgs.join(' ')}]`)
|
|
9
|
+
|
|
10
|
+
const options = this.opts()
|
|
11
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
|
+
|
|
13
|
+
const httpMethod = 'GET'
|
|
14
|
+
const url = findUrl(commandArgs)
|
|
15
|
+
const headers = await agent.headers(httpMethod, url)
|
|
16
|
+
const injected = [
|
|
17
|
+
'curl',
|
|
18
|
+
'-H', `Signature: ${headers.Signature}`,
|
|
19
|
+
'-H', `Signature-Input: ${headers['Signature-Input']}`,
|
|
20
|
+
...commandArgs
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
const child = execute.execa(injected[0], injected.slice(1), { stdio: 'inherit' })
|
|
24
|
+
|
|
25
|
+
// Wait for the command process to finish
|
|
26
|
+
const { exitCode } = await child
|
|
27
|
+
|
|
28
|
+
if (exitCode !== 0) {
|
|
29
|
+
logger.debug(`received exitCode ${exitCode}`)
|
|
30
|
+
throw new Error(`Command exited with exit code ${exitCode}`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = curl
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { logger } = require('./../../../shared/logger')
|
|
2
|
+
|
|
3
|
+
const agent = require('./../../../lib/agent')
|
|
4
|
+
|
|
5
|
+
async function headers (httpMethod, uri) {
|
|
6
|
+
logger.debug(`httpMethod: ${httpMethod}`)
|
|
7
|
+
logger.debug(`uri: ${uri}`)
|
|
8
|
+
|
|
9
|
+
const options = this.opts()
|
|
10
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
11
|
+
|
|
12
|
+
const output = await agent.headers(httpMethod, uri, options.tag, options.nonce)
|
|
13
|
+
|
|
14
|
+
let space = 0
|
|
15
|
+
if (options.prettyPrint) {
|
|
16
|
+
space = 2
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
console.log(JSON.stringify(output, null, space))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = headers
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const { logger } = require('./../../../shared/logger')
|
|
2
|
+
|
|
3
|
+
const primitives = require('./../../../lib/primitives')
|
|
4
|
+
|
|
5
|
+
async function headers (httpMethod, uri, privateKey) {
|
|
6
|
+
logger.debug(`httpMethod: ${httpMethod}`)
|
|
7
|
+
logger.debug(`uri: ${uri}`)
|
|
8
|
+
logger.debug(`privateKey: ${privateKey}`)
|
|
9
|
+
|
|
10
|
+
const options = this.opts()
|
|
11
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
12
|
+
|
|
13
|
+
const output = await primitives.headers(httpMethod, uri, privateKey, options.tag, options.nonce)
|
|
14
|
+
|
|
15
|
+
let space = 0
|
|
16
|
+
if (options.prettyPrint) {
|
|
17
|
+
space = 2
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
console.log(JSON.stringify(output, null, space))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = headers
|
|
@@ -3,6 +3,8 @@ const { logger } = require('./../../../shared/logger')
|
|
|
3
3
|
const primitives = require('./../../../lib/primitives')
|
|
4
4
|
|
|
5
5
|
function keypair (existingPrivateKey) {
|
|
6
|
+
logger.debug(`existingPrivateKey: ${existingPrivateKey}`)
|
|
7
|
+
|
|
6
8
|
const options = this.opts()
|
|
7
9
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
8
10
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { logger } = require('./../../../shared/logger')
|
|
2
|
+
|
|
3
|
+
const primitives = require('./../../../lib/primitives')
|
|
4
|
+
|
|
5
|
+
function keypairOld (existingPrivateKey) {
|
|
6
|
+
const options = this.opts()
|
|
7
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
8
|
+
|
|
9
|
+
const kp = primitives.keypairOld(existingPrivateKey, options.prefix)
|
|
10
|
+
|
|
11
|
+
const output = {
|
|
12
|
+
public_key: kp.publicKey,
|
|
13
|
+
private_key: kp.privateKey
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let space = 0
|
|
17
|
+
if (options.prettyPrint) {
|
|
18
|
+
space = 2
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
console.log(JSON.stringify(output, null, space))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = keypairOld
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
const { logger } = require('./../../../shared/logger')
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const prov = require('./../../../lib/provider')
|
|
4
4
|
|
|
5
|
-
function
|
|
5
|
+
async function provider (website) {
|
|
6
6
|
const options = this.opts()
|
|
7
7
|
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
8
8
|
|
|
9
|
-
const output =
|
|
10
|
-
hello: agent.hello()
|
|
11
|
-
}
|
|
9
|
+
const output = await prov.challenge()
|
|
12
10
|
|
|
13
11
|
let space = 0
|
|
14
12
|
if (options.prettyPrint) {
|
|
@@ -18,4 +16,4 @@ function hello () {
|
|
|
18
16
|
console.log(JSON.stringify(output, null, space))
|
|
19
17
|
}
|
|
20
18
|
|
|
21
|
-
module.exports =
|
|
19
|
+
module.exports = provider
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { logger } = require('./../../../shared/logger')
|
|
2
|
+
|
|
3
|
+
const { verify } = require('web-bot-auth')
|
|
4
|
+
const { verifierFromJWK } = require('web-bot-auth/crypto')
|
|
5
|
+
|
|
6
|
+
async function _verify (httpMethod, uri, signatureHeader, signatureInputHeader, publicKey) {
|
|
7
|
+
logger.debug(`httpMethod: ${httpMethod}`)
|
|
8
|
+
logger.debug(`uri: ${uri}`)
|
|
9
|
+
logger.debug(`signatureHeader: ${signatureHeader}`)
|
|
10
|
+
logger.debug(`signatureInputHeader: ${signatureInputHeader}`)
|
|
11
|
+
logger.debug(`publicKey: ${publicKey}`)
|
|
12
|
+
|
|
13
|
+
const options = this.opts()
|
|
14
|
+
logger.debug(`options: ${JSON.stringify(options)}`)
|
|
15
|
+
|
|
16
|
+
const verifier = await verifierFromJWK(JSON.parse(publicKey))
|
|
17
|
+
const headers = {
|
|
18
|
+
Signature: signatureHeader,
|
|
19
|
+
'Signature-Input': signatureInputHeader
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const signedRequest = new Request(uri, { headers: headers })
|
|
23
|
+
const r = await verify(signedRequest, verifier)
|
|
24
|
+
console.log(r)
|
|
25
|
+
|
|
26
|
+
const output = {
|
|
27
|
+
implement: 'todo'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let space = 0
|
|
31
|
+
if (options.prettyPrint) {
|
|
32
|
+
space = 2
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(JSON.stringify(output, null, space))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = _verify
|
|
@@ -3,17 +3,10 @@ const { Command } = require('commander')
|
|
|
3
3
|
const agent = new Command('agent')
|
|
4
4
|
|
|
5
5
|
agent
|
|
6
|
-
.
|
|
6
|
+
.usage('run -- yourcommand')
|
|
7
|
+
.description('🤖 agent')
|
|
7
8
|
.allowUnknownOption()
|
|
8
9
|
|
|
9
|
-
// vestauth agent auth
|
|
10
|
-
const authAction = require('./../actions/agent/auth')
|
|
11
|
-
agent.command('auth')
|
|
12
|
-
.description('auth agent')
|
|
13
|
-
.argument('<website>', 'root url of website')
|
|
14
|
-
.option('-pp, --pretty-print', 'pretty print output')
|
|
15
|
-
.action(authAction)
|
|
16
|
-
|
|
17
10
|
// vestauth agent init
|
|
18
11
|
const initAction = require('./../actions/agent/init')
|
|
19
12
|
agent.command('init')
|
|
@@ -21,10 +14,25 @@ agent.command('init')
|
|
|
21
14
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
22
15
|
.action(initAction)
|
|
23
16
|
|
|
24
|
-
// vestauth agent
|
|
25
|
-
const
|
|
26
|
-
agent.command('
|
|
27
|
-
.description('
|
|
28
|
-
.
|
|
17
|
+
// vestauth agent curl
|
|
18
|
+
const curlAction = require('./../actions/agent/curl')
|
|
19
|
+
agent.command('curl')
|
|
20
|
+
.description('run curl as agent')
|
|
21
|
+
.allowUnknownOption()
|
|
22
|
+
.option('--tag <tag>', 'vestauth (default) | web-bot-auth', 'vestauth')
|
|
23
|
+
.option('--nonce <nonce>', 'null (default)')
|
|
24
|
+
.option('-pp, --pretty-print', 'pretty print output')
|
|
25
|
+
.action(curlAction)
|
|
26
|
+
|
|
27
|
+
// vestauth agent headers
|
|
28
|
+
const headersAction = require('./../actions/agent/headers')
|
|
29
|
+
agent.command('headers')
|
|
30
|
+
.description('generate headers as agent')
|
|
31
|
+
.argument('<httpMethod>', 'GET (default)')
|
|
32
|
+
.argument('<uri>', '')
|
|
33
|
+
.option('--tag <tag>', 'vestauth (default) | web-bot-auth', 'vestauth')
|
|
34
|
+
.option('--nonce <nonce>', 'null (default)')
|
|
35
|
+
.option('-pp, --pretty-print', 'pretty print output')
|
|
36
|
+
.action(headersAction)
|
|
29
37
|
|
|
30
38
|
module.exports = agent
|
|
@@ -25,11 +25,23 @@ primitives.command('hash')
|
|
|
25
25
|
const keypairAction = require('./../actions/primitives/keypair')
|
|
26
26
|
primitives.command('keypair')
|
|
27
27
|
.description('generate public/private keypair')
|
|
28
|
-
.argument('[
|
|
28
|
+
.argument('[privateKey]', 'pre-existing private key')
|
|
29
29
|
.option('--prefix <type>', 'agent (default) | provider | none', 'agent')
|
|
30
30
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
31
31
|
.action(keypairAction)
|
|
32
32
|
|
|
33
|
+
// vestauth primitives headers
|
|
34
|
+
const headersAction = require('./../actions/primitives/headers')
|
|
35
|
+
primitives.command('headers')
|
|
36
|
+
.description('generate signed headers')
|
|
37
|
+
.argument('<httpMethod>', 'GET (default)')
|
|
38
|
+
.argument('<uri>', '')
|
|
39
|
+
.argument('<privateKey>', 'private key (json string)')
|
|
40
|
+
.option('--tag <tag>', 'vestauth (default) | web-bot-auth', 'vestauth')
|
|
41
|
+
.option('--nonce <nonce>', 'null (default)')
|
|
42
|
+
.option('-pp, --pretty-print', 'pretty print output')
|
|
43
|
+
.action(headersAction)
|
|
44
|
+
|
|
33
45
|
// vestauth primitives sign
|
|
34
46
|
const signAction = require('./../actions/primitives/sign')
|
|
35
47
|
primitives.command('sign')
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const { Command } = require('commander')
|
|
2
|
+
|
|
3
|
+
const provider = new Command('provider')
|
|
4
|
+
|
|
5
|
+
provider
|
|
6
|
+
.description('🔌 provider')
|
|
7
|
+
.allowUnknownOption()
|
|
8
|
+
|
|
9
|
+
// vestauth provider verify
|
|
10
|
+
const verifyAction = require('./../actions/provider/verify')
|
|
11
|
+
provider.command('verify')
|
|
12
|
+
.description('verify agent')
|
|
13
|
+
.argument('<httpMethod>', 'GET (default)')
|
|
14
|
+
.argument('<uri>', '')
|
|
15
|
+
.argument('<signatureHeader>', '')
|
|
16
|
+
.argument('<signatureInputHeader>', '')
|
|
17
|
+
.argument('<publicKey>', 'public key (json string)')
|
|
18
|
+
.option('-pp, --pretty-print', 'pretty print output')
|
|
19
|
+
.action(verifyAction)
|
|
20
|
+
|
|
21
|
+
// vestauth provider challenge
|
|
22
|
+
const challengeAction = require('./../actions/provider/challenge')
|
|
23
|
+
provider.command('challenge')
|
|
24
|
+
.description('generate challenge')
|
|
25
|
+
.option('-pp, --pretty-print', 'pretty print output')
|
|
26
|
+
.action(challengeAction)
|
|
27
|
+
|
|
28
|
+
module.exports = provider
|
package/src/cli/vestauth.js
CHANGED
|
@@ -38,8 +38,9 @@ program
|
|
|
38
38
|
.version(packageJson.version)
|
|
39
39
|
.allowUnknownOption()
|
|
40
40
|
|
|
41
|
-
// dotenvx agent
|
|
42
41
|
program.addCommand(require('./commands/agent'))
|
|
42
|
+
program.addCommand(require('./commands/provider'))
|
|
43
|
+
program.addCommand(require('./commands/primitives'))
|
|
43
44
|
|
|
44
45
|
// vestauth verifyAgent
|
|
45
46
|
const verifyAgentAction = require('./actions/verifyAgent')
|
|
@@ -51,9 +52,6 @@ program.command('verifyagent')
|
|
|
51
52
|
.option('-pp, --pretty-print', 'pretty print output')
|
|
52
53
|
.action(verifyAgentAction)
|
|
53
54
|
|
|
54
|
-
// dotenvx primitive
|
|
55
|
-
program.addCommand(require('./commands/primitives'))
|
|
56
|
-
|
|
57
55
|
// vestauth help
|
|
58
56
|
program.command('help [command]')
|
|
59
57
|
.description('display help for command')
|
package/src/lib/agent.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const agentAuth = require('./helpers/agentAuth')
|
|
2
1
|
const agentInit = require('./helpers/agentInit')
|
|
2
|
+
const agentHeaders = require('./helpers/agentHeaders')
|
|
3
3
|
const hello = require('./helpers/hello')
|
|
4
4
|
|
|
5
5
|
module.exports = {
|
|
6
|
-
auth: agentAuth,
|
|
7
6
|
init: agentInit,
|
|
7
|
+
headers: agentHeaders,
|
|
8
8
|
hello
|
|
9
9
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const headers = require('./headers')
|
|
2
|
+
const dotenvx = require('@dotenvx/dotenvx')
|
|
3
|
+
const { verify } = require('web-bot-auth')
|
|
4
|
+
const { verifierFromJWK } = require('web-bot-auth/crypto')
|
|
5
|
+
|
|
6
|
+
async function agentHeaders (httpMethod, uri, tag = 'vestauth', nonce = null) {
|
|
7
|
+
let publicKey = null
|
|
8
|
+
let privateKey = null
|
|
9
|
+
try { publicKey = dotenvx.get('AGENT_PUBLIC_KEY', { strict: true }) } catch (_e) {}
|
|
10
|
+
try { privateKey = dotenvx.get('AGENT_PRIVATE_KEY', { strict: true }) } catch (_e) {}
|
|
11
|
+
|
|
12
|
+
if (!publicKey && !privateKey) throw new Error('missing AGENT_PUBLIC_KEY and AGENT_PRIVATE_KEY. Run [vestauth agent init]')
|
|
13
|
+
|
|
14
|
+
const _headers = await headers(httpMethod, uri, privateKey, tag, nonce)
|
|
15
|
+
|
|
16
|
+
// verification (temp testing)
|
|
17
|
+
const verifier = await verifierFromJWK(JSON.parse(publicKey))
|
|
18
|
+
const signedRequest = new Request(uri, { headers: _headers })
|
|
19
|
+
const r = await verify(signedRequest, verifier)
|
|
20
|
+
console.log(r)
|
|
21
|
+
|
|
22
|
+
return _headers
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
module.exports = agentHeaders
|
|
@@ -14,8 +14,8 @@ function agentInit () {
|
|
|
14
14
|
touch(envPath)
|
|
15
15
|
|
|
16
16
|
// place in .env file
|
|
17
|
-
dotenvx.set('AGENT_PUBLIC_KEY', kp.publicKey, { path: envPath, plain: true, quiet: true })
|
|
18
|
-
dotenvx.set('AGENT_PRIVATE_KEY', kp.privateKey, { path: envPath, plain: true, quiet: true })
|
|
17
|
+
dotenvx.set('AGENT_PUBLIC_KEY', JSON.stringify(kp.publicKey), { path: envPath, plain: true, quiet: true })
|
|
18
|
+
dotenvx.set('AGENT_PRIVATE_KEY', JSON.stringify(kp.privateKey), { path: envPath, plain: true, quiet: true })
|
|
19
19
|
|
|
20
20
|
return {
|
|
21
21
|
AGENT_PUBLIC_KEY: kp.publicKey,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const execa = require('execa')
|
|
2
|
+
/* c8 ignore start */
|
|
3
|
+
const pkgArgs = process.pkg ? { PKG_EXECPATH: '' } : {}
|
|
4
|
+
/* c8 ignore stop */
|
|
5
|
+
|
|
6
|
+
const execute = {
|
|
7
|
+
execa (command, args, options) {
|
|
8
|
+
return execa(command, args, { ...options, env: { ...options.env, ...pkgArgs } })
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = execute
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const which = require('which')
|
|
3
|
+
const execute = require('./../../lib/helpers/execute')
|
|
4
|
+
const { logger } = require('./../../shared/logger')
|
|
5
|
+
|
|
6
|
+
async function executeCommand (commandArgs) {
|
|
7
|
+
const signals = [
|
|
8
|
+
'SIGHUP', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',
|
|
9
|
+
'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2'
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
logger.debug(`executing process command [${commandArgs.join(' ')}]`)
|
|
13
|
+
|
|
14
|
+
let child
|
|
15
|
+
let signalSent
|
|
16
|
+
|
|
17
|
+
/* c8 ignore start */
|
|
18
|
+
const sigintHandler = () => {
|
|
19
|
+
logger.debug('received SIGINT')
|
|
20
|
+
logger.debug('checking command process')
|
|
21
|
+
logger.debug(child)
|
|
22
|
+
|
|
23
|
+
if (child) {
|
|
24
|
+
logger.debug('sending SIGINT to command process')
|
|
25
|
+
signalSent = 'SIGINT'
|
|
26
|
+
child.kill('SIGINT') // Send SIGINT to the command process
|
|
27
|
+
} else {
|
|
28
|
+
logger.debug('no command process to send SIGINT to')
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sigtermHandler = () => {
|
|
33
|
+
logger.debug('received SIGTERM')
|
|
34
|
+
logger.debug('checking command process')
|
|
35
|
+
logger.debug(child)
|
|
36
|
+
|
|
37
|
+
if (child) {
|
|
38
|
+
logger.debug('sending SIGTERM to command process')
|
|
39
|
+
signalSent = 'SIGTERM'
|
|
40
|
+
child.kill('SIGTERM') // Send SIGTERM to the command process
|
|
41
|
+
} else {
|
|
42
|
+
logger.debug('no command process to send SIGTERM to')
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const handleOtherSignal = (signal) => {
|
|
47
|
+
logger.debug(`received ${signal}`)
|
|
48
|
+
child.kill(signal)
|
|
49
|
+
}
|
|
50
|
+
/* c8 ignore stop */
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
// ensure the first command is expanded
|
|
54
|
+
try {
|
|
55
|
+
commandArgs[0] = path.resolve(which.sync(`${commandArgs[0]}`))
|
|
56
|
+
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
57
|
+
} catch (e) {
|
|
58
|
+
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// expand any other commands that follow a --
|
|
62
|
+
let expandNext = false
|
|
63
|
+
for (let i = 0; i < commandArgs.length; i++) {
|
|
64
|
+
if (commandArgs[i] === '--') {
|
|
65
|
+
expandNext = true
|
|
66
|
+
} else if (expandNext) {
|
|
67
|
+
try {
|
|
68
|
+
commandArgs[i] = path.resolve(which.sync(`${commandArgs[i]}`))
|
|
69
|
+
logger.debug(`expanding process command to [${commandArgs.join(' ')}]`)
|
|
70
|
+
} catch (e) {
|
|
71
|
+
logger.debug(`could not expand process command. using [${commandArgs.join(' ')}]`)
|
|
72
|
+
}
|
|
73
|
+
expandNext = false
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
child = execute.execa(commandArgs[0], commandArgs.slice(1), {
|
|
78
|
+
stdio: 'inherit'
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
process.on('SIGINT', sigintHandler)
|
|
82
|
+
process.on('SIGTERM', sigtermHandler)
|
|
83
|
+
|
|
84
|
+
signals.forEach(signal => {
|
|
85
|
+
process.on(signal, () => handleOtherSignal(signal))
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Wait for the command process to finish
|
|
89
|
+
const { exitCode } = await child
|
|
90
|
+
|
|
91
|
+
if (exitCode !== 0) {
|
|
92
|
+
logger.debug(`received exitCode ${exitCode}`)
|
|
93
|
+
throw new Error(`Command exited with exit code ${exitCode}`)
|
|
94
|
+
}
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// no color on these errors as they can be standard errors for things like jest exiting with exitCode 1 for a single failed test.
|
|
97
|
+
if (!['SIGINT', 'SIGTERM'].includes(signalSent || error.signal)) {
|
|
98
|
+
if (error.code === 'ENOENT') {
|
|
99
|
+
logger.error(`Unknown command: ${error.command}`)
|
|
100
|
+
} else {
|
|
101
|
+
logger.error(error.message)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Exit with the error code from the command process, or 1 if unavailable
|
|
106
|
+
process.exit(error.exitCode || 1)
|
|
107
|
+
} finally {
|
|
108
|
+
// Clean up: Remove the SIGINT handler
|
|
109
|
+
process.removeListener('SIGINT', sigintHandler)
|
|
110
|
+
// Clean up: Remove the SIGTERM handler
|
|
111
|
+
process.removeListener('SIGTERM', sigtermHandler)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = executeCommand
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const thumbprint = require('./thumbprint')
|
|
2
|
+
const signatureParams = require('./signatureParams')
|
|
3
|
+
const webBotAuthSignature = require('./webBotAuthSignature')
|
|
4
|
+
|
|
5
|
+
// const { signatureHeaders } = require('web-bot-auth')
|
|
6
|
+
// const { signerFromJWK } = require('web-bot-auth/crypto')
|
|
7
|
+
|
|
8
|
+
async function headers (httpMethod, uri, privateKeyString, tag = 'vestauth', nonce = null) {
|
|
9
|
+
// shared
|
|
10
|
+
const privateKey = JSON.parse(privateKeyString)
|
|
11
|
+
const kid = thumbprint(privateKey)
|
|
12
|
+
privateKey.kid = kid
|
|
13
|
+
|
|
14
|
+
// // theirs
|
|
15
|
+
// const request = new Request(uri)
|
|
16
|
+
// const now = new Date()
|
|
17
|
+
// const headersTheirs = await signatureHeaders(
|
|
18
|
+
// request,
|
|
19
|
+
// await signerFromJWK(JSON.parse(privateKeyString)),
|
|
20
|
+
// {
|
|
21
|
+
// created: now,
|
|
22
|
+
// expires: new Date(now.getTime() + 300_000), // now + 5 min
|
|
23
|
+
// }
|
|
24
|
+
// )
|
|
25
|
+
|
|
26
|
+
// ours
|
|
27
|
+
const signature = signatureParams(privateKey.kid, tag, nonce)
|
|
28
|
+
const sig1 = webBotAuthSignature(httpMethod, uri, signature, privateKey)
|
|
29
|
+
|
|
30
|
+
const headersOurs = {
|
|
31
|
+
Signature: `sig1=:${sig1}:`,
|
|
32
|
+
'Signature-Input': `sig1=${signature}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return headersOurs
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = headers
|
|
@@ -1,33 +1,49 @@
|
|
|
1
|
-
const
|
|
1
|
+
const crypto = require('crypto')
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const thumbprint = require('./thumbprint')
|
|
4
4
|
|
|
5
5
|
function keypair (existingPrivateKey, prefix = 'agent') {
|
|
6
|
-
let
|
|
6
|
+
let publicJwk
|
|
7
|
+
let privateJwk
|
|
7
8
|
|
|
8
9
|
if (existingPrivateKey) {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
// example
|
|
11
|
+
// {
|
|
12
|
+
// "crv": "Ed25519",
|
|
13
|
+
// "d": "eScKeQcawvvRiBuA_-gWaAP7PZ3UUGPqJv7jks5tFVI",
|
|
14
|
+
// "x": "MYf21IkWEi6dXOtzUdbll3SMCaFiSFi4KgqktFZinCE",
|
|
15
|
+
// "kty": "OKP",
|
|
16
|
+
// "kid": "rBE7_zLOVYk4oYEdI-01qpXHWNMyZYD-4LEf6HiyZ9Q"
|
|
17
|
+
// }
|
|
18
|
+
// (publicKey just remove 'd')
|
|
19
|
+
|
|
20
|
+
privateJwk = JSON.parse(existingPrivateKey)
|
|
21
|
+
publicJwk = {
|
|
22
|
+
crv: privateJwk.crv,
|
|
23
|
+
x: privateJwk.x,
|
|
24
|
+
kty: privateJwk.kty,
|
|
25
|
+
kid: privateJwk.kid
|
|
26
|
+
}
|
|
27
|
+
const kid = thumbprint(publicJwk)
|
|
28
|
+
publicJwk.kid = kid
|
|
29
|
+
privateJwk.kid = kid
|
|
11
30
|
} else {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let privateKey = kp.secret.toString('hex')
|
|
31
|
+
const {
|
|
32
|
+
publicKey,
|
|
33
|
+
privateKey
|
|
34
|
+
} = crypto.generateKeyPairSync('ed25519')
|
|
17
35
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
privateKey = `agent_prv_${privateKey}`
|
|
21
|
-
}
|
|
36
|
+
publicJwk = publicKey.export({ format: 'jwk' })
|
|
37
|
+
privateJwk = privateKey.export({ format: 'jwk' })
|
|
22
38
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
const kid = thumbprint(publicJwk)
|
|
40
|
+
publicJwk.kid = kid
|
|
41
|
+
privateJwk.kid = kid
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
return {
|
|
29
|
-
publicKey,
|
|
30
|
-
privateKey
|
|
45
|
+
publicKey: publicJwk,
|
|
46
|
+
privateKey: privateJwk
|
|
31
47
|
}
|
|
32
48
|
}
|
|
33
49
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const { PrivateKey } = require('eciesjs')
|
|
2
|
+
|
|
3
|
+
const stripFormatting = require('./stripFormatting')
|
|
4
|
+
|
|
5
|
+
function keypairOld (existingPrivateKey, prefix = 'agent') {
|
|
6
|
+
let kp
|
|
7
|
+
|
|
8
|
+
if (existingPrivateKey) {
|
|
9
|
+
const existingPrivateKeyStripped = stripFormatting(existingPrivateKey)
|
|
10
|
+
kp = new PrivateKey(Buffer.from(existingPrivateKeyStripped, 'hex'))
|
|
11
|
+
} else {
|
|
12
|
+
kp = new PrivateKey()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let publicKey = kp.publicKey.toHex()
|
|
16
|
+
let privateKey = kp.secret.toString('hex')
|
|
17
|
+
|
|
18
|
+
if (prefix === 'agent') {
|
|
19
|
+
publicKey = `agent_pub_${publicKey}`
|
|
20
|
+
privateKey = `agent_prv_${privateKey}`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (prefix === 'provider') {
|
|
24
|
+
publicKey = `provider_pub_${publicKey}`
|
|
25
|
+
privateKey = `provider_prv_${privateKey}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
publicKey,
|
|
30
|
+
privateKey
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = keypairOld
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const crypto = require('crypto')
|
|
2
|
+
|
|
3
|
+
const epoch = require('./epoch')
|
|
4
|
+
|
|
5
|
+
function signatureParams (kid, tag = 'vestauth', nonce = null) {
|
|
6
|
+
const { created, expires } = epoch()
|
|
7
|
+
|
|
8
|
+
if (!nonce) nonce = crypto.randomBytes(64).toString('base64url')
|
|
9
|
+
|
|
10
|
+
return '("@authority");' +
|
|
11
|
+
`created=${created};` +
|
|
12
|
+
`keyid="${kid}";` +
|
|
13
|
+
'alg="ed25519";' +
|
|
14
|
+
`expires=${expires};` +
|
|
15
|
+
`nonce="${nonce}";` +
|
|
16
|
+
`tag="${tag}"`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = signatureParams
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const crypto = require('crypto')
|
|
2
|
+
|
|
3
|
+
function thumbprint (publicJwk) {
|
|
4
|
+
// RFC 7638 canonical JSON for OKP (Ed25519)
|
|
5
|
+
const canon = `{"crv":"${publicJwk.crv}","kty":"${publicJwk.kty}","x":"${publicJwk.x}"}`
|
|
6
|
+
const sha256 = crypto.createHash('sha256').update(canon).digest()
|
|
7
|
+
return Buffer.from(sha256).toString('base64url')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = thumbprint
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const PostVerify = require('../api/postVerify')
|
|
2
|
-
const
|
|
2
|
+
const keypairOld = require('./keypairOld')
|
|
3
3
|
const sign = require('./sign')
|
|
4
4
|
|
|
5
5
|
async function verifyAgent (providerPrivateKey, providerChallenge, authorizationHeader) {
|
|
6
|
-
const kp =
|
|
6
|
+
const kp = keypairOld(providerPrivateKey, 'provider')
|
|
7
7
|
const providerSignature = await sign(providerChallenge, kp.privateKey)
|
|
8
8
|
|
|
9
9
|
const raw = authorizationHeader.replace(/^Agent\s+/i, '').trim() // remove 'Agent ' prefix
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const crypto = require('crypto')
|
|
2
|
+
const edPrivateKeyObject = require('./edPrivateKeyObject')
|
|
3
|
+
|
|
4
|
+
function webBotAuthSignature (method = 'GET', uri = '', signatureParams, privateKey) {
|
|
5
|
+
const u = new URL(uri)
|
|
6
|
+
const authority = u.host // includes port if present
|
|
7
|
+
|
|
8
|
+
const message = [
|
|
9
|
+
`"@authority": ${authority}`,
|
|
10
|
+
`"@signature-params": ${signatureParams}`
|
|
11
|
+
].join('\n')
|
|
12
|
+
|
|
13
|
+
// const message = [
|
|
14
|
+
// `"@method": ${method.toUpperCase()}`,
|
|
15
|
+
// `"@target-uri": ${uri}`,
|
|
16
|
+
// `"@signature-params": ${signatureParams}`
|
|
17
|
+
// ].join('\n')
|
|
18
|
+
|
|
19
|
+
const privateKeyObject = edPrivateKeyObject(privateKey)
|
|
20
|
+
|
|
21
|
+
return crypto.sign(
|
|
22
|
+
null,
|
|
23
|
+
Buffer.from(message, 'utf8'),
|
|
24
|
+
privateKeyObject
|
|
25
|
+
).toString('base64')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = webBotAuthSignature
|
package/src/lib/main.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
const verifyAuthorizationHeader = require('./helpers/verifyAuthorizationHeader')
|
|
2
2
|
const verifyAgent = require('./helpers/verifyAgent')
|
|
3
|
+
const agent = require('./agent')
|
|
4
|
+
const provider = require('./provider')
|
|
3
5
|
const primitives = require('./primitives')
|
|
4
6
|
|
|
5
7
|
module.exports = {
|
|
8
|
+
agent,
|
|
9
|
+
provider,
|
|
6
10
|
primitives,
|
|
7
11
|
verifyAuthorizationHeader,
|
|
8
12
|
verifyAgent
|
package/src/lib/primitives.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const challenge = require('./helpers/challenge')
|
|
2
2
|
const hash = require('./helpers/hash')
|
|
3
3
|
const keypair = require('./helpers/keypair')
|
|
4
|
+
const keypairOld = require('./helpers/keypairOld')
|
|
5
|
+
const headers = require('./helpers/headers')
|
|
4
6
|
const sign = require('./helpers/sign')
|
|
5
7
|
const verify = require('./helpers/verify')
|
|
6
8
|
|
|
@@ -8,6 +10,8 @@ module.exports = {
|
|
|
8
10
|
challenge,
|
|
9
11
|
hash,
|
|
10
12
|
keypair,
|
|
13
|
+
keypairOld,
|
|
14
|
+
headers,
|
|
11
15
|
sign,
|
|
12
16
|
verify
|
|
13
17
|
}
|