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

List and Delete API Keys from Command Line #64

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 8 additions & 1 deletion orchestrator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@

Orca's web server is designed to receive grading jobs from Bottlenose and push them onto the grading queue accordingly.

## Running the Server
## API Key Scripts

Users running the orchestator can run the following scripts for interacting with API keys:
* `yarn generate-api-key -h <hostname>`
* `yarn list-api-keys -h <hostname>`
* `yarn delete-api-key -h <hostname> -k <apikey>`

**NOTE:** The `POSTGRES_URL` envirnoment variable _must be set_ in order to run these scripts.
2 changes: 2 additions & 0 deletions orchestrator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"private": "true",
"scripts": {
"generate-api-key": "yarn workspace @codegrade-orca/db generate-api-key",
"delete-api-key": "yarn workspace @codegrade-orca/db delete-api-key",
"list-api-keys": "yarn workspace @codegrade-orca/db list-api-keys",
"server": "yarn workspace @codegrade-orca/api start",
"server:dev": "yarn workspace @codegrade-orca/api dev",
"image-builder": "yarn workspace @codegrade-orca/image-build-service start",
Expand Down
4 changes: 3 additions & 1 deletion orchestrator/packages/db/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"scripts": {
"build": "tsc --build",
"check": "tsc --noEmit",
"generate-api-key": "ts-node src/scripts/generate-api-key.ts"
"generate-api-key": "ts-node src/scripts/generate-api-key.ts",
"list-api-keys": "ts-node src/scripts/list-api-keys.ts",
"delete-api-key": "ts-node src/scripts/delete-api-key.ts"
},
"devDependencies": {
"jest-mock-extended": "^3.0.5",
Expand Down
4 changes: 3 additions & 1 deletion orchestrator/packages/db/src/api-key-operations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ export const createAPIKey = async (hostname: string): Promise<string> =>
export const validAPIKey = async (hostname: string, value: string) =>
Boolean(await prismaInstance.apiKey.count({ where: { hostname, value } }))

const generateKey = (): string => randomBytes(KEY_LENGTH).toString('hex');
// randomBytes into hex string will return a value with double the length passed
// to randomBytes
const generateKey = (): string => randomBytes(KEY_LENGTH / 2).toString('hex');
30 changes: 30 additions & 0 deletions orchestrator/packages/db/src/scripts/delete-api-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { parseArgs } from "util";
import prismaInstance from "../prisma-instance";

const main = async () => {
const { values } = parseArgs(
{
options:
{
hostname: { type: "string", short: "h" },
key: { type: "string", short: "k" }
},
}
);
const missing = Object.entries(values).filter(([_, v]) => v === undefined).map(([k, _]) => k);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would be mildly more convenient to use if the -k option is optional when the -h host has a single unique key... Not urgent, but more convenient.

if (missing.length) {
process.stderr.write(`Missing the following options: ${missing.join(', ')}`);
process.exit(1);
}
const { hostname, key } = values;
const deletedResult = await prismaInstance.$transaction(async (tx) => await tx.apiKey.deleteMany(
{ where: { hostname, value: key } }
));
const { count } = deletedResult;
if (!count) {
process.stderr.write("The given key does not exist under the given host name.");
process.exit(1);
}
};

main();
3 changes: 2 additions & 1 deletion orchestrator/packages/db/src/scripts/generate-api-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const main = async () => {
console.error("Must provide hostname for api key generation with flag '-h'.");
process.exit(1);
}
await createAPIKey(hostname as string);
const newKey = await createAPIKey(hostname as string);
process.stdout.write(newKey + "\n");
}

main();
19 changes: 19 additions & 0 deletions orchestrator/packages/db/src/scripts/list-api-keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { parseArgs } from "util";
import prismaInstance from "../prisma-instance";

const main = async () => {
const { values } = parseArgs({ options: { hostname: { type: "string", short: "h" } } });
const { hostname } = values;
if (!hostname) {
process.stderr.write("Must provide hostname option.");
process.exit(1);
}
const keys = await prismaInstance.apiKey.findMany({ where: { hostname } }).then((vals) => vals.map((v) => v.value));
if (!keys.length) {
process.stderr.write("No keys found under given host name.");
process.exit(0);
}
process.stdout.write(keys.join("\n") + "\n");
};

main();
Loading