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

feat(backend): provision private key #638

Merged
merged 14 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions packages/backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build
/dist
.env
src/coverage
tmp
sabineschaller marked this conversation as resolved.
Show resolved Hide resolved
34 changes: 30 additions & 4 deletions packages/backend/src/config/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as crypto from 'crypto'
import { readFileSync } from 'fs'
import * as fs from 'fs'
import { ConnectionOptions } from 'tls'

function envString(name: string, value: string): string {
Expand Down Expand Up @@ -109,6 +109,9 @@ export const Config = {
'AUTH_SERVER_SPEC',
'https://raw.githubusercontent.com/interledger/open-payments/77462cd0872be8d0fa487a4b233defe2897a7ee4/auth-server-open-api-spec.yaml'
),
privateKey: parseOrProvisionKey(
envString('PRIVATE_KEY_PATH', './tmp/private.pem')
),

/** Frontend **/
frontendUrl: envString('FRONTEND_URL', 'http://localhost:3000')
Expand All @@ -123,17 +126,40 @@ function parseRedisTlsConfig(

// self-signed certs.
if (caFile !== '') {
options.ca = readFileSync(caFile)
options.ca = fs.readFileSync(caFile)
options.rejectUnauthorized = false
}

if (certFile !== '') {
options.cert = readFileSync(certFile)
options.cert = fs.readFileSync(certFile)
}

if (keyFile !== '') {
options.key = readFileSync(keyFile)
options.key = fs.readFileSync(keyFile)
}

return Object.keys(options).length > 0 ? options : undefined
}

function parseOrProvisionKey(keyPath: string): crypto.KeyObject {
sabineschaller marked this conversation as resolved.
Show resolved Hide resolved
try {
const key = crypto.createPrivateKey(fs.readFileSync(keyPath))
const jwk = key.export({ format: 'jwk' })
if (jwk.crv === 'Ed25519') {
return key
} else {
console.log('Private key is not EdDSA-Ed25519 key. Generating new key.')
}
} catch {
console.log('Private key could not be loaded. Generating new key.')
}
const keypair = crypto.generateKeyPairSync('ed25519')
sabineschaller marked this conversation as resolved.
Show resolved Hide resolved
sabineschaller marked this conversation as resolved.
Show resolved Hide resolved
if (!fs.existsSync('./tmp')) {
fs.mkdirSync('./tmp')
}
fs.writeFileSync(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will overwrite an existing private.pem if the provided PRIVATE_KEY_PATH couldn't be loaded, which is probably ok 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering that, too. But I don't see a reason to keep the old ones as long as the new one is also associated with this RS. And by associating I mean adding it to the internal key registry. Should this PR also do that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaning towards not overwriting.
I don't like the idea of potentially overwriting a file not intended for for Rafiki, however unlikely such a misconfiguration may be.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And by associating I mean adding it to the internal key registry. Should this PR also do that?

I think we should hold off until we decide if we're going to switch the key registry to using JWKS

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaning towards not overwriting.
I don't like the idea of potentially overwriting a file not intended for for Rafiki, however unlikely such a misconfiguration may be.

Should we use unique tmp dirs?

Copy link
Member Author

@sabineschaller sabineschaller Oct 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should hold off until we decide if we're going to switch the key registry to using JWKS

I'll create an issue to also create a payment pointer for the Rafiki instance itself that will then be linked to the key, in whatever way and form we end up doing that (probably JWKS endpoint).

'./tmp/private.pem',
keypair.privateKey.export({ format: 'pem', type: 'pkcs8' })
)
return keypair.privateKey
}