kubekrypt 2.1.0 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aafcb114c98241aef71fcd5bb8cc2da885720fe50ef89d6986595a86108e6066
4
- data.tar.gz: 5b4acdd48ddbf46aad74fa089c7c5de1a1d219c924836a9edf4ab528d38c389d
3
+ metadata.gz: 0fc12e50c4083f740004c80424c20d28abbdf9254be9e2c81752fa53c5b2ee9d
4
+ data.tar.gz: 1c72fef635ece42c16605893d8580234ff0efb63e147bd99ab6e9d08ee6b52a7
5
5
  SHA512:
6
- metadata.gz: 5b093a42bfaae3bf5dc63956c38c4ad454c87a5c91d56be298550a7c8bfc11ce9ff6403da1c8a6eddafcc415e1791a0889f8cb3c02c60faa7a76cf4dfdf936cd
7
- data.tar.gz: 145e1b546e18b9540273025e809f70fac4051c0b21a2d7d7e9739dbec7fed9bfa434812e6cfc340e33f1aff7ce972f41796c8c8aceff5575817a376102b5364e
6
+ metadata.gz: a4cf83f02bda125ed63c86ef872b023aac37393b1523bda8c583e60eef46e48c0e9e85fecfc0b4625158746a5cc9e643544e2d1f8a176fa6adad28e4f122c9ec
7
+ data.tar.gz: 46ec255f4439a16e280f2cc666d16be278e463ea108cd8cfd3d8dedc7b1e73b0bc2917ba9f816d3d6ae64ab1dcf6e306fad6ca8686e7390a466293db424c0ffe
@@ -0,0 +1,13 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 10
8
+
9
+ - package-ecosystem: github-actions
10
+ directory: "/"
11
+ schedule:
12
+ interval: weekly
13
+ open-pull-requests-limit: 5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.2.0] - 2026-03-24
4
+
5
+ ### Added
6
+ - `--in-place` / `-i` flag for `encrypt` and `decrypt` to write output back to the source file
7
+ - Directory support — pass a directory path to process all `*.yaml`/`*.yml` files recursively
8
+ - `kind: Secret` validation — non-Secret manifests are rejected with a clear error
9
+ - YAML parse error handling — invalid YAML prints a clean error instead of a backtrace
10
+ - Dependabot configuration for automated dependency updates
11
+
12
+ ## [2.1.1] - 2026-03-24
13
+
14
+ ### Fixed
15
+ - Typos in error class names (`AlreadyEncryptedError`, `NotEncryptedError`)
16
+ - CLI now prints clean error messages instead of backtraces on failure
17
+ - Use `METADATA_KEY` constant consistently in CLI
18
+
3
19
  ## [2.1.0] - 2026-03-24
4
20
 
5
21
  ### Changed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kubekrypt (2.1.0)
4
+ kubekrypt (2.2.0)
5
5
  google-cloud-kms
6
6
  grpc (< 1.74.0)
7
7
  thor (>= 1.0)
data/README.md CHANGED
@@ -1,86 +1,136 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/kubekrypt.svg)](https://rubygems.org/gems/kubekrypt)
2
+ [![Ruby CI](https://github.com/knapo/kubekrypt/actions/workflows/ci.yml/badge.svg)](https://github.com/knapo/kubekrypt/actions/workflows/ci.yml)
2
3
 
3
4
  # KubeKrypt
4
5
 
5
- A command-line tool for securely encrypting and decrypting Kubernetes Secret manifests using Google Cloud KMS encryption keys.
6
+ A command-line tool for encrypting and decrypting Kubernetes Secret manifests using Google Cloud KMS.
6
7
 
7
- ## Overview
8
+ Secret manifests can be safely committed to version control in their encrypted form and decrypted on demand — either to inspect values or to pipe directly into `kubectl`.
8
9
 
9
- KubeKrypt provides a simple and secure way to manage sensitive information in Kubernetes Secret manifests. It allows you to encrypt Secret manifests before they're stored in version control systems, and decrypt them when they need to be applied to a cluster.
10
+ ## Installation
10
11
 
11
- ## Features
12
+ ```bash
13
+ gem install kubekrypt
14
+ ```
12
15
 
13
- - **Secure Encryption**: Uses Google Cloud KMS to encrypt sensitive data in Kubernetes Secret manifests
14
- - **Simple Interface**: Easy-to-use CLI commands for encryption and decryption
15
- - **Metadata Tracking**: Embeds metadata in encrypted files for tracking and verification
16
- - **Stdout Integration**: Outputs to standard out for easy piping and redirection
17
- - **Base64 Processing**: Automatically handles base64 encoding/decoding under the hood, maintaining compatibility with Kubernetes Secret format
16
+ Or add it to your `Gemfile`:
18
17
 
19
- ## Installation
18
+ ```ruby
19
+ gem "kubekrypt"
20
+ ```
21
+
22
+ ## Requirements
23
+
24
+ - Ruby >= 3.4
25
+ - A Google Cloud KMS key with `cloudkms.cryptoKeyVersions.useToEncrypt` / `useToDecrypt` permissions
26
+
27
+ ## Authentication
20
28
 
21
- `kubecrypt` uses `google-cloud-kms` and it requires an [environment variable](https://cloud.google.com/ruby/docs/reference/google-cloud-kms/latest/AUTHENTICATION) to be set in order to authenticate and work properly.
22
- You need one of:
29
+ KubeKrypt delegates authentication to the `google-cloud-kms` gem. Set one of the following environment variables:
23
30
 
24
- - `GOOGLE_CLOUD_CREDENTIALS` - Path to JSON file, or JSON contents
25
- - `GOOGLE_APPLICATION_CREDENTIALS` - Path to JSON file
31
+ | Variable | Description |
32
+ |---|---|
33
+ | `GOOGLE_APPLICATION_CREDENTIALS` | Path to a service account JSON key file |
34
+ | `GOOGLE_CLOUD_CREDENTIALS` | Path to JSON file, or JSON contents inline |
35
+
36
+ Application Default Credentials (e.g. `gcloud auth application-default login`) are also supported.
26
37
 
27
38
  ## Usage
28
39
 
29
- ### Encrypting a Secret
40
+ ### Encrypt a Secret
41
+
42
+ ```bash
43
+ kubekrypt encrypt secret.yaml \
44
+ -k projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key \
45
+ > secret.enc.yaml
46
+ ```
47
+
48
+ Overwrite the file in place with `--in-place` / `-i`:
30
49
 
31
50
  ```bash
32
- kubekrypt encrypt secret.yaml -k projects/your-project/locations/global/keyRings/your-keyring/cryptoKeys/your-key > secret.enc.yaml
51
+ kubekrypt encrypt -i secret.yaml -k projects/my-project/...
33
52
  ```
34
53
 
35
- ### Decrypting a Secret
54
+ Encrypt every Secret in a directory:
55
+
56
+ ```bash
57
+ kubekrypt encrypt secrets/ -k projects/my-project/...
58
+ ```
59
+
60
+ Each value under `data` is encrypted individually using KMS and prefixed with `enc:`. A `kubekrypt` metadata block is embedded in the output to record the KMS key used and the version:
61
+
62
+ ```yaml
63
+ apiVersion: v1
64
+ kind: Secret
65
+ metadata:
66
+ name: my-secret
67
+ data:
68
+ token: enc:CiQAjMDkZ3...
69
+ kubekrypt:
70
+ kms_key: projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key
71
+ version: 2.1.1
72
+ modified_at: "2026-03-24T10:00:00Z"
73
+ ```
74
+
75
+ ### Decrypt a Secret
36
76
 
37
77
  ```bash
38
78
  kubekrypt decrypt secret.enc.yaml > secret.yaml
39
79
  ```
40
80
 
41
- ### Piping to kubectl
81
+ Or in place:
82
+
83
+ ```bash
84
+ kubekrypt decrypt -i secret.enc.yaml
85
+ ```
86
+
87
+ Decrypt every Secret in a directory:
88
+
89
+ ```bash
90
+ kubekrypt decrypt -i secrets/
91
+ ```
92
+
93
+ The KMS key is read from the embedded `kubekrypt` metadata — no need to specify it again.
94
+
95
+ ### Decrypt and apply directly with kubectl
96
+
97
+ Kubernetes Secret `data` values must be base64-encoded. Use `--base64` to have KubeKrypt re-encode the decrypted values before output:
42
98
 
43
99
  ```bash
44
100
  kubekrypt decrypt --base64 secret.enc.yaml | kubectl apply -f -
45
101
  ```
46
102
 
47
- ### Checking Version
103
+ ### Check version
48
104
 
49
105
  ```bash
50
106
  kubekrypt version
51
107
  ```
52
108
 
53
- ## How It Works
109
+ ## How it works
54
110
 
55
- 1. KubeKrypt reads your Kubernetes Secret YAML file
56
- 2. For encryption, it:
57
- - Validates that it's a proper Kubernetes Secret
58
- - Ensures it's not already encrypted
59
- - Decodes base64 values to get raw data
60
- - Uses Google Cloud KMS to encrypt sensitive data
61
- - Re-encodes with base64 as needed
62
- - Adds metadata about the encryption
63
- - Outputs the encrypted YAML
111
+ **Encryption:**
64
112
 
65
- 3. For decryption, it:
66
- - Verifies the file contains KubeKrypt encryption metadata
67
- - Uses the embedded information to decrypt the data
68
- - Handles all necessary base64 encoding/decoding
69
- - Outputs the original Secret YAML
113
+ 1. Reads the YAML file and validates it is not already encrypted.
114
+ 2. Calls Google Cloud KMS to encrypt each value in the `data` map.
115
+ 3. Stores ciphertext as `enc:<base64>` in place of the original value.
116
+ 4. Appends a `kubekrypt` metadata block with the KMS key name, gem version, and timestamp.
117
+ 5. Prints the resulting YAML to stdout.
70
118
 
71
- ## Security
119
+ **Decryption:**
72
120
 
73
- KubeKrypt never stores encryption keys locally. All encryption and decryption operations are performed using Google Cloud KMS, ensuring that key material is never exposed.
121
+ 1. Reads the `kubekrypt` metadata block to determine which KMS key to use.
122
+ 2. Calls Google Cloud KMS to decrypt each `enc:<base64>` value.
123
+ 3. Strips the `kubekrypt` metadata block from the output.
124
+ 4. Prints the resulting YAML to stdout (optionally with base64-encoded values via `--base64`).
74
125
 
75
- ## Requirements
126
+ ## Security
76
127
 
77
- - Ruby 3.4+
78
- - Access to a KMS key with appropriate permissions
128
+ KubeKrypt never stores or logs key material. All cryptographic operations are performed by Google Cloud KMS — plaintext values exist only transiently in memory during a command invocation.
79
129
 
80
130
  ## Contributing
81
131
 
82
- Contributions are welcome! Please feel free to submit a Pull Request.
132
+ Pull requests are welcome. Please make sure `bundle exec rake ci` passes before submitting.
83
133
 
84
134
  ## License
85
135
 
86
- This project is licensed under the MIT License - see the LICENSE file for details.
136
+ MIT see [LICENSE](LICENSE) for details.
data/lib/kubekrypt/cli.rb CHANGED
@@ -12,29 +12,85 @@ module KubeKrypt
12
12
  end
13
13
 
14
14
  method_option KMS_KEY, aliases: "-k", desc: "Google KMS encryption key id to use", required: true
15
- desc "encrypt FILE", "Encrypts Kubernetes secrets manifest using the specified KMS key"
16
- def encrypt(file_path)
17
- yaml_content = File.read(file_path)
18
- content = YAML.safe_load(yaml_content)
15
+ method_option :in_place, aliases: "-i", desc: "Write output back to the source file", type: :boolean, default: false
16
+ desc "encrypt FILE [FILE ...]", "Encrypts Kubernetes Secret manifests using the specified KMS key"
17
+ def encrypt(*paths)
19
18
  key_name = options.fetch(KMS_KEY)
19
+ in_place = options[:in_place]
20
20
 
21
- raise AlreadyEncrytpedError, "#{file_path} is already encrypted" if content["kubekrypt"]
22
-
23
- result = KubeKrypt::Encryptor.call(content:, key_name:)
24
- puts result
21
+ expand(paths).each { |file_path| process_encrypt(file_path, key_name:, in_place:) }
25
22
  end
26
23
 
27
24
  method_option :base64, desc: "Base64 encoded values", type: :boolean, required: false
28
- desc "decrypt FILE", "Decrypts Kubernetes secrets manifest using embedded kubekrypt metadata"
29
- def decrypt(file_path)
30
- yaml_content = File.read(file_path)
31
- content = YAML.safe_load(yaml_content)
25
+ method_option :in_place, aliases: "-i", desc: "Write output back to the source file", type: :boolean, default: false
26
+ desc "decrypt FILE [FILE ...]", "Decrypts Kubernetes Secret manifests using embedded kubekrypt metadata"
27
+ def decrypt(*paths)
32
28
  base64 = options.fetch(:base64, false)
29
+ in_place = options[:in_place]
30
+
31
+ expand(paths).each { |file_path| process_decrypt(file_path, base64:, in_place:) }
32
+ end
33
+
34
+ private
35
+
36
+ def expand(paths)
37
+ paths.flat_map do |path|
38
+ if File.directory?(path)
39
+ Dir.glob(File.join(path, "**", "*.{yaml,yml}")).sort
40
+ else
41
+ [path]
42
+ end
43
+ end
44
+ end
45
+
46
+ def load_secret(file_path)
47
+ content = YAML.safe_load_file(file_path)
48
+ raise InvalidSecretError, "#{file_path} is not a Kubernetes Secret" unless content["kind"] == "Secret"
49
+ content
50
+ rescue Psych::Exception => e
51
+ raise InvalidSecretError, "#{file_path} is not valid YAML: #{e.message}"
52
+ end
53
+
54
+ def write_output(result, file_path:, in_place:)
55
+ if in_place
56
+ File.write(file_path, result)
57
+ else
58
+ puts result
59
+ end
60
+ end
61
+
62
+ def process_encrypt(file_path, key_name:, in_place:)
63
+ content = load_secret(file_path)
64
+ raise AlreadyEncryptedError, "#{file_path} is already encrypted" if content[METADATA_KEY]
65
+
66
+ result = KubeKrypt::Encryptor.call(content:, key_name:)
67
+ write_output(result, file_path:, in_place:)
68
+ rescue AlreadyEncryptedError, NotEncryptedError, InvalidSecretError => e
69
+ warn "Error: #{e.message}"
70
+ exit 1
71
+ rescue Errno::ENOENT
72
+ warn "Error: file not found: #{file_path}"
73
+ exit 1
74
+ rescue => e
75
+ warn "Error: #{e.message}"
76
+ exit 1
77
+ end
33
78
 
34
- raise NotEncrytpedError, "#{file_path} is not encrypted" unless content["kubekrypt"]
79
+ def process_decrypt(file_path, base64:, in_place:)
80
+ content = load_secret(file_path)
81
+ raise NotEncryptedError, "#{file_path} is not encrypted" unless content[METADATA_KEY]
35
82
 
36
83
  result = KubeKrypt::Decryptor.call(content:, base64:)
37
- puts result
84
+ write_output(result, file_path:, in_place:)
85
+ rescue AlreadyEncryptedError, NotEncryptedError, InvalidSecretError => e
86
+ warn "Error: #{e.message}"
87
+ exit 1
88
+ rescue Errno::ENOENT
89
+ warn "Error: file not found: #{file_path}"
90
+ exit 1
91
+ rescue => e
92
+ warn "Error: #{e.message}"
93
+ exit 1
38
94
  end
39
95
  end
40
96
  end
@@ -1,3 +1,3 @@
1
1
  module KubeKrypt
2
- VERSION = "2.1.0".freeze
2
+ VERSION = "2.2.0".freeze
3
3
  end
data/lib/kubekrypt.rb CHANGED
@@ -5,8 +5,9 @@ require "thor"
5
5
  require "yaml"
6
6
 
7
7
  module KubeKrypt
8
- AlreadyEncrytpedError = Class.new(StandardError)
9
- NotEncrytpedError = Class.new(StandardError)
8
+ AlreadyEncryptedError = Class.new(StandardError)
9
+ NotEncryptedError = Class.new(StandardError)
10
+ InvalidSecretError = Class.new(StandardError)
10
11
  KMS_KEY = :kms_key
11
12
  ENCRYPTION_METHOD = "aes-256-gcm".freeze
12
13
  METADATA_KEY = "kubekrypt".freeze
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kubekrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Krzysztof Knapik
@@ -72,6 +72,7 @@ executables:
72
72
  extensions: []
73
73
  extra_rdoc_files: []
74
74
  files:
75
+ - ".github/dependabot.yml"
75
76
  - ".github/workflows/ci.yml"
76
77
  - ".gitignore"
77
78
  - ".rspec"