This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const crypto = require('node:crypto');
|
||||
const { isIP } = require('node:net');
|
||||
const secretStore = require('./secret-store');
|
||||
const { parseOnlineBackupKey } = require('./online-backup');
|
||||
|
||||
const STORED_LEGACY_ENTRY_KEYS = ['createdAt', 'encryptedKey', 'id'];
|
||||
const STORED_EXPIRING_ENTRY_KEYS = ['createdAt', 'encryptedKey', 'expiresAt', 'id'];
|
||||
const STORED_IP_ENTRY_KEYS = ['createdAt', 'encryptedKey', 'expiresAt', 'id', 'sourceIp'];
|
||||
const STORED_V1_DOCUMENT_KEYS = ['keys', 'version'];
|
||||
const STORED_GENERATED_DOCUMENT_KEYS = ['generation', 'keys', 'version'];
|
||||
const KEYRING_ERROR_CODES = Object.freeze({
|
||||
@@ -181,13 +183,15 @@ function createOnlineBackupKeyring({
|
||||
|
||||
function validateEntry(entry) {
|
||||
const hasLegacyShape = hasExactKeys(entry, STORED_LEGACY_ENTRY_KEYS);
|
||||
const hasExpiringShape = hasExactKeys(entry, STORED_EXPIRING_ENTRY_KEYS);
|
||||
const hasIpShape = hasExactKeys(entry, STORED_IP_ENTRY_KEYS);
|
||||
const hasExpiringShape = hasExactKeys(entry, STORED_EXPIRING_ENTRY_KEYS) || hasIpShape;
|
||||
if (
|
||||
(!hasLegacyShape && !hasExpiringShape)
|
||||
|| !isCanonicalId(entry.id)
|
||||
|| typeof entry.encryptedKey !== 'string'
|
||||
|| !isEncrypted(entry.encryptedKey)
|
||||
|| typeof entry.createdAt !== 'string'
|
||||
|| (hasIpShape && (typeof entry.sourceIp !== 'string' || !isIP(entry.sourceIp)))
|
||||
) {
|
||||
return { issue: KEYRING_ERROR_CODES.structure, id: typeof entry?.id === 'string' ? entry.id : null };
|
||||
}
|
||||
@@ -228,6 +232,7 @@ function createOnlineBackupKeyring({
|
||||
encryptedKey: entry.encryptedKey,
|
||||
createdAt,
|
||||
expiresAt,
|
||||
...(hasIpShape ? { sourceIp: entry.sourceIp } : {}),
|
||||
key
|
||||
}
|
||||
};
|
||||
@@ -413,7 +418,7 @@ function createOnlineBackupKeyring({
|
||||
const contents = JSON.stringify({
|
||||
version: 2,
|
||||
generation,
|
||||
keys: entries.map(({ id, encryptedKey, createdAt, expiresAt }) => ({ id, encryptedKey, createdAt, expiresAt: expiresAt ?? null }))
|
||||
keys: entries.map(({ id, encryptedKey, createdAt, expiresAt, sourceIp }) => ({ id, encryptedKey, createdAt, expiresAt: expiresAt ?? null, ...(sourceIp ? { sourceIp } : {}) }))
|
||||
});
|
||||
const payload = canonicalPayload(parseDocument(contents));
|
||||
const stagingPath = temporaryPath('staging');
|
||||
@@ -455,11 +460,12 @@ function createOnlineBackupKeyring({
|
||||
}
|
||||
const entries = activeEntries
|
||||
.sort((left, right) => right.createdAt.localeCompare(left.createdAt))
|
||||
.map(({ id, key, createdAt, expiresAt }) => Object.freeze({
|
||||
.map(({ id, key, createdAt, expiresAt, sourceIp }) => Object.freeze({
|
||||
id,
|
||||
displayKey: `${key.slice(0, 9)}…${key.slice(-4)}`,
|
||||
createdAt,
|
||||
expiresAt
|
||||
expiresAt,
|
||||
...(sourceIp ? { sourceIp } : {})
|
||||
}));
|
||||
return Object.freeze({
|
||||
entries: Object.freeze(entries),
|
||||
|
||||
Reference in New Issue
Block a user