hiera-eyaml-age 0.1.0
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 +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +53 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +69 -0
- data/README.md +94 -0
- data/Rakefile +9 -0
- data/hiera-eyaml-age.gemspec +24 -0
- data/lib/hiera/backend/eyaml/encryptors/age/eyaml_init.rb +3 -0
- data/lib/hiera/backend/eyaml/encryptors/age/version.rb +11 -0
- data/lib/hiera/backend/eyaml/encryptors/age.rb +125 -0
- metadata +65 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: b410dda98aafc5197a88ce2da1c5b9e946b5262edeed99dc556431d69d8e4801
|
|
4
|
+
data.tar.gz: e84d835a8e3f8ab55b2209d51ffc24972b969fed00333797f12dee85c83c7479
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e4de4e92ce526c1bd1385b9bfc0facc9ff94b45f5c672e72959ee623be5e37f09ff469d22eb51b4c044398f236a24b1d3347dcecd57e77394ee73a036fbb8200
|
|
7
|
+
data.tar.gz: 450e0669ae45fd070500042c171c89dc042364847890ea28f9ff8541a2cfbb0cb961e5052a77c6d57e56390386cc03d34a65fa30755e806b1a501f0bcb9236d4
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.3
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/DotPosition:
|
|
7
|
+
Enabled: false
|
|
8
|
+
|
|
9
|
+
Layout/EndOfLine:
|
|
10
|
+
Enabled: false
|
|
11
|
+
|
|
12
|
+
Layout/LineLength:
|
|
13
|
+
Enabled: false
|
|
14
|
+
|
|
15
|
+
Metrics/AbcSize:
|
|
16
|
+
Enabled: false
|
|
17
|
+
|
|
18
|
+
Metrics/BlockLength:
|
|
19
|
+
Enabled: false
|
|
20
|
+
|
|
21
|
+
Metrics/ClassLength:
|
|
22
|
+
Enabled: false
|
|
23
|
+
|
|
24
|
+
Metrics/CyclomaticComplexity:
|
|
25
|
+
Enabled: false
|
|
26
|
+
|
|
27
|
+
Metrics/MethodLength:
|
|
28
|
+
Enabled: false
|
|
29
|
+
|
|
30
|
+
Metrics/ParameterLists:
|
|
31
|
+
Enabled: false
|
|
32
|
+
|
|
33
|
+
Metrics/PerceivedComplexity:
|
|
34
|
+
Enabled: false
|
|
35
|
+
|
|
36
|
+
Style/ClassAndModuleChildren:
|
|
37
|
+
Enabled: false
|
|
38
|
+
|
|
39
|
+
Style/IfUnlessModifier:
|
|
40
|
+
Enabled: false
|
|
41
|
+
|
|
42
|
+
Style/Documentation:
|
|
43
|
+
Enabled: false
|
|
44
|
+
|
|
45
|
+
Style/FrozenStringLiteralComment:
|
|
46
|
+
Enabled: false
|
|
47
|
+
|
|
48
|
+
Style/StringLiterals:
|
|
49
|
+
Enabled: false
|
|
50
|
+
|
|
51
|
+
# based on https://github.com/voxpupuli/modulesync_config/issues/168
|
|
52
|
+
Style/RegexpLiteral:
|
|
53
|
+
EnforcedStyle: percent_r
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
hiera-eyaml-age (0.1.0)
|
|
5
|
+
hiera-eyaml (~> 5.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
ast (2.4.3)
|
|
11
|
+
base64 (0.3.0)
|
|
12
|
+
hiera-eyaml (5.0.1)
|
|
13
|
+
base64 (~> 0.1)
|
|
14
|
+
highline (>= 2.1, < 4)
|
|
15
|
+
optimist (~> 3.1)
|
|
16
|
+
highline (3.1.2)
|
|
17
|
+
reline
|
|
18
|
+
io-console (0.8.2)
|
|
19
|
+
json (2.19.5)
|
|
20
|
+
language_server-protocol (3.17.0.5)
|
|
21
|
+
lint_roller (1.1.0)
|
|
22
|
+
optimist (3.2.1)
|
|
23
|
+
parallel (2.1.0)
|
|
24
|
+
parser (3.3.11.1)
|
|
25
|
+
ast (~> 2.4.1)
|
|
26
|
+
racc
|
|
27
|
+
prettier_print (1.2.1)
|
|
28
|
+
prism (1.9.0)
|
|
29
|
+
racc (1.8.1)
|
|
30
|
+
rainbow (3.1.1)
|
|
31
|
+
rake (13.4.2)
|
|
32
|
+
regexp_parser (2.12.0)
|
|
33
|
+
reline (0.6.3)
|
|
34
|
+
io-console (~> 0.5)
|
|
35
|
+
rubocop (1.86.2)
|
|
36
|
+
json (~> 2.3)
|
|
37
|
+
language_server-protocol (~> 3.17.0.2)
|
|
38
|
+
lint_roller (~> 1.1.0)
|
|
39
|
+
parallel (>= 1.10)
|
|
40
|
+
parser (>= 3.3.0.2)
|
|
41
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
42
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
43
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
44
|
+
ruby-progressbar (~> 1.7)
|
|
45
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
46
|
+
rubocop-ast (1.49.1)
|
|
47
|
+
parser (>= 3.3.7.2)
|
|
48
|
+
prism (~> 1.7)
|
|
49
|
+
ruby-progressbar (1.13.0)
|
|
50
|
+
syntax (1.2.2)
|
|
51
|
+
syntax_tree (6.3.0)
|
|
52
|
+
prettier_print (>= 1.2.0)
|
|
53
|
+
unicode-display_width (3.2.0)
|
|
54
|
+
unicode-emoji (~> 4.1)
|
|
55
|
+
unicode-emoji (4.2.0)
|
|
56
|
+
|
|
57
|
+
PLATFORMS
|
|
58
|
+
ruby
|
|
59
|
+
x86_64-linux-gnu
|
|
60
|
+
|
|
61
|
+
DEPENDENCIES
|
|
62
|
+
hiera-eyaml-age!
|
|
63
|
+
rake
|
|
64
|
+
rubocop
|
|
65
|
+
syntax
|
|
66
|
+
syntax_tree
|
|
67
|
+
|
|
68
|
+
BUNDLED WITH
|
|
69
|
+
2.6.7
|
data/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
hiera-eyaml-age
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
age encryption backend for [hiera-eyaml].
|
|
5
|
+
|
|
6
|
+
# Motivation
|
|
7
|
+
|
|
8
|
+
The default PKCS#7 encryption scheme used by `hiera-eyaml` works, but relies upon just a single key.
|
|
9
|
+
|
|
10
|
+
A solution that allows each team member and Puppet Server to hold their own keys allows for easier rotation.
|
|
11
|
+
|
|
12
|
+
[hiera-eyaml-gpg] supports each team member using their own keys, but.... it is GPG. Many may not be keen to get a degree in keyring management just to edit hieradata.
|
|
13
|
+
|
|
14
|
+
[age] supports encrypting to many with individual keys as well, but without the hassle. It offers meaningfully stronger encryption, even introducing post-quantum resistance since v1.3.0.
|
|
15
|
+
|
|
16
|
+
# Requirements
|
|
17
|
+
|
|
18
|
+
age [installed] in your `$PATH`.
|
|
19
|
+
|
|
20
|
+
# Install
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
gem install hiera-eyaml-age
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
# Configuration
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
# ~/.eyaml/config.yaml
|
|
30
|
+
age_identity_file: '/path/to/your/identity/file'
|
|
31
|
+
age_recipients: '<age_pubkey1>,<age_pubkey2>,...'
|
|
32
|
+
# age_recipients_file: '/path/to/recipients/file/pubkeys/one/per/line.txt'
|
|
33
|
+
# age_binary_path: '/optional/path/directly/to/age'
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
# Usage
|
|
37
|
+
|
|
38
|
+
## Encrypting and editing encrypted data
|
|
39
|
+
|
|
40
|
+
It is recommended to configure `hiera-eyaml` as above to avoid having to pass the necessary arguments each time.
|
|
41
|
+
|
|
42
|
+
The usual workflow can be as simple as `eyaml edit` and following the instructions at the top of the file:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
eyaml edit /path/to/hieradata/file.yaml
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or more manually, create encrypted ``hiera-eyaml`` blocks encrypted with age:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
eyaml encrypt --encrypt-method age --string "My string to encrypt" --age-recipients age126amywumzxvz2d9umnv3796tfsy044ww7pe7rwampammswl0n4rqv4c557,age162268ddynmjurmd7z628rctuh4qfavd84c62sjxhnmq7sw06c3lsmyetzf
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or pass a file containing a list of recipients (one per line, `#` comments ignored):
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
eyaml encrypt --encrypt-method age --string "My string to encrypt" --age-recipients-file /path/to/youur/recipients/file
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
age recipients can be native age public keys (`age1...`) or SSH public keys (`ssh-ed25519 ...`, `ssh-rsa ...`).
|
|
61
|
+
|
|
62
|
+
Use `eyaml --help` for more, or see the [hiera-eyaml] docs.
|
|
63
|
+
|
|
64
|
+
### Configuring hiera
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
---
|
|
68
|
+
version: 5
|
|
69
|
+
defaults:
|
|
70
|
+
hierarchy:
|
|
71
|
+
- name: "Per-node data"
|
|
72
|
+
lookup_key: eyaml_lookup_key
|
|
73
|
+
options:
|
|
74
|
+
age_identity_file: /opt/puppetlabs/server/data/puppetserver/.age/identity.txt
|
|
75
|
+
path: "nodes/%{::trusted.certname}.yaml"
|
|
76
|
+
- name: "Common data"
|
|
77
|
+
lookup_key: eyaml_lookup_key
|
|
78
|
+
options:
|
|
79
|
+
age_identity_file: /opt/puppetlabs/server/data/puppetserver/.age/identity.txt
|
|
80
|
+
path: "common.yaml"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Installing on Puppet server
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
# Puppet agent and Server have separate Ruby environments
|
|
87
|
+
/opt/puppetlabs/puppet/bin/gem install hiera-eyaml-age
|
|
88
|
+
/opt/puppetlabs/server/bin/puppetserver gem install hiera-eyaml-age
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
[age]: https://age-encryption.org/
|
|
92
|
+
[hiera-eyaml-gpg]: https://github.com/voxpupuli/hiera-eyaml-gpg
|
|
93
|
+
[hiera-eyaml]: https://github.com/voxpupuli/hiera-eyaml
|
|
94
|
+
[installed]: https://age-encryption.org/#installation
|
data/Rakefile
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require 'hiera/backend/eyaml/encryptors/age/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |gem|
|
|
6
|
+
gem.name = 'hiera-eyaml-age'
|
|
7
|
+
gem.version = Hiera::Backend::Eyaml::Encryptors::AgeVersion::VERSION
|
|
8
|
+
gem.description = 'age encryptor for use with hiera-eyaml'
|
|
9
|
+
gem.summary = 'Encryption plugin for hiera-eyaml backend for Hiera'
|
|
10
|
+
gem.authors = ['IAS Network']
|
|
11
|
+
gem.license = 'MIT'
|
|
12
|
+
gem.homepage = 'https://github.com/theias/hiera-eyaml-age'
|
|
13
|
+
gem.metadata = {
|
|
14
|
+
'source_code_uri' => 'https://github.com/theias/hiera-eyaml-age',
|
|
15
|
+
'changelog_uri' => 'https://github.com/theias/hiera-eyaml-age/blob/main/CHANGELOG.md',
|
|
16
|
+
'bug_tracker_uri' => 'https://github.com/theias/hiera-eyaml-age/issues',
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
|
20
|
+
gem.require_paths = ['lib']
|
|
21
|
+
|
|
22
|
+
gem.required_ruby_version = '>= 3.0'
|
|
23
|
+
gem.add_dependency('hiera-eyaml', '~> 5.0')
|
|
24
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require "open3"
|
|
2
|
+
require "hiera/backend/eyaml/encryptor"
|
|
3
|
+
require "hiera/backend/eyaml/utils"
|
|
4
|
+
require "hiera/backend/eyaml/options"
|
|
5
|
+
require "hiera/backend/eyaml/encryptors/age/version"
|
|
6
|
+
|
|
7
|
+
class Hiera
|
|
8
|
+
module Backend
|
|
9
|
+
module Eyaml
|
|
10
|
+
module Encryptors
|
|
11
|
+
class Age < Encryptor
|
|
12
|
+
VERSION = Hiera::Backend::Eyaml::Encryptors::AgeVersion::VERSION
|
|
13
|
+
self.tag = "AGE"
|
|
14
|
+
|
|
15
|
+
self.options = {
|
|
16
|
+
age_binary_path: {
|
|
17
|
+
desc: "Full path to the age executable",
|
|
18
|
+
type: :string,
|
|
19
|
+
default: "age"
|
|
20
|
+
},
|
|
21
|
+
identity_file: {
|
|
22
|
+
desc: "Path to age identity file for decryption",
|
|
23
|
+
type: :string
|
|
24
|
+
},
|
|
25
|
+
recipients: {
|
|
26
|
+
desc: "List of recipients (comma separated)",
|
|
27
|
+
type: :string
|
|
28
|
+
},
|
|
29
|
+
recipients_file: {
|
|
30
|
+
desc: "File containing a list of recipients (one on each line)",
|
|
31
|
+
type: :string
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
def self.encrypt(plaintext)
|
|
36
|
+
recipients = determine_recipients
|
|
37
|
+
debug("Recipients are #{recipients}")
|
|
38
|
+
|
|
39
|
+
if recipients.empty?
|
|
40
|
+
raise RecoverableError,
|
|
41
|
+
"No recipients provided, don't know who to encrypt to"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
recipient_args =
|
|
45
|
+
recipients.flat_map { |recipient| ["-r", recipient] }
|
|
46
|
+
|
|
47
|
+
stdout, stderr, status =
|
|
48
|
+
Open3.capture3(
|
|
49
|
+
option(:age_binary_path),
|
|
50
|
+
"--encrypt",
|
|
51
|
+
*recipient_args,
|
|
52
|
+
stdin_data: plaintext,
|
|
53
|
+
binmode: true
|
|
54
|
+
)
|
|
55
|
+
unless status.success?
|
|
56
|
+
raise RecoverableError, "age encrypt failed: #{stderr.strip}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
stdout
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
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"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
stdout, stderr, status =
|
|
75
|
+
Open3.capture3(
|
|
76
|
+
option(:age_binary_path),
|
|
77
|
+
"--decrypt",
|
|
78
|
+
"--identity",
|
|
79
|
+
identity_file,
|
|
80
|
+
stdin_data: ciphertext,
|
|
81
|
+
binmode: true
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
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}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
stdout
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def self.create_keys
|
|
95
|
+
warn "The age encryptor does not support creation of keys, use the age command line tools instead"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
class << self
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def determine_recipients
|
|
102
|
+
recipient_option = option :recipients
|
|
103
|
+
|
|
104
|
+
unless recipient_option.nil?
|
|
105
|
+
debug("Using --recipients option")
|
|
106
|
+
return recipient_option.split(",").map(&:strip)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
recipients_file_option = option :recipients_file
|
|
110
|
+
return [] if recipients_file_option.nil?
|
|
111
|
+
|
|
112
|
+
debug("Using --recipients-file option")
|
|
113
|
+
File
|
|
114
|
+
.readlines(recipients_file_option)
|
|
115
|
+
.map do |line|
|
|
116
|
+
line.strip unless line.start_with?("#") || line.strip.empty?
|
|
117
|
+
end
|
|
118
|
+
.compact
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: hiera-eyaml-age
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- IAS Network
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: hiera-eyaml
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '5.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '5.0'
|
|
26
|
+
description: age encryptor for use with hiera-eyaml
|
|
27
|
+
executables: []
|
|
28
|
+
extensions: []
|
|
29
|
+
extra_rdoc_files: []
|
|
30
|
+
files:
|
|
31
|
+
- ".gitignore"
|
|
32
|
+
- ".rubocop.yml"
|
|
33
|
+
- Gemfile
|
|
34
|
+
- Gemfile.lock
|
|
35
|
+
- README.md
|
|
36
|
+
- Rakefile
|
|
37
|
+
- hiera-eyaml-age.gemspec
|
|
38
|
+
- lib/hiera/backend/eyaml/encryptors/age.rb
|
|
39
|
+
- lib/hiera/backend/eyaml/encryptors/age/eyaml_init.rb
|
|
40
|
+
- lib/hiera/backend/eyaml/encryptors/age/version.rb
|
|
41
|
+
homepage: https://github.com/theias/hiera-eyaml-age
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata:
|
|
45
|
+
source_code_uri: https://github.com/theias/hiera-eyaml-age
|
|
46
|
+
changelog_uri: https://github.com/theias/hiera-eyaml-age/blob/main/CHANGELOG.md
|
|
47
|
+
bug_tracker_uri: https://github.com/theias/hiera-eyaml-age/issues
|
|
48
|
+
rdoc_options: []
|
|
49
|
+
require_paths:
|
|
50
|
+
- lib
|
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '3.0'
|
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
requirements: []
|
|
62
|
+
rubygems_version: 3.6.7
|
|
63
|
+
specification_version: 4
|
|
64
|
+
summary: Encryption plugin for hiera-eyaml backend for Hiera
|
|
65
|
+
test_files: []
|