hiera-eyaml-age 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b410dda98aafc5197a88ce2da1c5b9e946b5262edeed99dc556431d69d8e4801
4
- data.tar.gz: e84d835a8e3f8ab55b2209d51ffc24972b969fed00333797f12dee85c83c7479
3
+ metadata.gz: 705b8add5ef02f0dded07812e427e71e66bb8d9fb232d5caa0a479408186f2b3
4
+ data.tar.gz: dceba351e19d85bc85a716beb1a6cc765bdc343bc1ad33d6113a47d39537ae1c
5
5
  SHA512:
6
- metadata.gz: e4de4e92ce526c1bd1385b9bfc0facc9ff94b45f5c672e72959ee623be5e37f09ff469d22eb51b4c044398f236a24b1d3347dcecd57e77394ee73a036fbb8200
7
- data.tar.gz: 450e0669ae45fd070500042c171c89dc042364847890ea28f9ff8541a2cfbb0cb961e5052a77c6d57e56390386cc03d34a65fa30755e806b1a501f0bcb9236d4
6
+ metadata.gz: eabe1f74179e9013b2d6f410a1e92d76a01990a23bd067a6c637e68394e65bda7061f5272c091a1581de741af2631e842877b80ee81f85540202cdb3b5074cc4
7
+ data.tar.gz: 062a51fa6e8ab4212f6cf1134be570abaf8229d15c3e67c22a723516701afbf9cf910b657d47401f10d49df7838ff91b8cd91dcc3f5729f1273c1ed2aa5453eb
data/.gitignore CHANGED
@@ -1,4 +1,11 @@
1
1
  *.gem
2
2
  *.swp
3
3
  .bundle/
4
+ gem2deb*
5
+ gem2deb*/
6
+ hiera-eyaml-age-*
7
+ hiera-eyaml-age-*/
8
+ hiera-eyaml-age_*
9
+ hiera-eyaml-age_*/
10
+ ruby
4
11
  vendor/
data/CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.1] - 2026-05-27
9
+
10
+ ### Fixed
11
+
12
+ - Widen hiera-eyaml dependency range to `>= 4.2.0, < 6.0` to work with both Debian packaging and current gem releases
13
+
14
+ ## [0.2.0] - 2026-05-26
15
+
16
+ ### Added
17
+
18
+ - Manage packaging (gem, deb)
19
+ - Add options to take identity and/or recipients from environment variables instead of files
20
+
21
+ ### Fixed
22
+
23
+ - Handle errors without dumping age's stderr unless asked for
24
+
25
+ ## [0.1.0]
26
+
27
+ ### Added
28
+
29
+ - init
data/Makefile ADDED
@@ -0,0 +1,29 @@
1
+ VERSION := $(shell ruby -r ./lib/hiera/backend/eyaml/encryptors/age/version \
2
+ -e 'puts Hiera::Backend::Eyaml::Encryptors::AgeVersion::VERSION')
3
+ export DEBEMAIL:=network@ias.edu
4
+
5
+
6
+ .PHONY: gem
7
+ gem: hiera-eyaml-age-$(VERSION).gem
8
+
9
+ .PHONY: deb
10
+ deb: hiera-eyaml-age-$(VERSION).gem
11
+ gem2deb --package hiera-eyaml-age hiera-eyaml-age-$(VERSION).gem
12
+
13
+ targz:
14
+ git archive --output hiera-eyaml-age_$(VERSION).tar.gz --prefix hiera-eyaml-age main
15
+
16
+ .PHONY: packages
17
+ packages: deb gem targz
18
+
19
+ hiera-eyaml-age-$(VERSION).gem:
20
+ gem build hiera-eyaml-age.gemspec
21
+
22
+ .PHONY: clean
23
+ clean:
24
+ rm -rf \
25
+ gem2deb* \
26
+ hiera-eyaml-age-* \
27
+ ruby* \
28
+ hiera-eyaml-age-* \
29
+ hiera-eyaml-age_*
data/README.md CHANGED
@@ -61,6 +61,10 @@ age recipients can be native age public keys (`age1...`) or SSH public keys (`ss
61
61
 
62
62
  Use `eyaml --help` for more, or see the [hiera-eyaml] docs.
63
63
 
64
+ ## Hardware keys and PKCS#11 tokens
65
+
66
+ If your age identity is protected by another factor (e.g. encrypted with a password, or an identity stored with touch required on a hardware security key) be aware that `hiera-eyaml` calls the encryptor once per encrypted value per file. Each call spawns a separate `age` process, which could mean one authorization interaction per encrypted value., depending on your setup. This is a limitation of `hiera-eyaml`'s design, not of `age`.
67
+
64
68
  ### Configuring hiera
65
69
 
66
70
  ```yaml
@@ -20,5 +20,5 @@ Gem::Specification.new do |gem|
20
20
  gem.require_paths = ['lib']
21
21
 
22
22
  gem.required_ruby_version = '>= 3.0'
23
- gem.add_dependency('hiera-eyaml', '~> 5.0')
23
+ gem.add_dependency('hiera-eyaml', '>= 4.2.0', '< 6.0')
24
24
  end
@@ -3,7 +3,7 @@ class Hiera
3
3
  module Eyaml
4
4
  module Encryptors
5
5
  module AgeVersion
6
- VERSION = "0.1.0".freeze
6
+ VERSION = "0.2.1".freeze
7
7
  end
8
8
  end
9
9
  end
@@ -14,7 +14,7 @@ class Hiera
14
14
 
15
15
  self.options = {
16
16
  age_binary_path: {
17
- desc: "Full path to the age executable",
17
+ desc: "Full path to the age executable (use an absolute path in production to avoid PATH-based substitution)",
18
18
  type: :string,
19
19
  default: "age"
20
20
  },
@@ -22,6 +22,10 @@ class Hiera
22
22
  desc: "Path to age identity file for decryption",
23
23
  type: :string
24
24
  },
25
+ identity_env_var: {
26
+ desc: "Name of environment variable containing age identity for decryption",
27
+ type: :string
28
+ },
25
29
  recipients: {
26
30
  desc: "List of recipients (comma separated)",
27
31
  type: :string
@@ -29,6 +33,10 @@ class Hiera
29
33
  recipients_file: {
30
34
  desc: "File containing a list of recipients (one on each line)",
31
35
  type: :string
36
+ },
37
+ recipients_env_var: {
38
+ desc: "Name of environment variable containing age recipients (comma separated)",
39
+ type: :string
32
40
  }
33
41
  }
34
42
 
@@ -53,22 +61,40 @@ class Hiera
53
61
  binmode: true
54
62
  )
55
63
  unless status.success?
56
- raise RecoverableError, "age encrypt failed: #{stderr.strip}"
64
+ warn("age encrypt failed (run with --trace for details, including errors from age which may be sensitive)")
65
+ debug("age encrypt stderr: #{stderr.strip}")
66
+ raise RecoverableError, "age encrypt failed"
57
67
  end
58
68
 
59
69
  stdout
60
70
  end
61
71
 
62
72
  def self.decrypt(ciphertext)
63
- identity_file = option(:identity_file)
64
- debug("age identity file is #{identity_file}")
65
-
66
- if identity_file.nil? || identity_file.empty?
67
- raise ArgumentError,
68
- "No age identity file configured, check age_identity_file configuration value is correct"
69
- elsif !File.exist?(identity_file)
70
- raise ArgumentError,
71
- "Configured age identity file #{identity_file} doesn't exist, check age_identity_file configuration value is correct"
73
+ env_var = option(:identity_env_var)
74
+
75
+ if env_var
76
+ raise ArgumentError, "env #{env_var} is not set" unless ENV[env_var]
77
+
78
+ # Pass the identity via a pipe rather than a temp file so the key
79
+ # material never touches disk. age's --identity accepts /dev/fd/N.
80
+ # Ruby 2.0+ opens FDs with O_CLOEXEC by default, so we must
81
+ # explicitly preserve the read end across the exec boundary.
82
+ r_fd, w_fd = IO.pipe
83
+ w_fd.write(ENV[env_var])
84
+ w_fd.close
85
+ identity_arg = "/dev/fd/#{r_fd.fileno}"
86
+ extra_opts = { r_fd.fileno => r_fd }
87
+ else
88
+ identity_file = option(:identity_file)
89
+ debug("age identity file is #{identity_file}")
90
+
91
+ if identity_file.nil? || identity_file.empty?
92
+ raise ArgumentError,
93
+ "No age identity file configured, check age_identity_file configuration value is correct"
94
+ end
95
+
96
+ identity_arg = identity_file
97
+ extra_opts = {}
72
98
  end
73
99
 
74
100
  stdout, stderr, status =
@@ -76,16 +102,18 @@ class Hiera
76
102
  option(:age_binary_path),
77
103
  "--decrypt",
78
104
  "--identity",
79
- identity_file,
105
+ identity_arg,
80
106
  stdin_data: ciphertext,
81
- binmode: true
107
+ binmode: true,
108
+ **extra_opts
82
109
  )
83
110
 
111
+ r_fd&.close
112
+
84
113
  unless status.success?
85
- warn(
86
- "Fatal: Failed to decrypt ciphertext (check settings and that you are a recipient)"
87
- )
88
- raise StandardError, "age decrypt failed: #{stderr.strip}"
114
+ warn("age decrypt failed (run with --trace for details, including errors from age which may be sensitive)")
115
+ debug("age decrypt stderr: #{stderr.strip}")
116
+ raise StandardError, "age decrypt failed"
89
117
  end
90
118
 
91
119
  stdout
@@ -99,6 +127,14 @@ class Hiera
99
127
  private
100
128
 
101
129
  def determine_recipients
130
+ env_var = option(:recipients_env_var)
131
+ if env_var
132
+ raise ArgumentError, "env #{env_var} is not set" unless ENV[env_var]
133
+
134
+ debug("Using --recipients-env-var option")
135
+ return ENV[env_var].split(",").map(&:strip)
136
+ end
137
+
102
138
  recipient_option = option :recipients
103
139
 
104
140
  unless recipient_option.nil?
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiera-eyaml-age
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - IAS Network
@@ -13,16 +13,22 @@ dependencies:
13
13
  name: hiera-eyaml
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '5.0'
18
+ version: 4.2.0
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '6.0'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: 4.2.0
29
+ - - "<"
24
30
  - !ruby/object:Gem::Version
25
- version: '5.0'
31
+ version: '6.0'
26
32
  description: age encryptor for use with hiera-eyaml
27
33
  executables: []
28
34
  extensions: []
@@ -30,8 +36,10 @@ extra_rdoc_files: []
30
36
  files:
31
37
  - ".gitignore"
32
38
  - ".rubocop.yml"
39
+ - CHANGELOG.md
33
40
  - Gemfile
34
41
  - Gemfile.lock
42
+ - Makefile
35
43
  - README.md
36
44
  - Rakefile
37
45
  - hiera-eyaml-age.gemspec