mirror of
https://github.com/Mic92/sops-nix.git
synced 2024-12-14 11:57:52 +00:00
Emit plain file when key is empty
Co-Authored-By: Slaier <slaier@users.noreply.github.com>
This commit is contained in:
parent
aa5caa129b
commit
f21c31dadf
4 changed files with 83 additions and 11 deletions
38
README.md
38
README.md
|
@ -707,6 +707,44 @@ This is how it can be included in your `configuration.nix`:
|
|||
}
|
||||
```
|
||||
|
||||
## Emit plain file for yaml and json formats
|
||||
|
||||
By default, sops-nix extracts a single key from yaml and json files. If you
|
||||
need the plain file instead of extracting a specific key from the input document,
|
||||
you can set `key` to an empty string.
|
||||
|
||||
For example, the input document `my-config.yaml` likes this:
|
||||
|
||||
```yaml
|
||||
my-secret1: ENC[AES256_GCM,data:tkyQPQODC3g=,iv:yHliT2FJ74EtnLIeeQtGbOoqVZnF0q5HiXYMJxYx6HE=,tag:EW5LV4kG4lcENaN2HIFiow==,type:str]
|
||||
my-secret2: ENC[AES256_GCM,data:tkyQPQODC3g=,iv:yHliT2FJ74EtnLIeeQtGbOoqVZnF0q5HiXYMJxYx6HE=,tag:EW5LV4kG4lcENaN2HIFiow==,type:str]
|
||||
sops:
|
||||
kms: []
|
||||
gcp_kms: []
|
||||
azure_kv: []
|
||||
hc_vault: []
|
||||
...
|
||||
```
|
||||
|
||||
This is how it can be included in your NixOS module:
|
||||
|
||||
```nix
|
||||
{
|
||||
sops.secrets.my-config = {
|
||||
format = "yaml";
|
||||
sopsFile = ./my-config.yaml;
|
||||
key = "";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Then, it will be mounted as `/run/secrets/my-config`:
|
||||
|
||||
```yaml
|
||||
my-secret1: hello
|
||||
my-secret2: hello
|
||||
```
|
||||
|
||||
## Use with home manager
|
||||
|
||||
sops-nix also provides a home-manager module.
|
||||
|
|
|
@ -15,11 +15,12 @@ let
|
|||
|
||||
key = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = name;
|
||||
default = if cfg.defaultSopsKey != null then cfg.defaultSopsKey else name;
|
||||
description = ''
|
||||
Key used to lookup in the sops file.
|
||||
No tested data structures are supported right now.
|
||||
This option is ignored if format is binary.
|
||||
"" means whole file.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -131,6 +132,16 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
defaultSopsKey = mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Default key used to lookup in all secrets.
|
||||
This option is ignored if format is binary.
|
||||
"" means whole file.
|
||||
'';
|
||||
};
|
||||
|
||||
validateSopsFiles = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
|
|
|
@ -41,11 +41,12 @@ let
|
|||
};
|
||||
key = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = config._module.args.name;
|
||||
default = if cfg.defaultSopsKey != null then cfg.defaultSopsKey else config._module.args.name;
|
||||
description = ''
|
||||
Key used to lookup in the sops file.
|
||||
No tested data structures are supported right now.
|
||||
This option is ignored if format is binary.
|
||||
"" means whole file.
|
||||
'';
|
||||
};
|
||||
path = lib.mkOption {
|
||||
|
@ -176,6 +177,16 @@ in {
|
|||
'';
|
||||
};
|
||||
|
||||
defaultSopsKey = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
Default key used to lookup in all secrets.
|
||||
This option is ignored if format is binary.
|
||||
"" means whole file.
|
||||
'';
|
||||
};
|
||||
|
||||
validateSopsFiles = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
|
|
|
@ -294,12 +294,20 @@ func decryptSecret(s *secret, sourceFiles map[string]plainData) error {
|
|||
case Binary, Dotenv, Ini:
|
||||
sourceFile.binary = plain
|
||||
case Yaml:
|
||||
if err := yaml.Unmarshal(plain, &sourceFile.data); err != nil {
|
||||
return fmt.Errorf("cannot parse yaml of '%s': %w", s.SopsFile, err)
|
||||
if s.Key == "" {
|
||||
sourceFile.binary = plain
|
||||
} else {
|
||||
if err := yaml.Unmarshal(plain, &sourceFile.data); err != nil {
|
||||
return fmt.Errorf("Cannot parse yaml of '%s': %w", s.SopsFile, err)
|
||||
}
|
||||
}
|
||||
case JSON:
|
||||
if err := json.Unmarshal(plain, &sourceFile.data); err != nil {
|
||||
return fmt.Errorf("cannot parse json of '%s': %w", s.SopsFile, err)
|
||||
if s.Key == "" {
|
||||
sourceFile.binary = plain
|
||||
} else {
|
||||
if err := json.Unmarshal(plain, &sourceFile.data); err != nil {
|
||||
return fmt.Errorf("Cannot parse json of '%s': %w", s.SopsFile, err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("secret of type %s in %s is not supported", s.Format, s.SopsFile)
|
||||
|
@ -309,11 +317,15 @@ func decryptSecret(s *secret, sourceFiles map[string]plainData) error {
|
|||
case Binary, Dotenv, Ini:
|
||||
s.value = sourceFile.binary
|
||||
case Yaml, JSON:
|
||||
strVal, err := recurseSecretKey(sourceFile.data, s.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("secret %s in %s is not valid: %w", s.Name, s.SopsFile, err)
|
||||
if s.Key == "" {
|
||||
s.value = sourceFile.binary
|
||||
} else {
|
||||
strVal, err := recurseSecretKey(sourceFile.data, s.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("secret %s in %s is not valid: %w", s.Name, s.SopsFile, err)
|
||||
}
|
||||
s.value = []byte(strVal)
|
||||
}
|
||||
s.value = []byte(strVal)
|
||||
}
|
||||
sourceFiles[s.SopsFile] = sourceFile
|
||||
return nil
|
||||
|
@ -482,7 +494,7 @@ func (app *appContext) validateSopsFile(s *secret, file *secretFile) error {
|
|||
s.Name, s.SopsFile, s.Format,
|
||||
file.firstSecret.Format, file.firstSecret.Name)
|
||||
}
|
||||
if app.checkMode != Manifest && (s.Format != Binary && s.Format != Dotenv && s.Format != Ini) {
|
||||
if app.checkMode != Manifest && !(s.Format == Binary || s.Format == Dotenv || s.Format == Ini) && s.Key != "" {
|
||||
_, err := recurseSecretKey(file.keys, s.Key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("secret %s in %s is not valid: %w", s.Name, s.SopsFile, err)
|
||||
|
|
Loading…
Reference in a new issue