Skip to content

Commit bf8e1c5

Browse files
authored
Merge pull request #417 from MatrixAI/feature-make-rename-accept-vault-path-for-both-params
Allow fully qualified paths for new secret name in secrets rename
2 parents 9180ec4 + 8d9e54b commit bf8e1c5

File tree

3 files changed

+84
-19
lines changed

3 files changed

+84
-19
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,6 @@ dist
130130
# editor
131131
.vscode/
132132
.idea/
133+
134+
# prettier for editor formatting
135+
.prettierrc

src/secrets/CommandRename.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,30 @@ class CommandRename extends CommandPolykey {
1616
'Path to where the secret to be renamed, specified as <vaultName>:<directoryPath>',
1717
binParsers.parseSecretPath,
1818
);
19-
this.argument('<newSecretName>', 'New name of the secret');
19+
this.argument(
20+
'<newSecretName>',
21+
'Fully-qualified new name for the secret, specified as <vaultName>:<secretPath>',
22+
binParsers.parseSecretPath,
23+
);
2024
this.addOption(binOptions.nodeId);
2125
this.addOption(binOptions.clientHost);
2226
this.addOption(binOptions.clientPort);
23-
this.action(async (secretPath, newSecretName, options) => {
27+
this.action(async (secretPath, newSecretPath, options) => {
28+
// Rename operation cannot work across vaults, only within a vault
29+
if (secretPath[0] !== newSecretPath[0]) {
30+
throw new errors.ErrorPolykeyCLIRenameSecret(
31+
'Cannot rename file into another vault',
32+
);
33+
}
2434
// Ensure that a valid secret path is provided
2535
if (secretPath[1] == null) {
2636
throw new errors.ErrorPolykeyCLIRenameSecret(
27-
'EPERM: Cannot rename vault root',
37+
'Cannot rename vault root',
38+
);
39+
}
40+
if (newSecretPath[1] == null) {
41+
throw new errors.ErrorPolykeyCLIRenameSecret(
42+
'Cannot rename to vault root',
2843
);
2944
}
3045
const { default: PolykeyClient } = await import(
@@ -63,7 +78,7 @@ class CommandRename extends CommandPolykey {
6378
metadata: auth,
6479
nameOrId: secretPath[0],
6580
secretName: secretPath[1],
66-
newSecretName: newSecretName,
81+
newSecretName: newSecretPath[1],
6782
}),
6883
meta,
6984
);

tests/secrets/rename.test.ts

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ describe('commandRenameSecret', () => {
1212
const logger = new Logger('CLI Test', LogLevel.WARN, [new StreamHandler()]);
1313
let dataDir: string;
1414
let polykeyAgent: PolykeyAgent;
15-
let command: Array<string>;
1615

1716
beforeEach(async () => {
1817
dataDir = await fs.promises.mkdtemp(
@@ -33,6 +32,7 @@ describe('commandRenameSecret', () => {
3332
logger: logger,
3433
});
3534
});
35+
3636
afterEach(async () => {
3737
await polykeyAgent.stop();
3838
await fs.promises.rm(dataDir, {
@@ -44,39 +44,86 @@ describe('commandRenameSecret', () => {
4444
test('should rename secrets', async () => {
4545
const vaultName = 'vault' as VaultName;
4646
const vaultId = await polykeyAgent.vaultManager.createVault(vaultName);
47-
const secretName = 'secret';
48-
const newSecretName = 'secret-renamed';
49-
const secretContent = 'this is the secret';
47+
const oldSecretName = 'secretOld';
48+
const newSecretName = 'secretNew';
49+
const secretContent = 'this is the secret for simple rename';
5050
await polykeyAgent.vaultManager.withVaults([vaultId], async (vault) => {
51-
await vaultOps.addSecret(vault, secretName, secretContent);
51+
await vaultOps.addSecret(vault, oldSecretName, secretContent);
5252
});
53-
command = [
53+
54+
// Should fail if only new name is provided
55+
const command1 = [
5456
'secrets',
5557
'rename',
5658
'-np',
5759
dataDir,
58-
`${vaultName}:${secretName}`,
60+
`${vaultName}:${oldSecretName}`,
5961
newSecretName,
6062
];
61-
const result = await testUtils.pkStdio(command, {
63+
const result1 = await testUtils.pkStdio(command1, {
6264
env: { PK_PASSWORD: password },
6365
cwd: dataDir,
6466
});
65-
expect(result.exitCode).toBe(0);
67+
expect(result1.exitCode).toBe(1);
68+
await polykeyAgent.vaultManager.withVaults([vaultId], async (vault) => {
69+
const list = await vaultOps.listSecrets(vault);
70+
expect(list.sort()).toStrictEqual([oldSecretName]);
71+
});
72+
73+
// Should pass if fully-qualified path is provided
74+
const command2 = [
75+
'secrets',
76+
'rename',
77+
'-np',
78+
dataDir,
79+
`${vaultName}:${oldSecretName}`,
80+
`${vaultName}:${newSecretName}`,
81+
];
82+
const result2 = await testUtils.pkStdio(command2, {
83+
env: { PK_PASSWORD: password },
84+
cwd: dataDir,
85+
});
86+
expect(result2.exitCode).toBe(0);
6687
await polykeyAgent.vaultManager.withVaults([vaultId], async (vault) => {
6788
const list = await vaultOps.listSecrets(vault);
6889
expect(list.sort()).toStrictEqual([newSecretName]);
6990
});
7091
});
71-
test('should not rename vault root', async () => {
72-
const vaultName = 'vault' as VaultName;
73-
await polykeyAgent.vaultManager.createVault(vaultName);
74-
command = ['secrets', 'rename', '-np', dataDir, vaultName, 'rename'];
92+
93+
test('should fail renaming across vaults', async () => {
94+
const vaultName1 = 'vault1' as VaultName;
95+
const vaultName2 = 'vault2' as VaultName;
96+
const vaultId1 = await polykeyAgent.vaultManager.createVault(vaultName1);
97+
const vaultId2 = await polykeyAgent.vaultManager.createVault(vaultName2);
98+
const oldSecretName = 'secretOld';
99+
const newSecretName = 'secretNew';
100+
const secretContent = 'this is the secret for simple rename';
101+
await polykeyAgent.vaultManager.withVaults([vaultId1], async (vault) => {
102+
await vaultOps.addSecret(vault, oldSecretName, secretContent);
103+
});
104+
const command = [
105+
'secrets',
106+
'rename',
107+
'-np',
108+
dataDir,
109+
`${vaultName1}:${oldSecretName}`,
110+
`${vaultName2}:${newSecretName}`,
111+
];
75112
const result = await testUtils.pkStdio(command, {
76113
env: { PK_PASSWORD: password },
77114
cwd: dataDir,
78115
});
79-
expect(result.exitCode).not.toBe(0);
80-
expect(result.stderr).toInclude('EPERM');
116+
expect(result.exitCode).toBe(1);
117+
await polykeyAgent.vaultManager.withVaults(
118+
[vaultId1, vaultId2],
119+
async (vault1, vault2) => {
120+
// The secret wasn't changed in the original place
121+
const list1 = await vaultOps.listSecrets(vault1);
122+
expect(list1.sort()).toStrictEqual([oldSecretName]);
123+
// The target vault is also unchanged
124+
const list2 = await vaultOps.listSecrets(vault2);
125+
expect(list2.sort()).toStrictEqual([]);
126+
},
127+
);
81128
});
82129
});

0 commit comments

Comments
 (0)