Skip to content

Commit

Permalink
Manage public-api keys (#295)
Browse files Browse the repository at this point in the history
As part of the new Public API efforts, here are new commands to manage
API keys.
  • Loading branch information
Corentin Mors authored Nov 19, 2024
1 parent f4eb6d2 commit 063ca35
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/command-handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export * from './lock.js';
export * from './logout.js';
export * from './passwords.js';
export * from './read.js';
export * from './publicAPI.js';
export * from './secrets.js';
export * from './secureNotes.js';
export * from './sync.js';
Expand Down
28 changes: 28 additions & 0 deletions src/command-handlers/publicAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { createPublicAPIKey, listPublicAPIKeys, revokePublicAPIKey } from '../endpoints';
import { connectAndPrepare } from '../modules/database';

export const createPublicAPIKeyHandler = async (description: string) => {
const { db, localConfiguration } = await connectAndPrepare({ autoSync: false });
const key = await createPublicAPIKey({ description, localConfiguration });
db.close();

const { accessKey, secretKey, teamUuid } = key;

const deviceAccountKey = `DLP_${teamUuid}_${accessKey}_${secretKey}`;

return deviceAccountKey;
};

export const listPublicAPIKeysHandler = async () => {
const { db, localConfiguration } = await connectAndPrepare({ autoSync: false });
const publicAPIKeys = await listPublicAPIKeys({ localConfiguration });
db.close();

return publicAPIKeys;
};

export const revokePublicAPIKeyHandler = async (accessKey: string) => {
const { db, localConfiguration } = await connectAndPrepare({ autoSync: false });
await revokePublicAPIKey({ accessKey, localConfiguration });
db.close();
};
3 changes: 3 additions & 0 deletions src/commands/team/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Command, Option } from 'commander';
import { teamCredentialsCommands } from './credentials.js';
import { PublicAPICommands } from './publicAPI.js';
import { CouldNotFindTeamCredentialsError } from '../../errors.js';
import {
runTeamDarkWebInsightsReport,
Expand Down Expand Up @@ -28,6 +29,8 @@ export const teamCommands = (params: { program: Command }) => {

teamCredentialsCommands({ teamGroup });

PublicAPICommands({ teamGroup });

teamGroup
.command('members')
.alias('m')
Expand Down
58 changes: 58 additions & 0 deletions src/commands/team/publicAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { createPublicAPIKeyHandler, listPublicAPIKeysHandler, revokePublicAPIKeyHandler } from '../../command-handlers';
import { logger } from '../../logger.js';
import { Command } from 'commander';

export const PublicAPICommands = (params: { teamGroup: Command }) => {
const { teamGroup } = params;

const publicAPIGroup = teamGroup.command('public-api').description('Public API operations');

publicAPIGroup
.command('create-key')
.description('Generate a new Public API key (Bearer token)')
.argument('<description>', 'Description')
.action(async (description: string) => {
const publicAPIToken = await createPublicAPIKeyHandler(description);

logger.success(
'The new Public API key has been generated, you can use it as a Bearer token in your requests:'
);
logger.content(`Bearer ${publicAPIToken}`);
});

publicAPIGroup
.command('list-keys')
.description('List all Public API keys')
.option('--json', 'Output in JSON format')
.action(async (options: { json: boolean }) => {
const publicAPIKeys = await listPublicAPIKeysHandler();

if (options.json) {
logger.content(JSON.stringify(publicAPIKeys));
} else {
console.table(
publicAPIKeys.publicAPIKeys.map((key) => ({
'Creation date': new Date(key.creationDateUnix).toISOString(),
'Update date': new Date(key.updateDateUnix).toISOString(),
'Invalidation date': key.invalidationDateUnix
? new Date(key.invalidationDateUnix).toISOString()
: 'N/A',
'Access key': key.accessKey,
Description: key.description,
Origin: key.origin,
Valid: key.valid ? 'Yes' : 'No',
}))
);
}
});

publicAPIGroup
.command('revoke-key')
.description('Revoke a Public API key')
.argument('<accessKey>', 'Access key')
.action(async (accessKey: string) => {
await revokePublicAPIKeyHandler(accessKey);

logger.success('The Public API key has been revoked');
});
};
36 changes: 36 additions & 0 deletions src/endpoints/createPublicAPIKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { requestUserApi } from '../requestApi.js';
import { LocalConfiguration } from '../types.js';

interface CreatePublicAPIKey {
description: string;
localConfiguration: LocalConfiguration;
}

export interface CreatePublicAPIKeyOutput {
/**
* Team UUID
*/
teamUuid: string;
/**
* Public Api access key
*/
accessKey: string;
/**
* Public Api secret key
*/
secretKey: string;
}

export const createPublicAPIKey = (params: CreatePublicAPIKey) =>
requestUserApi<CreatePublicAPIKeyOutput>({
path: 'partners/CreatePublicAPIKey',
login: params.localConfiguration.login,
deviceKeys: {
accessKey: params.localConfiguration.accessKey,
secretKey: params.localConfiguration.secretKey,
},
payload: {
description: params.description,
origin: 'server_cli',
},
});
3 changes: 3 additions & 0 deletions src/endpoints/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './completeDeviceRegistration.js';
export * from './completeLoginWithAuthTicket.js';
export * from './createPublicAPIKey.js';
export * from './deactivateDevices.js';
export * from './deactivateTeamDevice.js';
export * from './getAuditLogs.js';
Expand All @@ -9,8 +10,10 @@ export * from './getTeamDarkWebInsightsReport.js';
export * from './getTeamMembers.js';
export * from './getTeamReport.js';
export * from './listDevices.js';
export * from './listPublicAPIKeys.js';
export * from './listTeamDevices.js';
export * from './performDuoPushVerification.js';
export * from './performEmailTokenVerification.js';
export * from './performTotpVerification.js';
export * from './registerTeamDevice.js';
export * from './revokePublicAPIKey.js';
53 changes: 53 additions & 0 deletions src/endpoints/listPublicAPIKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { requestUserApi } from '../requestApi.js';
import { LocalConfiguration } from '../types.js';

interface ListPublicAPIKeys {
localConfiguration: LocalConfiguration;
}

export interface ListPublicAPIKeysOutput {
/**
* List of api keys
*/
publicAPIKeys: {
/**
* The creation date
*/
creationDateUnix: number;
/**
* The last modification date
*/
updateDateUnix: number;
/**
* The last invalidation date
*/
invalidationDateUnix: null | number;
/**
* The access key
*/
accessKey: string;
/**
* The description of the api key
*/
description: string;
/**
* Platform used to create the public api key
*/
origin: string;
/**
* Is the public api key activated or not
*/
valid: boolean;
}[];
}

export const listPublicAPIKeys = (params: ListPublicAPIKeys) =>
requestUserApi<ListPublicAPIKeysOutput>({
path: 'partners/ListPublicAPIKeys',
login: params.localConfiguration.login,
deviceKeys: {
accessKey: params.localConfiguration.accessKey,
secretKey: params.localConfiguration.secretKey,
},
payload: {},
});
22 changes: 22 additions & 0 deletions src/endpoints/revokePublicAPIKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { requestUserApi } from '../requestApi.js';
import { LocalConfiguration } from '../types.js';

interface RevokePublicAPIKey {
accessKey: string;
localConfiguration: LocalConfiguration;
}

export interface RevokePublicAPIKeyOutput {}

export const revokePublicAPIKey = (params: RevokePublicAPIKey) =>
requestUserApi<RevokePublicAPIKeyOutput>({
path: 'partners/RevokePublicAPIKey',
login: params.localConfiguration.login,
deviceKeys: {
accessKey: params.localConfiguration.accessKey,
secretKey: params.localConfiguration.secretKey,
},
payload: {
accessKey: params.accessKey,
},
});

0 comments on commit 063ca35

Please sign in to comment.