Last active
October 30, 2024 14:51
-
-
Save bmingles/536b21bab983b28037630a37ae709cd9 to your computer and use it in GitHub Desktop.
KeyGen
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// Experiment with generating a key pair, uploading the public key to the server, | |
// and authenticating with the private key. | |
import { | |
generateBase64KeyPair, | |
loginClientWithKeyPair, | |
uploadPublicKey, | |
} from '@deephaven-enterprise/auth-nodejs' | |
import { loginPrompt } from './loginPrompt.mjs' | |
import { createDheClient, getDhe } from './utils.mjs' | |
const { serverUrl, username, password } = await loginPrompt() | |
const credentials = { | |
type: 'password', | |
username, | |
token: password, | |
} | |
const dhe = await getDhe(serverUrl) | |
const dheClient = await createDheClient(dhe, serverUrl) | |
const { publicKey, privateKey } = await generateBase64KeyPair() | |
console.log({ publicKey, privateKey }) | |
await uploadPublicKey(dheClient, credentials, publicKey, 'ec') | |
const keyPairCredentials = { | |
type: 'keyPair', | |
username: credentials.username, | |
keyPair: { | |
type: 'ec', | |
publicKey, | |
privateKey, | |
}, | |
} | |
await loginClientWithKeyPair( | |
await createDheClient(dhe, serverUrl), | |
keyPairCredentials, | |
) | |
console.log('Yeah!!') | |
process.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Prompt the user for information to connect to a DH server. | |
*/ | |
import fs from 'node:fs' | |
import path from 'node:path' | |
import { read } from 'read' | |
if (typeof globalThis.__dirname === 'undefined') { | |
globalThis.__dirname = import.meta.dirname | |
} | |
const AUTO_COMPLETE_PATH = path.join( | |
__dirname, | |
'..', | |
'..', | |
'tabAutocomplete.txt', | |
) | |
export async function loginPrompt() { | |
const completions = getAutoComplete(AUTO_COMPLETE_PATH) | |
const serverUrlRaw = await read({ | |
prompt: 'Enter the Deephaven server URL: ', | |
completer: (input) => { | |
const filtered = completions.filter((c) => c.includes(input)) | |
return [filtered, input] | |
}, | |
}) | |
const serverUrl = new URL(serverUrlRaw) | |
const username = await read({ prompt: 'Enter your username: ' }) | |
const password = await read({ | |
prompt: 'Enter your password: ', | |
replace: '*', | |
silent: true, | |
}) | |
return { | |
serverUrl, | |
username, | |
password, | |
} | |
} | |
// Optionally provide a list of server URLs to `tab` autocompletions via serverList.txt. | |
function getAutoComplete(autoCompletePath) { | |
if (!fs.existsSync(autoCompletePath)) { | |
return [] | |
} | |
return String(fs.readFileSync(autoCompletePath)).split('\n') | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "generate-key-pair", | |
"description": "Generate Key Pair", | |
"version": "0.0.1", | |
"bin": "./index.mjs", | |
"dependencies": { | |
"@deephaven-enterprise/auth-nodejs": "1.20240723.107-alpha-auth-nodejs.23555", | |
"@deephaven/jsapi-nodejs": "^0.96.2-alpha-jsapi-nodejs.7", | |
"read": "^4.0.0" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { loadModules } from '@deephaven/jsapi-nodejs' | |
import path from 'node:path' | |
export async function getDhe(serverUrl) { | |
polyfill() | |
const tmpDir = path.join(__dirname, 'tmp') | |
// Download jsapi `ESM` files from DH Community server. | |
await loadModules({ | |
serverUrl, | |
serverPaths: ['irisapi/irisapi.nocache.js'], | |
download: true, | |
storageDir: tmpDir, | |
sourceModuleType: 'cjs', | |
targetModuleType: 'esm', | |
}) | |
// DHE currently exposes the jsapi via the global `iris` object. | |
return iris | |
} | |
export function polyfill() { | |
// These will eventually not be needed once JSAPI is updated to not rely on `window` and `self`. | |
// @ts-ignore | |
globalThis.self = globalThis | |
// @ts-ignore | |
globalThis.window = globalThis | |
// This is needed to mimic running in a local http browser environment when | |
// making requests to the server. This at least impacts websocket connections. | |
// Not sure if it is needed for other requests. The url is an arbitrary | |
// non-https url just to make it stand out in logs. | |
// @ts-ignore | |
global.window.location = new URL('http://deephaven-keygen.localhost/') | |
} | |
export async function createDheClient(dhe, serverUrl) { | |
const dheClient = new dhe.Client(getWsUrl(serverUrl).toString()) | |
return new Promise((resolve) => { | |
const unsubscribe = dheClient.addEventListener( | |
dhe.Client.EVENT_CONNECT, | |
() => { | |
unsubscribe() | |
resolve(dheClient) | |
}, | |
) | |
}) | |
} | |
/** | |
* Get the WebSocket URL for a DHE server URL. | |
* @param serverUrl The DHE server URL. | |
* @returns The WebSocket URL. | |
*/ | |
export function getWsUrl(serverUrl) { | |
const url = new URL('/socket', serverUrl) | |
if (url.protocol === 'http:') { | |
url.protocol = 'ws:' | |
} else { | |
url.protocol = 'wss:' | |
} | |
return url | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment