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

Emit plain file when key is empty #520

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

thomaslepoix
Copy link

Renewal of #338

Fixes: #120

Co-Authored-By: Slaier <slaier@users.noreply.github.com>
@@ -124,6 +125,16 @@ in {
'';
};

defaultSopsKey = mkOption {
Copy link
Owner

@Mic92 Mic92 Mar 25, 2024

Choose a reason for hiding this comment

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

Currently I don't have a better name but defaultSopsKey sounds very confusing because it's quite overloaded as we have private / public keys everywhere. One has to reach out fo the description to figure out what it's for.

Copy link
Owner

Choose a reason for hiding this comment

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

For your usecase, do you actually need this option?
Is it not enough to set this instead?

{
  sops.defaultSopsFormat = "binary";
}

@@ -15,11 +15,12 @@ let

key = lib.mkOption {
type = lib.types.str;
default = name;
default = if cfg.defaultSopsKey != null then cfg.defaultSopsKey else name;
Copy link
Owner

@Mic92 Mic92 Mar 25, 2024

Choose a reason for hiding this comment

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

Also here, can you not just set the format to "binary" on a per secret base?

```nix
{
sops.secrets.my-config = {
format = "yaml";
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
format = "yaml";
format = "binary";

sops.secrets.my-config = {
format = "yaml";
sopsFile = ./my-config.yaml;
key = "";
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
key = "";

@thomaslepoix
Copy link
Author

thomaslepoix commented Mar 28, 2024

For sops, treating the secret as binary is not the same as treating it as json/yaml with an empty key (whole file), binary puts everything under a data key:

cat file
{
	"acl": {
		"tokens": {
			"initial_management": "911578ef-e979-4811-b607-32b1e9819b85"
		}
	}
}

sops --input-type binary -e file
{
	"data": "ENC[AES256_GCM,data:hMbIl33ak/I4SP+eJtbHwGnUn40OfagGC7AHrKk12KcLbn4M/dRjOQ+h4OwOtfp/ZSo6lyRcZKllA/DI0V6z/pL072Hs/nTkJtDnSZorCOk4THOJ84QOYVe1mcEoptX03NGN,iv:MateN0FjgcpfTcZQ7xdCIBXJW7LjchGLiy3EIo9Kt7g=,tag:7IY0D/VIclNu6oudxtl/Hw==,type:str]",
	"sops": { ... }
}

sops --input-type json -e file
{
	"acl": {
		"tokens": {
			"initial_management": "ENC[AES256_GCM,data:VChCbEmx1Mri5siKZGeIL2f2DQR7aX9YVaXtlFGnwFfkugsc,iv:0nt21nZUKaGCdviDOSCyLDvjjfajZ6UK+Mat/8LZ80I=,tag:gsZ/kavDx/YLfxGjrl5ilQ==,type:str]"
		}
	},
	"sops": { ... }
}

And decrypting as binary a file that was encrypted as json/yaml won't work:

sops --input-type json --output file_enc_json -e file

sops -d --output-type json file_enc_json
{
	"acl": {
		"tokens": {
			"initial_management": "911578ef-e979-4811-b607-32b1e9819b85"
		}
	}
}

sops -d --output-type binary file_enc_json
Error dumping file: error emitting binary store: no binary data found in tree

This is likely not an encrypted binary file? If not, use --output-type to select the correct output type.

So as detailed in the issue, using binary format implies the file was encrypted as such which has several drawbacks:

  • It breaks sops format detection, as json/yaml assumptions from the file extension becomes wrong, since sops-nix will decrypt as binary in the end. So the user has to remember this and act appropriately when encrypting secrets. Note this can go even worse when it comes to IDE plugins that brings sops support.
  • It also breaks a selling feature of sops: diffable encrypted files, as everything is under the same key.
  • It feels odd regarding sops that does not have such a restriction and thus generally unintuitive while learning sops-nix

Now, when the preferred workflow is "every secret its own file" instead of "all secrets in the same file, one secret per key", everything being json/yaml : defaultSopsKey just allows to be more concise than repeating key = ""; but I agree it is really confusion-prone regarding age/pgp keys and I would like to clarify that too. To be fair this confusion is already part of sops which takes the json/yaml semantic for "key" while also dealing with cryptographic keys.

Here is an example for my current use case:

  sops = {
    age.keyFile = "/var/lib/sops-nix/key.txt";
    defaultSopsKey = "";
    defaultSopsFormat = "json";
    secrets = {
      "certs/consul-agent-ca.pem" = {
        sopsFile = self + /secrets/dev/consul-agent-ca.pem;
        format = "binary";
        owner = "consul";
      };
      "consul-encrypt.json" = {
        sopsFile = self + "/secrets/dev/consul-encrypt.json";
        owner = "consul";
        restartUnits = [ "consul-rotate-gossip-encryption-key.service" ];
      };
      "consul-acl-initial-management.json" = {
        sopsFile = self + "/secrets/dev/consul-acl-initial-management.json";
        owner = "consul";
      };
    };
  };

@Mic92
Copy link
Owner

Mic92 commented Apr 6, 2024

I see. Thanks for clarification.

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

Successfully merging this pull request may close these issues.

Support mounting yaml and json files as is?
2 participants