diff --git a/src/client/callers/index.ts b/src/client/callers/index.ts index 48189df7c..fe2ec3c7f 100644 --- a/src/client/callers/index.ts +++ b/src/client/callers/index.ts @@ -65,10 +65,8 @@ import vaultsRename from './vaultsRename'; import vaultsScan from './vaultsScan'; import vaultsSecretsCat from './vaultsSecretsCat'; import vaultsSecretsEnv from './vaultsSecretsEnv'; -import vaultsSecretsGet from './vaultsSecretsGet'; import vaultsSecretsList from './vaultsSecretsList'; import vaultsSecretsMkdir from './vaultsSecretsMkdir'; -import vaultsSecretsNew from './vaultsSecretsNew'; import vaultsSecretsNewDir from './vaultsSecretsNewDir'; import vaultsSecretsRename from './vaultsSecretsRename'; import vaultsSecretsRemove from './vaultsSecretsRemove'; @@ -147,10 +145,8 @@ const clientManifest = { vaultsScan, vaultsSecretsCat, vaultsSecretsEnv, - vaultsSecretsGet, vaultsSecretsList, vaultsSecretsMkdir, - vaultsSecretsNew, vaultsSecretsNewDir, vaultsSecretsRename, vaultsSecretsRemove, @@ -228,10 +224,8 @@ export { vaultsScan, vaultsSecretsCat, vaultsSecretsEnv, - vaultsSecretsGet, vaultsSecretsList, vaultsSecretsMkdir, - vaultsSecretsNew, vaultsSecretsNewDir, vaultsSecretsRename, vaultsSecretsRemove, diff --git a/src/client/callers/vaultsSecretsGet.ts b/src/client/callers/vaultsSecretsGet.ts deleted file mode 100644 index 5f4a6b541..000000000 --- a/src/client/callers/vaultsSecretsGet.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { HandlerTypes } from '@matrixai/rpc'; -import type VaultsSecretsGet from '../handlers/VaultsSecretsGet'; -import { UnaryCaller } from '@matrixai/rpc'; - -type CallerTypes = HandlerTypes; - -const vaultsSecretsGet = new UnaryCaller< - CallerTypes['input'], - CallerTypes['output'] ->(); - -export default vaultsSecretsGet; diff --git a/src/client/callers/vaultsSecretsNew.ts b/src/client/callers/vaultsSecretsNew.ts deleted file mode 100644 index 581bac90b..000000000 --- a/src/client/callers/vaultsSecretsNew.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { HandlerTypes } from '@matrixai/rpc'; -import type VaultsSecretsNew from '../handlers/VaultsSecretsNew'; -import { UnaryCaller } from '@matrixai/rpc'; - -type CallerTypes = HandlerTypes; - -const vaultsSecretsNew = new UnaryCaller< - CallerTypes['input'], - CallerTypes['output'] ->(); - -export default vaultsSecretsNew; diff --git a/src/client/handlers/VaultsSecretsCat.ts b/src/client/handlers/VaultsSecretsCat.ts index b3a3fc32e..c5038cd9f 100644 --- a/src/client/handlers/VaultsSecretsCat.ts +++ b/src/client/handlers/VaultsSecretsCat.ts @@ -13,9 +13,6 @@ import * as vaultsUtils from '../../vaults/utils'; import * as vaultsErrors from '../../vaults/errors'; import * as vaultOps from '../../vaults/VaultOps'; -// This method takes in multiple secret paths, and either returns the file -// contents, or an `ErrorMessage` signifying the error. To read a single secret -// instead, refer to `VaultsSecretsGet`. class VaultsSecretsCat extends DuplexHandler< { db: DB; diff --git a/src/client/handlers/VaultsSecretsGet.ts b/src/client/handlers/VaultsSecretsGet.ts deleted file mode 100644 index 2fb68044b..000000000 --- a/src/client/handlers/VaultsSecretsGet.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { DB } from '@matrixai/db'; -import type { - ClientRPCRequestParams, - ClientRPCResponseResult, - ContentMessage, - SecretIdentifierMessage, -} from '../types'; -import type VaultManager from '../../vaults/VaultManager'; -import { UnaryHandler } from '@matrixai/rpc'; -import * as vaultsUtils from '../../vaults/utils'; -import * as vaultsErrors from '../../vaults/errors'; -import * as vaultOps from '../../vaults/VaultOps'; - -// This method only returns the contents of a single secret, and throws an error -// if the secret couldn't be read. To read multiple secrets, refer to -// `VaultsSecretsCat`. -class VaultsSecretsGet extends UnaryHandler< - { - db: DB; - vaultManager: VaultManager; - }, - ClientRPCRequestParams, - ClientRPCResponseResult -> { - public handle = async ( - input: ClientRPCRequestParams, - ): Promise> => { - const { db, vaultManager }: { db: DB; vaultManager: VaultManager } = - this.container; - return db.withTransactionF(async (tran) => { - const vaultIdFromName = await vaultManager.getVaultId( - input.nameOrId, - tran, - ); - const vaultId = - vaultIdFromName ?? vaultsUtils.decodeVaultId(input.nameOrId); - if (vaultId == null) { - throw new vaultsErrors.ErrorVaultsVaultUndefined( - `Vault "${input.nameOrId}" does not exist`, - ); - } - // Get the contents of the file - return await vaultManager.withVaults([vaultId], async (vault) => { - const content = await vaultOps.getSecret(vault, input.secretName); - return { secretContent: content.toString('binary') }; - }); - }); - }; -} - -export default VaultsSecretsGet; diff --git a/src/client/handlers/VaultsSecretsNew.ts b/src/client/handlers/VaultsSecretsNew.ts deleted file mode 100644 index 23ff7360e..000000000 --- a/src/client/handlers/VaultsSecretsNew.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { ContextTimed } from '@matrixai/contexts'; -import type { DB } from '@matrixai/db'; -import type { JSONValue } from '@matrixai/rpc'; -import type { - ClientRPCRequestParams, - ClientRPCResponseResult, - SecretContentMessage, - SuccessMessage, -} from '../types'; -import type VaultManager from '../../vaults/VaultManager'; -import { UnaryHandler } from '@matrixai/rpc'; -import * as vaultsUtils from '../../vaults/utils'; -import * as vaultsErrors from '../../vaults/errors'; -import * as vaultOps from '../../vaults/VaultOps'; - -class VaultsSecretsNew extends UnaryHandler< - { - db: DB; - vaultManager: VaultManager; - }, - ClientRPCRequestParams, - ClientRPCResponseResult -> { - public handle = async ( - input: ClientRPCRequestParams, - _cancel: (reason?: any) => void, - _meta: Record | undefined, - ctx: ContextTimed, - ): Promise> => { - const { db, vaultManager }: { db: DB; vaultManager: VaultManager } = - this.container; - await db.withTransactionF(async (tran) => { - const vaultIdFromName = await vaultManager.getVaultId( - input.nameOrId, - tran, - ); - const vaultId = - vaultIdFromName ?? vaultsUtils.decodeVaultId(input.nameOrId); - if (vaultId == null) { - throw new vaultsErrors.ErrorVaultsVaultUndefined( - `Vault "${input.nameOrId}" does not exist`, - ); - } - const content = Buffer.from(input.secretContent, 'binary'); - await vaultManager.withVaults( - [vaultId], - async (vault) => { - await vaultOps.addSecret(vault, input.secretName, content); - }, - tran, - ctx, - ); - }); - return { success: true }; - }; -} - -export default VaultsSecretsNew; diff --git a/src/client/handlers/index.ts b/src/client/handlers/index.ts index 4d2d74727..4a7bd1af8 100644 --- a/src/client/handlers/index.ts +++ b/src/client/handlers/index.ts @@ -82,10 +82,8 @@ import VaultsRename from './VaultsRename'; import VaultsScan from './VaultsScan'; import VaultsSecretsCat from './VaultsSecretsCat'; import VaultsSecretsEnv from './VaultsSecretsEnv'; -import VaultsSecretsGet from './VaultsSecretsGet'; import VaultsSecretsList from './VaultsSecretsList'; import VaultsSecretsMkdir from './VaultsSecretsMkdir'; -import VaultsSecretsNew from './VaultsSecretsNew'; import VaultsSecretsNewDir from './VaultsSecretsNewDir'; import VaultsSecretsRename from './VaultsSecretsRename'; import VaultsSecretsRemove from './VaultsSecretsRemove'; @@ -187,10 +185,8 @@ const serverManifest = (container: { vaultsScan: new VaultsScan(container), vaultsSecretsCat: new VaultsSecretsCat(container), vaultsSecretsEnv: new VaultsSecretsEnv(container), - vaultsSecretsGet: new VaultsSecretsGet(container), vaultsSecretsList: new VaultsSecretsList(container), vaultsSecretsMkdir: new VaultsSecretsMkdir(container), - vaultsSecretsNew: new VaultsSecretsNew(container), vaultsSecretsNewDir: new VaultsSecretsNewDir(container), vaultsSecretsRename: new VaultsSecretsRename(container), vaultsSecretsRemove: new VaultsSecretsRemove(container), @@ -270,10 +266,8 @@ export { VaultsScan, VaultsSecretsCat, VaultsSecretsEnv, - VaultsSecretsGet, VaultsSecretsList, VaultsSecretsMkdir, - VaultsSecretsNew, VaultsSecretsNewDir, VaultsSecretsRename, VaultsSecretsRemove, diff --git a/tests/client/handlers/vaults.test.ts b/tests/client/handlers/vaults.test.ts index 4be926dca..9ba1765cf 100644 --- a/tests/client/handlers/vaults.test.ts +++ b/tests/client/handlers/vaults.test.ts @@ -43,12 +43,10 @@ import { VaultsSecretsRemove, VaultsSecretsWriteFile, VaultsSecretsEnv, - VaultsSecretsGet, VaultsSecretsCat, VaultsSecretsList, VaultsSecretsMkdir, VaultsSecretsNewDir, - VaultsSecretsNew, VaultsSecretsRename, VaultsSecretsStat, VaultsVersion, @@ -65,11 +63,9 @@ import { vaultsSecretsRemove, vaultsSecretsWriteFile, vaultsSecretsEnv, - vaultsSecretsGet, vaultsSecretsCat, vaultsSecretsList, vaultsSecretsMkdir, - vaultsSecretsNew, vaultsSecretsNewDir, vaultsSecretsRename, vaultsSecretsStat, @@ -2224,344 +2220,6 @@ describe('vaultsSecretsCat', () => { }, ); }); -describe('vaultsSecretsGet', () => { - const logger = new Logger('vaultsSecretsGet test', LogLevel.WARN, [ - new StreamHandler( - formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`, - ), - ]); - const password = 'helloWorld'; - const localhost = '127.0.0.1'; - let dataDir: string; - let db: DB; - let keyRing: KeyRing; - let tlsConfig: TLSConfig; - let clientService: ClientService; - let webSocketClient: WebSocketClient; - let rpcClient: RPCClient<{ - vaultsSecretsGet: typeof vaultsSecretsGet; - }>; - let vaultManager: VaultManager; - beforeEach(async () => { - dataDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), 'polykey-test-'), - ); - const keysPath = path.join(dataDir, 'keys'); - keyRing = await KeyRing.createKeyRing({ - password, - keysPath, - passwordOpsLimit: keysUtils.passwordOpsLimits.min, - passwordMemLimit: keysUtils.passwordMemLimits.min, - strictMemoryLock: false, - logger, - }); - tlsConfig = await testsUtils.createTLSConfig(keyRing.keyPair); - const dbPath = path.join(dataDir, 'db'); - db = await DB.createDB({ - dbPath, - logger, - }); - const vaultsPath = path.join(dataDir, 'vaults'); - vaultManager = await VaultManager.createVaultManager({ - vaultsPath, - db, - acl: {} as ACL, - keyRing, - nodeManager: {} as NodeManager, - gestaltGraph: {} as GestaltGraph, - notificationsManager: {} as NotificationsManager, - logger, - }); - clientService = new ClientService({ - tlsConfig, - logger: logger.getChild(ClientService.name), - }); - await clientService.start({ - manifest: { - vaultsSecretsGet: new VaultsSecretsGet({ - db, - vaultManager, - }), - }, - host: localhost, - }); - webSocketClient = await WebSocketClient.createWebSocketClient({ - config: { - verifyPeer: false, - }, - host: localhost, - logger: logger.getChild(WebSocketClient.name), - port: clientService.port, - }); - rpcClient = new RPCClient({ - manifest: { - vaultsSecretsGet, - }, - streamFactory: () => webSocketClient.connection.newStream(), - toError: networkUtils.toError, - logger: logger.getChild(RPCClient.name), - }); - }); - afterEach(async () => { - await clientService?.stop({ force: true }); - await webSocketClient.destroy({ force: true }); - await vaultManager.stop(); - await db.stop(); - await keyRing.stop(); - await fs.promises.rm(dataDir, { - force: true, - recursive: true, - }); - }); - test('fails with invalid vault name', async () => { - const vaultName = 'test-vault'; - const secretName = 'secret'; - // Get file - const responseP = rpcClient.methods.vaultsSecretsGet({ - nameOrId: vaultName, - secretName: secretName, - }); - // Read response - await testsUtils.expectRemoteError( - responseP, - vaultsErrors.ErrorVaultsVaultUndefined, - ); - }); - test('gets a secret', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const secretName = 'secret'; - const secretContent = 'secret-content'; - // Write file - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.writeF(async (efs) => { - await efs.writeFile(secretName, secretContent); - }); - }); - // Get file - const response = await rpcClient.methods.vaultsSecretsGet({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretName, - }); - // Read response - expect(response.secretContent).toEqual(secretContent); - }); - test('fails to read invalid secret', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const secretName = 'secret'; - // Get file - const responseP = rpcClient.methods.vaultsSecretsGet({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretName, - }); - // Read response - await testsUtils.expectRemoteError( - responseP, - vaultsErrors.ErrorSecretsSecretUndefined, - ); - }); - test('fails to read a directory', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const secretName = 'secret'; - // Create a directory - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.writeF(async (efs) => { - await efs.mkdir(secretName); - }); - }); - // Get file - const responseP = rpcClient.methods.vaultsSecretsGet({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretName, - }); - // Read response - await testsUtils.expectRemoteError( - responseP, - vaultsErrors.ErrorSecretsIsDirectory, - ); - }); -}); -describe('vaultsSecretsNew', () => { - const logger = new Logger('vaultsSecretsNew test', LogLevel.WARN, [ - new StreamHandler( - formatting.format`${formatting.level}:${formatting.keys}:${formatting.msg}`, - ), - ]); - const password = 'helloWorld'; - const localhost = '127.0.0.1'; - let dataDir: string; - let db: DB; - let keyRing: KeyRing; - let tlsConfig: TLSConfig; - let clientService: ClientService; - let webSocketClient: WebSocketClient; - let rpcClient: RPCClient<{ - vaultsSecretsNew: typeof vaultsSecretsNew; - }>; - let vaultManager: VaultManager; - beforeEach(async () => { - dataDir = await fs.promises.mkdtemp( - path.join(os.tmpdir(), 'polykey-test-'), - ); - const keysPath = path.join(dataDir, 'keys'); - keyRing = await KeyRing.createKeyRing({ - password, - keysPath, - passwordOpsLimit: keysUtils.passwordOpsLimits.min, - passwordMemLimit: keysUtils.passwordMemLimits.min, - strictMemoryLock: false, - logger, - }); - tlsConfig = await testsUtils.createTLSConfig(keyRing.keyPair); - const dbPath = path.join(dataDir, 'db'); - db = await DB.createDB({ - dbPath, - logger, - }); - const vaultsPath = path.join(dataDir, 'vaults'); - vaultManager = await VaultManager.createVaultManager({ - vaultsPath, - db, - acl: {} as ACL, - keyRing, - nodeManager: {} as NodeManager, - gestaltGraph: {} as GestaltGraph, - notificationsManager: {} as NotificationsManager, - logger, - }); - clientService = new ClientService({ - tlsConfig, - logger: logger.getChild(ClientService.name), - }); - await clientService.start({ - manifest: { - vaultsSecretsNew: new VaultsSecretsNew({ - db, - vaultManager, - }), - }, - host: localhost, - }); - webSocketClient = await WebSocketClient.createWebSocketClient({ - config: { - verifyPeer: false, - }, - host: localhost, - logger: logger.getChild(WebSocketClient.name), - port: clientService.port, - }); - rpcClient = new RPCClient({ - manifest: { - vaultsSecretsNew, - }, - streamFactory: () => webSocketClient.connection.newStream(), - toError: networkUtils.toError, - logger: logger.getChild(RPCClient.name), - }); - }); - afterEach(async () => { - await clientService?.stop({ force: true }); - await webSocketClient.destroy({ force: true }); - await vaultManager.stop(); - await db.stop(); - await keyRing.stop(); - await fs.promises.rm(dataDir, { - force: true, - recursive: true, - }); - }); - test('fails with invalid vault name', async () => { - const vaultName = 'test-vault'; - const secretName = 'secret'; - // New file - const responseP = rpcClient.methods.vaultsSecretsNew({ - nameOrId: vaultName, - secretName: secretName, - secretContent: secretName, - }); - await testsUtils.expectRemoteError( - responseP, - vaultsErrors.ErrorVaultsVaultUndefined, - ); - }); - test('creates a secret', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const secretName = 'secret'; - const secretContent = 'secret-content'; - // Create file - await rpcClient.methods.vaultsSecretsNew({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretName, - secretContent: secretContent, - }); - // Check for file - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.readF(async (efs) => { - const fileContent = await efs.readFile(secretName); - expect(fileContent.toString()).toEqual(secretContent); - }); - }); - }); - test('creates nested secret', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const dirName = 'dir'; - const secretName = 'secret'; - const secretPath = path.join(dirName, secretName); - const secretContent = 'secret-content'; - // Create file - await rpcClient.methods.vaultsSecretsNew({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretPath, - secretContent: secretContent, - }); - // Check for file - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.readF(async (efs) => { - const dirStat = await efs.stat(dirName); - expect(dirStat.isDirectory()).toBeTruthy(); - const fileStat = await efs.stat(secretPath); - expect(fileStat.isFile()).toBeTruthy(); - const fileContent = await efs.readFile(secretPath); - expect(fileContent.toString()).toEqual(secretContent); - }); - }); - }); - test('fails to create an existing secret', async () => { - const vaultName = 'test-vault'; - const vaultId = await vaultManager.createVault(vaultName); - const secretName = 'secret'; - const oldSecretContent = 'secret-content'; - const newSecretContent = 'new-secret-content'; - // Write file - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.writeF(async (efs) => { - await efs.writeFile(secretName, oldSecretContent); - }); - }); - // Cat file - const responseP = rpcClient.methods.vaultsSecretsNew({ - nameOrId: vaultsUtils.encodeVaultId(vaultId), - secretName: secretName, - secretContent: newSecretContent, - }); - // Read response - await testsUtils.expectRemoteError( - responseP, - vaultsErrors.ErrorSecretsSecretDefined, - ); - // Confirm the file is unchanged - await vaultManager.withVaults([vaultId], async (vault) => { - await vault.readF(async (efs) => { - const content = await efs.readFile(secretName); - expect(content.toString()).toEqual(oldSecretContent); - }); - }); - }); -}); describe('vaultsSecretsRemove', () => { const logger = new Logger('vaultsSecretsRemove test', LogLevel.WARN, [ new StreamHandler(