Skip to content

Commit

Permalink
feat(hashicorp-vault-signing-manager): add 30 second timeout for vaul…
Browse files Browse the repository at this point in the history
…t signing manager
  • Loading branch information
polymath-eric committed Apr 16, 2024
1 parent a9683cb commit 82f02a1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { HexString } from '@polkadot/util/types';
import fetch from 'cross-fetch';

import { SignerTimeoutError } from '../../types';
import {
GetKeyResponse,
ListKeysResponse,
Expand All @@ -9,6 +10,8 @@ import {
VaultKey,
} from './types';

const TIMEOUT = 30 * 1000;

export class HashicorpVault {
private headers: { 'X-Vault-Token': string };

Expand All @@ -34,12 +37,9 @@ export class HashicorpVault {
* Retrieve all public keys (hex) stored in the Vault with their respective names and versions
*/
public async fetchAllKeys(): Promise<VaultKey[]> {
const { headers } = this;
const url = this.getUrl('keys');

const response = await fetch(this.getUrl('keys'), {
method: 'LIST',
headers,
});
const response = await this.fetch(url, 'LIST');

// Vault returns 404 for empty lists for [ease of implementation](https://github.com/hashicorp/vault/issues/1365#issuecomment-216369253)
if (response.status === 404) {
Expand All @@ -63,12 +63,8 @@ export class HashicorpVault {
* @param name - name of the key for which to fetch the public keys
*/
public async fetchKeysByName(name: string): Promise<VaultKey[]> {
const { headers } = this;

const response = await fetch(this.getUrl('keys', name), {
method: 'GET',
headers,
});
const url = this.getUrl('keys', name);
const response = await this.fetch(url, 'GET');

await this.assertResponseOk(response);

Expand Down Expand Up @@ -97,13 +93,7 @@ export class HashicorpVault {
* @param data - data that will be signed
*/
public async signData(name: string, data: SignRequestPayload): Promise<HexString> {
const { headers } = this;

const response = await fetch(this.getUrl('sign', name), {
method: 'POST',
body: JSON.stringify(data),
headers,
});
const response = await this.fetch(this.getUrl('sign', name), 'POST', data);

await this.assertResponseOk(response);

Expand All @@ -120,6 +110,39 @@ export class HashicorpVault {
return `0x00${hexSignature}`;
}

private async fetch(url: string, method: string, body?: unknown): Promise<Response> {
const { headers } = this;
const controller = new AbortController();
const timer = setTimeout(() => {
controller.abort();
}, TIMEOUT);

try {
const response = await fetch(url, {
method,
body: body ? JSON.stringify(body) : undefined,
headers,
signal: controller.signal,
});

return response;
} catch (error) {
if (controller.signal.aborted) {
throw new SignerTimeoutError({
message: 'Hashicorp Vault request timed out',
data: {
timeoutSeconds: TIMEOUT / 1000,
url,
},
});
} else {
throw error;
}
} finally {
clearTimeout(timer);
}
}

/**
*
* @param res
Expand Down
13 changes: 13 additions & 0 deletions packages/hashicorp-vault-signing-manager/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,16 @@ export interface AddressedVaultKey extends VaultKey {
*/
address: string;
}

export class SignerTimeoutError extends Error {
public data?: Record<string, unknown>;

/**
* @hidden
*/
constructor({ message, data }: { message?: string; data?: Record<string, unknown> }) {
super(message);

this.data = data;
}
}

0 comments on commit 82f02a1

Please sign in to comment.