Skip to content

Commit cafaf3e

Browse files
committed
feat: allowing to pass in vault name without path for secrets env
[ci skip]
1 parent 3d6ec55 commit cafaf3e

18 files changed

+345
-254
lines changed

src/secrets/CommandEnv.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CommandEnv extends CommandPolykey {
2828
binParsers.parseEnvArgs,
2929
);
3030
this.action(async (args: Array<string>, options) => {
31+
console.error(args)
3132
const { default: PolykeyClient } = await import(
3233
'polykey/dist/PolykeyClient'
3334
);

src/secrets/CommandStat.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class CommandStat extends CommandPolykey {
1313
this.argument(
1414
'<secretPath>',
1515
'Path to where the secret, specified as <vaultName>:<directoryPath>',
16-
binParsers.parseSecretPathValue,
16+
binParsers.parseSecretPath,
1717
);
1818
this.addOption(binOptions.nodeId);
1919
this.addOption(binOptions.clientHost);

src/utils/parsers.ts

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import * as gestaltsUtils from 'polykey/dist/gestalts/utils';
88
import * as networkUtils from 'polykey/dist/network/utils';
99
import * as nodesUtils from 'polykey/dist/nodes/utils';
1010

11-
const secretPathRegex = /^([\w-]+)(?::([^\0\\=]+))?$/;
11+
const vaultNameRegex = /^(?!.*[:])[ -~\t\n]*$/s;
12+
const secretPathRegex = /^(?!.*[=])[ -~\t\n]*$/s;
13+
const vaultNameSecretPathRegex = /^([\w-]+)(?::([^\0\\=]+))?$/;
1214
const secretPathValueRegex = /^([a-zA-Z_][\w]+)?$/;
1315
const environmentVariableRegex = /^([a-zA-Z_]+[a-zA-Z0-9_]*)?$/;
1416

@@ -80,15 +82,26 @@ function parseSecretPathOptional(
8082
lastEqualIndex === -1
8183
? undefined
8284
: secretPath.substring(lastEqualIndex + 1);
83-
if (!secretPathRegex.test(splitSecretPath)) {
85+
if (!vaultNameSecretPathRegex.test(splitSecretPath)) {
8486
throw new commander.InvalidArgumentError(
8587
`${secretPath} is not of the format <vaultName>[:<directoryPath>][=<value>]`,
8688
);
8789
}
88-
const [, vaultName, directoryPath] = splitSecretPath.match(secretPathRegex)!;
90+
const [, vaultName, directoryPath] = splitSecretPath.match(
91+
vaultNameSecretPathRegex,
92+
)!;
8993
return [vaultName, directoryPath, value];
9094
}
9195

96+
function parseVaultName(vaultName: string): string {
97+
if (!vaultNameRegex.test(vaultName)) {
98+
throw new commander.InvalidArgumentError(
99+
`${vaultName} is not a valid vault name`,
100+
);
101+
}
102+
return vaultName;
103+
}
104+
92105
function parseSecretPath(secretPath: string): [string, string, string?] {
93106
// E.g. If 'vault1:a/b/c', ['vault1', 'a/b/c'] is returned
94107
// If 'vault1', an error is thrown
@@ -111,8 +124,40 @@ function parseSecretPathValue(secretPath: string): [string, string, string?] {
111124
return [vaultName, directoryPath, value];
112125
}
113126

114-
function parseSecretPathEnv(secretPath: string): [string, string, string?] {
115-
const [vaultName, directoryPath, value] = parseSecretPath(secretPath);
127+
function parseSecretPathEnv(secretPath: string): [string, string?, string?] {
128+
// The colon character `:` is prohibited in vaultName, so it's first occurence
129+
// means that this is the delimiter between vaultName and secretPath.
130+
const colonIndex = secretPath.indexOf(':');
131+
// If no colon exists, treat entire string as vault name
132+
if (colonIndex === -1) {
133+
return [parseVaultName(secretPath), undefined, undefined];
134+
}
135+
// Calculate contents before the `=` separator
136+
const vaultNamePart = secretPath.substring(0, colonIndex);
137+
const secretPathPart = secretPath.substring(colonIndex + 1);
138+
// Calculate contents after the `=` separator
139+
const equalIndex = secretPathPart.indexOf('=');
140+
const splitSecretPath =
141+
equalIndex === -1
142+
? secretPathPart
143+
: secretPathPart.substring(0, equalIndex);
144+
const valueData =
145+
equalIndex === -1 ? undefined : secretPathPart.substring(equalIndex + 1);
146+
if (splitSecretPath != null && !secretPathRegex.test(splitSecretPath)) {
147+
throw new commander.InvalidArgumentError(
148+
`${secretPath} is not of the format <vaultName>[:<secretPath>][=<value>]`,
149+
);
150+
}
151+
const parsedVaultName = parseVaultName(vaultNamePart);
152+
const parsedSecretPath = splitSecretPath.match(secretPathRegex)?.[0];
153+
const [vaultName, directoryPath, value] = [
154+
parsedVaultName,
155+
parsedSecretPath,
156+
valueData,
157+
];
158+
console.error('vaultName', vaultName)
159+
console.error('directoryPath', directoryPath)
160+
console.error('value', value)
116161
if (value != null && !environmentVariableRegex.test(value)) {
117162
throw new commander.InvalidArgumentError(
118163
`${value} is not a valid environment variable name`,
@@ -189,20 +234,26 @@ function parseEnvArgs(
189234
value: string,
190235
prev: [Array<[string, string, string?]>, Array<string>] | undefined,
191236
): [Array<[string, string, string?]>, Array<string>] {
237+
console.error('original value', value)
192238
const current: [Array<[string, string, string?]>, Array<string>] = prev ?? [
193239
[],
194240
[],
195241
];
196242
if (current[1].length === 0) {
197243
// Parse a secret path
198244
try {
199-
current[0].push(parseSecretPathEnv(value));
245+
const [vaultName, secretPath, valueData] = parseSecretPathEnv(value);
246+
const parsedSecretPath = secretPath == null ? '/' : secretPath;
247+
console.error(`parsed. [${vaultName}, ${parsedSecretPath}, ${valueData}]`)
248+
current[0].push([vaultName, parsedSecretPath, valueData]);
200249
} catch (e) {
201250
if (!(e instanceof commander.InvalidArgumentError)) throw e;
251+
console.error('errored. value', value)
202252
// If we get an invalid argument error then we switch over to parsing args verbatim
203253
current[1].push(value);
204254
}
205255
} else {
256+
console.error('added secret path. value', value)
206257
// Otherwise we just have the cmd args
207258
current[1].push(value);
208259
}
@@ -215,13 +266,15 @@ function parseEnvArgs(
215266
}
216267

217268
export {
269+
vaultNameRegex,
218270
secretPathRegex,
219271
secretPathValueRegex,
220272
environmentVariableRegex,
221273
validateParserToArgParser,
222274
validateParserToArgListParser,
223275
parseCoreCount,
224276
parseSecretPathOptional,
277+
parseVaultName,
225278
parseSecretPath,
226279
parseSecretPathValue,
227280
parseSecretPathEnv,

src/vaults/CommandClone.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ class CommandClone extends CommandPolykey {
1111
super(...args);
1212
this.name('clone');
1313
this.description('Clone a Vault from Another Node');
14-
this.argument('<vaultNameOrId>', 'Name or Id of the vault to be cloned');
14+
this.argument(
15+
'<vaultName>',
16+
'Name of the vault to be cloned',
17+
binParsers.parseVaultName,
18+
);
1519
this.argument(
1620
'<nodeId>',
1721
'Id of the node to clone the vault from',

src/vaults/CommandCreate.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@ import CommandPolykey from '../CommandPolykey';
44
import * as binUtils from '../utils';
55
import * as binOptions from '../utils/options';
66
import * as binProcessors from '../utils/processors';
7+
import * as binParsers from '../utils/parsers';
78

89
class CommandCreate extends CommandPolykey {
910
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
1011
super(...args);
1112
this.name('create');
1213
this.aliases(['touch']);
1314
this.description('Create a new Vault');
14-
this.argument('<vaultName>', 'Name of the new vault to be created');
15+
this.argument(
16+
'<vaultName>',
17+
'Name of the new vault to be created',
18+
binParsers.parseVaultName,
19+
);
1520
this.addOption(binOptions.nodeId);
1621
this.addOption(binOptions.clientHost);
1722
this.addOption(binOptions.clientPort);

src/vaults/CommandDelete.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ import CommandPolykey from '../CommandPolykey';
33
import * as binUtils from '../utils';
44
import * as binOptions from '../utils/options';
55
import * as binProcessors from '../utils/processors';
6+
import * as binParsers from '../utils/parsers';
67

78
class CommandDelete extends CommandPolykey {
89
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
910
super(...args);
1011
this.name('delete');
1112
this.description('Delete an Existing Vault');
12-
this.argument('<vaultName>', 'Name of the vault to be deleted');
13+
this.argument(
14+
'<vaultName>',
15+
'Name of the vault to be deleted',
16+
binParsers.parseVaultName,
17+
);
1318
this.addOption(binOptions.nodeId);
1419
this.addOption(binOptions.clientHost);
1520
this.addOption(binOptions.clientPort);

src/vaults/CommandLog.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ import CommandPolykey from '../CommandPolykey';
44
import * as binUtils from '../utils';
55
import * as binOptions from '../utils/options';
66
import * as binProcessors from '../utils/processors';
7+
import * as binParsers from '../utils/parsers';
78

89
class CommandLog extends CommandPolykey {
910
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
1011
super(...args);
1112
this.name('log');
1213
this.description('Get the Version History of a Vault');
13-
this.argument('<vaultName>', 'Name of the vault to obtain the log from');
14+
this.argument(
15+
'<vaultName>',
16+
'Name of the vault to obtain the log from',
17+
binParsers.parseVaultName,
18+
);
1419
this.addOption(binOptions.commitId);
1520
this.addOption(binOptions.depth);
1621
this.addOption(binOptions.nodeId);

src/vaults/CommandPermissions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import * as binProcessors from '../utils/processors';
33
import * as binUtils from '../utils';
44
import CommandPolykey from '../CommandPolykey';
55
import * as binOptions from '../utils/options';
6+
import * as binParsers from '../utils/parsers';
67

78
class CommandPermissions extends CommandPolykey {
89
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
910
super(...args);
1011
this.name('permissions');
1112
this.alias('perms');
1213
this.description('Sets the permissions of a vault for Node Ids');
13-
this.argument('<vaultName>', 'Name or ID of the vault');
14+
this.argument('<vaultName', 'Name of the vault', binParsers.parseVaultName);
1415
this.addOption(binOptions.nodeId);
1516
this.addOption(binOptions.clientHost);
1617
this.addOption(binOptions.clientPort);

src/vaults/CommandPull.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ class CommandPull extends CommandPolykey {
1111
super(...args);
1212
this.name('pull');
1313
this.description('Pull a Vault from Another Node');
14-
this.argument('<vaultNameOrId>', 'Name of the vault to be pulled into');
14+
this.argument(
15+
'<vaultName>',
16+
'Name of the vault to be pulled into',
17+
binParsers.parseVaultName,
18+
);
1519
this.argument(
1620
'[targetNodeId]',
1721
'(Optional) target node to pull from',

src/vaults/CommandRename.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@ import CommandPolykey from '../CommandPolykey';
33
import * as binUtils from '../utils';
44
import * as binOptions from '../utils/options';
55
import * as binProcessors from '../utils/processors';
6+
import * as binParsers from '../utils/parsers';
67

78
class CommandRename extends CommandPolykey {
89
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
910
super(...args);
1011
this.name('rename');
1112
this.description('Rename an Existing Vault');
12-
this.argument('<vaultName>', 'Name of the vault to be renamed');
13-
this.argument('<newVaultName>', 'New name of the vault');
13+
this.argument(
14+
'<vaultName>',
15+
'Name of the vault to be renamed',
16+
binParsers.parseVaultName,
17+
);
18+
this.argument(
19+
'<newVaultName>',
20+
'New name of the vault',
21+
binParsers.parseVaultName,
22+
);
1423
this.addOption(binOptions.nodeId);
1524
this.addOption(binOptions.clientHost);
1625
this.addOption(binOptions.clientPort);

0 commit comments

Comments
 (0)