diff --git a/modules/sops/default.nix b/modules/sops/default.nix index e2d3824a..748678e3 100644 --- a/modules/sops/default.nix +++ b/modules/sops/default.nix @@ -79,6 +79,13 @@ let User of the file. ''; }; + uid = lib.mkOption { + type = with lib.types; nullOr int; + default = -1; + description = '' + UID of the file, only applied when owner is set to "". The UID will be applied even if the corresponding user doesn't exist. + ''; + }; group = lib.mkOption { type = lib.types.str; default = users.${config.owner}.group; @@ -87,6 +94,13 @@ let Group of the file. ''; }; + gid = lib.mkOption { + type = with lib.types; nullOr int; + default = -1; + description = '' + GID of the file, only applied when group is set to "". The UID will be applied even if the corresponding group doesn't exist. + ''; + }; sopsFile = lib.mkOption { type = lib.types.path; defaultText = "\${config.sops.defaultSopsFile}"; diff --git a/pkgs/sops-install-secrets/main.go b/pkgs/sops-install-secrets/main.go index 2597fc5e..c578ab62 100644 --- a/pkgs/sops-install-secrets/main.go +++ b/pkgs/sops-install-secrets/main.go @@ -30,7 +30,9 @@ type secret struct { Key string `json:"key"` Path string `json:"path"` Owner string `json:"owner"` + UID int `json:"uid"` Group string `json:"group"` + GID int `json:"gid"` SopsFile string `json:"sopsFile"` Format FormatType `json:"format"` Mode string `json:"mode"` @@ -475,25 +477,34 @@ func (app *appContext) validateSecret(secret *secret) error { secret.group = 0 } else if app.checkMode == Off || app.ignorePasswd { // we only access to the user/group during deployment - owner, err := user.Lookup(secret.Owner) - if err != nil { - return fmt.Errorf("failed to lookup user '%s': %w", secret.Owner, err) - } - ownerNr, err := strconv.ParseUint(owner.Uid, 10, 64) - if err != nil { - return fmt.Errorf("cannot parse uid %s: %w", owner.Uid, err) - } - secret.owner = int(ownerNr) - group, err := user.LookupGroup(secret.Group) - if err != nil { - return fmt.Errorf("failed to lookup group '%s': %w", secret.Group, err) + if secret.Owner == "" && secret.UID >= 0 { + secret.owner = secret.UID + } else { + owner, err := user.Lookup(secret.Owner) + if err != nil { + return fmt.Errorf("failed to lookup user '%s': %w", secret.Owner, err) + } + uid, err := strconv.ParseUint(owner.Uid, 10, 64) + if err != nil { + return fmt.Errorf("cannot parse uid %s: %w", owner.Uid, err) + } + secret.owner = int(uid) } - groupNr, err := strconv.ParseUint(group.Gid, 10, 64) - if err != nil { - return fmt.Errorf("cannot parse gid %s: %w", group.Gid, err) + + if secret.Group == "" && secret.GID >= 0 { + secret.group = secret.GID + } else { + group, err := user.LookupGroup(secret.Group) + if err != nil { + return fmt.Errorf("failed to lookup group '%s': %w", secret.Group, err) + } + gid, err := strconv.ParseUint(group.Gid, 10, 64) + if err != nil { + return fmt.Errorf("cannot parse gid %s: %w", group.Gid, err) + } + secret.group = int(gid) } - secret.group = int(groupNr) } if secret.Format == "" {