Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow exporting all environment variables by default for secrets env #312

Merged
merged 1 commit into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
451 changes: 229 additions & 222 deletions src/secrets/CommandEnv.ts

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion src/utils/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,13 @@ const envVariables = new commander.Option('-e --env <envs...>', 'specify envs')
.argParser(
(value: string, previous: Array<[string, string, string?]> | undefined) => {
const acc = previous ?? [];
acc.push(binParsers.parseSecretPathEnv(value));
const [vault, secret, val] = binParsers.parseSecretPathEnv(value);
if (secret == null) {
throw new commander.InvalidArgumentError(
'You must provide at least one secret path',
);
}
acc.push([vault, secret, val]);
return acc;
},
);
Expand Down
71 changes: 57 additions & 14 deletions src/utils/parsers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import * as gestaltsUtils from 'polykey/dist/gestalts/utils';
import * as networkUtils from 'polykey/dist/network/utils';
import * as nodesUtils from 'polykey/dist/nodes/utils';

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

Expand Down Expand Up @@ -80,15 +82,26 @@ function parseSecretPathOptional(
lastEqualIndex === -1
? undefined
: secretPath.substring(lastEqualIndex + 1);
if (!secretPathRegex.test(splitSecretPath)) {
if (!vaultNameSecretPathRegex.test(splitSecretPath)) {
throw new commander.InvalidArgumentError(
`${secretPath} is not of the format <vaultName>[:<directoryPath>][=<value>]`,
);
}
const [, vaultName, directoryPath] = splitSecretPath.match(secretPathRegex)!;
const [, vaultName, directoryPath] = splitSecretPath.match(
vaultNameSecretPathRegex,
)!;
return [vaultName, directoryPath, value];
}

function parseVaultName(vaultName: string): string {
if (!vaultNameRegex.test(vaultName)) {
throw new commander.InvalidArgumentError(
`${vaultName} is not a valid vault name`,
);
}
return vaultName;
}

function parseSecretPath(secretPath: string): [string, string, string?] {
// E.g. If 'vault1:a/b/c', ['vault1', 'a/b/c'] is returned
// If 'vault1', an error is thrown
Expand All @@ -111,8 +124,37 @@ function parseSecretPathValue(secretPath: string): [string, string, string?] {
return [vaultName, directoryPath, value];
}

function parseSecretPathEnv(secretPath: string): [string, string, string?] {
const [vaultName, directoryPath, value] = parseSecretPath(secretPath);
function parseSecretPathEnv(secretPath: string): [string, string?, string?] {
// The colon character `:` is prohibited in vaultName, so it's first occurence
// means that this is the delimiter between vaultName and secretPath.
const colonIndex = secretPath.indexOf(':');
// If no colon exists, treat entire string as vault name
if (colonIndex === -1) {
return [parseVaultName(secretPath), undefined, undefined];
}
// Calculate contents before the `=` separator
const vaultNamePart = secretPath.substring(0, colonIndex);
const secretPathPart = secretPath.substring(colonIndex + 1);
// Calculate contents after the `=` separator
const equalIndex = secretPathPart.indexOf('=');
const splitSecretPath =
equalIndex === -1
? secretPathPart
: secretPathPart.substring(0, equalIndex);
const valueData =
equalIndex === -1 ? undefined : secretPathPart.substring(equalIndex + 1);
if (splitSecretPath != null && !secretPathRegex.test(splitSecretPath)) {
throw new commander.InvalidArgumentError(
`${secretPath} is not of the format <vaultName>[:<secretPath>][=<value>]`,
);
}
const parsedVaultName = parseVaultName(vaultNamePart);
const parsedSecretPath = splitSecretPath.match(secretPathRegex)?.[0] ?? '/';
const [vaultName, directoryPath, value] = [
parsedVaultName,
parsedSecretPath,
valueData,
];
if (value != null && !environmentVariableRegex.test(value)) {
throw new commander.InvalidArgumentError(
`${value} is not a valid environment variable name`,
Expand Down Expand Up @@ -182,25 +224,24 @@ const parseSeedNodes: (data: string) => [SeedNodes, boolean] =

/**
* This parses the arguments used for the env command. It should be formatted as
* <secretPath...> [--] [cmd] [cmdArgs...]
* The cmd part of the list is separated in two ways, either the user explicitly uses `--` or the first non-secret path separates it.
* <secretPath...> [-- cmd [cmdArgs...]]
* The cmd part of the list is separated by using `--`.
*/
function parseEnvArgs(
value: string,
prev: [Array<[string, string, string?]>, Array<string>] | undefined,
): [Array<[string, string, string?]>, Array<string>] {
const current: [Array<[string, string, string?]>, Array<string>] = prev ?? [
prev: [Array<[string, string?, string?]>, Array<string>] | undefined,
): [Array<[string, string?, string?]>, Array<string>] {
const current: [Array<[string, string?, string?]>, Array<string>] = prev ?? [
[],
[],
];
if (current[1].length === 0) {
// Parse a secret path
try {
if (value !== '--') {
current[0].push(parseSecretPathEnv(value));
} catch (e) {
if (!(e instanceof commander.InvalidArgumentError)) throw e;
// If we get an invalid argument error then we switch over to parsing args verbatim
} else {
current[1].push(value);
return current;
}
} else {
// Otherwise we just have the cmd args
Expand All @@ -215,13 +256,15 @@ function parseEnvArgs(
}

export {
vaultNameRegex,
secretPathRegex,
secretPathValueRegex,
environmentVariableRegex,
validateParserToArgParser,
validateParserToArgListParser,
parseCoreCount,
parseSecretPathOptional,
parseVaultName,
parseSecretPath,
parseSecretPathValue,
parseSecretPathEnv,
Expand Down
6 changes: 5 additions & 1 deletion src/vaults/CommandClone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ class CommandClone extends CommandPolykey {
super(...args);
this.name('clone');
this.description('Clone a Vault from Another Node');
this.argument('<vaultNameOrId>', 'Name or Id of the vault to be cloned');
this.argument(
'<vaultName>',
'Name of the vault to be cloned',
binParsers.parseVaultName,
);
this.argument(
'<nodeId>',
'Id of the node to clone the vault from',
Expand Down
7 changes: 6 additions & 1 deletion src/vaults/CommandCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';
import * as binParsers from '../utils/parsers';

class CommandCreate extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('create');
this.aliases(['touch']);
this.description('Create a new Vault');
this.argument('<vaultName>', 'Name of the new vault to be created');
this.argument(
'<vaultName>',
'Name of the new vault to be created',
binParsers.parseVaultName,
);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
Expand Down
7 changes: 6 additions & 1 deletion src/vaults/CommandDelete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';
import * as binParsers from '../utils/parsers';

class CommandDelete extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('delete');
this.description('Delete an Existing Vault');
this.argument('<vaultName>', 'Name of the vault to be deleted');
this.argument(
'<vaultName>',
'Name of the vault to be deleted',
binParsers.parseVaultName,
);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
Expand Down
7 changes: 6 additions & 1 deletion src/vaults/CommandLog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';
import * as binParsers from '../utils/parsers';

class CommandLog extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('log');
this.description('Get the Version History of a Vault');
this.argument('<vaultName>', 'Name of the vault to obtain the log from');
this.argument(
'<vaultName>',
'Name of the vault to obtain the log from',
binParsers.parseVaultName,
);
this.addOption(binOptions.commitId);
this.addOption(binOptions.depth);
this.addOption(binOptions.nodeId);
Expand Down
3 changes: 2 additions & 1 deletion src/vaults/CommandPermissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import * as binProcessors from '../utils/processors';
import * as binUtils from '../utils';
import CommandPolykey from '../CommandPolykey';
import * as binOptions from '../utils/options';
import * as binParsers from '../utils/parsers';

class CommandPermissions extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('permissions');
this.alias('perms');
this.description('Sets the permissions of a vault for Node Ids');
this.argument('<vaultName>', 'Name or ID of the vault');
this.argument('<vaultName', 'Name of the vault', binParsers.parseVaultName);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
Expand Down
6 changes: 5 additions & 1 deletion src/vaults/CommandPull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ class CommandPull extends CommandPolykey {
super(...args);
this.name('pull');
this.description('Pull a Vault from Another Node');
this.argument('<vaultNameOrId>', 'Name of the vault to be pulled into');
this.argument(
'<vaultName>',
'Name of the vault to be pulled into',
binParsers.parseVaultName,
);
this.argument(
'[targetNodeId]',
'(Optional) target node to pull from',
Expand Down
13 changes: 11 additions & 2 deletions src/vaults/CommandRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,23 @@ import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';
import * as binParsers from '../utils/parsers';

class CommandRename extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('rename');
this.description('Rename an Existing Vault');
this.argument('<vaultName>', 'Name of the vault to be renamed');
this.argument('<newVaultName>', 'New name of the vault');
this.argument(
'<vaultName>',
'Name of the vault to be renamed',
binParsers.parseVaultName,
);
this.argument(
'<newVaultName>',
'New name of the vault',
binParsers.parseVaultName,
);
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
this.addOption(binOptions.clientPort);
Expand Down
6 changes: 5 additions & 1 deletion src/vaults/CommandShare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ class CommandShare extends CommandPolykey {
super(...args);
this.name('share');
this.description('Set the Permissions of a Vault for a Node');
this.argument('<vaultName>', 'Name of the vault to be shared');
this.argument(
'<vaultName>',
'Name of the vault to be shared',
binParsers.parseVaultName,
);
this.argument(
'<nodeId>',
'Id of the node to share to',
Expand Down
6 changes: 5 additions & 1 deletion src/vaults/CommandUnshare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ class CommandUnshare extends CommandPolykey {
super(...args);
this.name('unshare');
this.description('Unset the Permissions of a Vault for a Node');
this.argument('<vaultName>', 'Name of the vault to be unshared');
this.argument(
'<vaultName>',
'Name of the vault to be unshared',
binParsers.parseVaultName,
);
this.argument(
'<nodeId>',
'Id of the node to unshare with',
Expand Down
7 changes: 6 additions & 1 deletion src/vaults/CommandVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ import CommandPolykey from '../CommandPolykey';
import * as binUtils from '../utils';
import * as binOptions from '../utils/options';
import * as binProcessors from '../utils/processors';
import * as binParsers from '../utils/parsers';

class CommandVersion extends CommandPolykey {
constructor(...args: ConstructorParameters<typeof CommandPolykey>) {
super(...args);
this.name('version');
this.description('Set a Vault to a Particular Version in its History');
this.argument('<vaultName>', 'Name of the vault to change the version of');
this.argument(
'<vaultName>',
'Name of the vault to change the version of',
binParsers.parseVaultName,
);
this.argument('<versionId>', 'Id of the commit that will be changed to');
this.addOption(binOptions.nodeId);
this.addOption(binOptions.clientHost);
Expand Down
Loading