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

Remove newlines by default when exporting contents using secrets env #329

Merged
merged 1 commit into from
Nov 19, 2024

Conversation

aryanjassal
Copy link
Member

@aryanjassal aryanjassal commented Nov 12, 2024

Description

The standard to end all files in Unix is adding a newline at the end of the file. All editors, including vim do it. However, adding a stray newline at the end of a secret, like a password, can have adverse effects.

As such, this PR will, by default, trim the single trailing newline, with an option to disable it if needed.

Issues Fixed

Tasks

  • 1. Remove newlines by default
  • 2. Add a new option to allow preserving newlines
  • 3. Add tests ensuring this behaviour

Final checklist

  • Domain specific tests
  • Full tests
  • Updated inline-comment documentation
  • Lint fixed
  • Squash and rebased
  • Sanity check the final build

@aryanjassal aryanjassal self-assigned this Nov 12, 2024
@aryanjassal
Copy link
Member Author

aryanjassal commented Nov 12, 2024

We are using spawnSync to spawn the env command. This will result in everything else being blocked, and in cases of a long-running command, will also lead to websocket timeouts. To avoid this, I will change it to use spawn much like what I did in secrets edit.

Also, there was a minor inaccuracy in the command, where the command would fail without any environment variables being provided. This is different than the Unix env, which just runs the command with all the system variables instead. was this intentional or should I fix it?

@tegefaulkes @CMCDragonkai

@CMCDragonkai
Copy link
Member

In our case polykey secrets env doesn't make sense to run with no variables. But... What do you mean by runs with system variables?

@aryanjassal
Copy link
Member Author

In our case polykey secrets env doesn't make sense to run with no variables. But... What do you mean by runs with system variables?

By default, when no variables are provided to env, it exports all the current shell variables into the command. This can be previewed by running env in the terminal, which would output all the current variables. That's what gets passed on to any command. Any other variables we define gets appended to that list.

In our case, it does not make much sense, but is a deviation from the standard Unix behaviour, which is why I wanted to ask and confirm this.

@aryanjassal
Copy link
Member Author

We are using spawnSync to spawn the env command. This will result in everything else being blocked, and in cases of a long-running command, will also lead to websocket timeouts. To avoid this, I will change it to use spawn much like what I did in secrets edit.

After talking about this with Brian, I have realised that the Polykey client is actually stopped before the commands are even run. This means that, without a connection to Polykey, the websocket errors won't happen, and that is a non-issue in this case.

I did a manual sanity check by using a long-running command in secrets env, and it didn't throw any errors.

@aryanjassal
Copy link
Member Author

aryanjassal commented Nov 13, 2024

The syntax to preserve newlines for a secret is as follows:

[aryanj@matrix-34xx:~]$ polykey secrets env vault:SECRET1 vault:SECRET2
SECRET1='testing123'
SECRET2='testing123'

[aryanj@matrix-34xx:~]$ polykey secrets env -pn vault:SECRET1 vault:SECRET2
SECRET1='testing123
'
SECRET2='testing123'

[aryanj@matrix-34xx:~]$ polykey secrets env --preserve-newline VAULT:SECRET3
SECRET3='newlines-after-this

'

[aryanj@matrix-34xx:~]$ polykey secrets env VAULT:SECRET3
SECRET3='newlines-after-this
'

If the newlines should be preserved, then the flag -pn --preserve-newline should be used before providing a secret.

@aryanjassal
Copy link
Member Author

aryanjassal commented Nov 13, 2024

How should I handle providing the same secret in two different contexts? If SECRET1 has been provided with both a preserve newline and without, what should take precedence?

What about cases where we export entire vaults? Currently, the flag does preserve newlines of all the secrets exported from the vault, but what if we need one secret to have newlines, and the rest can be trimmed? Or vice-versa, where all secrets need to have preserved newlines, but one secret needs to be trimmed? How would be handle those cases?

With the way how the command is currently structured, is it not possible to preserve the order of the secrets, so they can't be used for prioritisation.

Currently, the preserving newline takes precedence over trimming them. For example, the following will preserve newlines for all secrets:

[aryanj@matrix-34xx:~]$ polykey secrets env -pn vault vault:SECRET1
SECRET1='testing123
'
SECRET2='testing123
'

Should this be the intentional behaviour? @CMCDragonkai

Copy link
Member Author

@aryanjassal aryanjassal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've run into a roadblock and need some inputs from @CMCDragonkai and @tegefaulkes to help me with some issues.

src/secrets/CommandEnv.ts Outdated Show resolved Hide resolved
src/utils/parsers.ts Show resolved Hide resolved
Copy link

linear bot commented Nov 13, 2024

@CMCDragonkai
Copy link
Member

You can have a global flag or the flags are applied per spec. I would do something like that.

@CMCDragonkai
Copy link
Member

By default secret env is going to need to trim a single trailing newline.

Repeating the spec is an interesting situation I would argue that you maintain order in line with whatever the order of the specification is. In the case of env shells the last one takes priority because of how shell processes them.

@aryanjassal
Copy link
Member Author

After a discussion with Brian, we have come to the following conclusion:

Instead of using a separate option like --preserve-newline, then merging the secrets passed in to that and the original arguments, we instead pass in all the secret paths as arguments. The flag can be used as a modifier to the argument list instead of acting as a separate argument list to keep track of.

This means that all secrets specified are, by default, trimmed. However, if a secret name is present in the list to preserve newlines, then the newlines will be preserved. This approach does cause duplication to the secret path, but that's not a huge concern, as most of the times, the newlines would be trimmed as usual.

This approach solves all the issues. The newline preservation takes precedence. If the newlines must be trimmed, then don't specify it to be preserved. As the arguments need to be populated anyways, they will never be empty, and the usual checks can be done from within the parser without need of manually creating an empty object or throwing an error from the action.

This also, to an extent, treats the symptoms of '--' being weird to use. That is an exceptionally weird issue, as they work perfectly in the tests, but break when used via the command line. I can start by using shell in pkExec, which is being used in the tests. This will let me find out if the shell is misbehaving or not.

@CMCDragonkai
Copy link
Member

Can you also review MatrixAI/Polykey#222 (comment)? I want to make sure we're laying foundations to enable egress schema implementation.

@aryanjassal
Copy link
Member Author

Can you also review MatrixAI/Polykey#222 (comment)? I want to make sure we're laying foundations to enable egress schema implementation.

Just to confirm, this egress schema refers to a schema which would allow formatting of the secrets in a particular way at the time of egress, which would be using the secrets env command in this case? For example, the schema would specify if a secret needs to preserve trailing newline or not. If so, then yes, foundation for supporting this is being laid in this PR.

@aryanjassal aryanjassal marked this pull request as ready for review November 15, 2024 05:45
@aryanjassal aryanjassal force-pushed the feature-env-newline branch 2 times, most recently from 76a1e6f to 6bc2f06 Compare November 15, 2024 06:31
@aryanjassal
Copy link
Member Author

Key changes in this PR:

  • Added a new error which is thrown whenever a subprocess fails. It is used in secrets env (if the command fails) and secrets edit (if the editor fails).
  • Properly removed handlers from editor process in secrets edit
  • Automatically trimming newlines when exporting secrets using secrets env
  • Preserving newlines of any secrets listed in -pn option. (should there be a short form of this option?)
  • Created type for parsed secret path and value ([string, string?, string?] like [vaultName, secretPath, value])
  • Added tests for trimming and preserving newlines using fastcheck

Need input on:

  • Is the addition and usage of ErrorPolykeyCLISubprocessFailure reasonable?
  • Should -pn --preserve-newline have a short form of the option?

@tegefaulkes

@CMCDragonkai
Copy link
Member

Key changes in this PR:

  • Added a new error which is thrown whenever a subprocess fails. It is used in secrets env (if the command fails) and secrets edit (if the editor fails).
  • Properly removed handlers from editor process in secrets edit
  • Automatically trimming newlines when exporting secrets using secrets env
  • Preserving newlines of any secrets listed in -pn option. (should there be a short form of this option?)
  • Created type for parsed secret path and value ([string, string?, string?] like [vaultName, secretPath, value])
  • Added tests for trimming and preserving newlines using fastcheck

Need input on:

  • Is the addition and usage of ErrorPolykeyCLISubprocessFailure reasonable?
  • Should -pn --preserve-newline have a short form of the option?

@tegefaulkes

If we are using exec, subprocess failure should be temporary on Unix systems, because of process replacement. It would be more accurate to say that you were not able to execute the subprocess. Also I prefer the name ChildProcess.

On windows however there is no process replacement. It's always a child process. Did you do cross platform sanity checks?

@aryanjassal
Copy link
Member Author

Did you do cross platform sanity checks?

Oh, it completely slipped my mind. I will do this today before merging.

src/secrets/CommandEnv.ts Outdated Show resolved Hide resolved
src/secrets/CommandEnv.ts Show resolved Hide resolved
tests/utils/utils.ts Outdated Show resolved Hide resolved
@aryanjassal
Copy link
Member Author

On windows however there is no process replacement. It's always a child process. Did you do cross platform sanity checks?

#331

feat: added option to preserve newlines

chore: removed listeners after closing edit process

chore: added fastcheck tests for added features

chore: automatically removing -- from parsed command list

chore: added comments for empty cases

chore: optimised handling of newline preservation

chore: updated tests
@aryanjassal
Copy link
Member Author

The CI is passing, and the PR has been approved. I will be merging it now.

@aryanjassal aryanjassal merged commit 0e43ae8 into staging Nov 19, 2024
22 checks passed
@CMCDragonkai
Copy link
Member

This was a significant change to the UX of secrets env. Now it is actually usable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Update secrets env to omit single trailing \n from files which automatically include it
3 participants