blob: 83689e381a94daec896ae2136e3f636dca97cd21 [file] [log] [blame]
garciadeblas83775ba2025-07-23 18:35:24 +02001#######################################################################################
2# Copyright ETSI Contributors and Others.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#######################################################################################
17
18# Module with custom commands to create and manage age key pairs for SOPS encryption/decryption of Kubernetes secrets.
19
20
21# Create a new age key pair
22export def "create age" [
23 age_key_name: string,
24 credentials_dir?: path # Optional, defaults to $env.CREDENTIALS_DIR
25] {
26 let dir: path = if $credentials_dir == null { $env.CREDENTIALS_DIR } else { $credentials_dir }
27 let key_path: path = ({ parent: $dir, stem: $age_key_name, extension: "key"} | path join)
28 let pub_path: path = ({ parent: $dir, stem: $age_key_name, extension: "pub"} | path join)
29
30 # Delete existing keys
31 rm -f $key_path $pub_path
32
33 # Generate private key
34 ^age-keygen -o $key_path
35
36 # Extract public key
37 ^age-keygen -y $key_path | save $pub_path
38}
39
40export alias create_age_keypair = create age
41
42
43# In-place encrypt secrets in manifest
44# -- NOT EXPORTED --
45def "encrypt secret inplace" [
46 file: path,
47 public_key: string
48]: [
49 nothing -> nothing
50] {
51 ^sops --age $public_key --encrypt --encrypted-regex '^(data|stringData)$' --in-place $file
52}
53
54export alias encrypt_secret_inplace = encrypt secret inplace
55
56
57# Encrypt with SOPS a manifest of Kubernetes secret received from stdin
58export def "encrypt secret manifest" [public_key: string]: [
59 string -> string
60] {
61 # Saves the input to preserve it from multiple invokes
62 let manifest: string = $in
63
64 # If the input empty, just returns an empty string
65 if $manifest == "" {
66 return ""
67 }
68
69 let tmp_file = (mktemp -t --suffix .yaml)
70 $manifest | save -f $tmp_file
71
72 ^sops --age $public_key --encrypt --encrypted-regex '^(data|stringData)$' --in-place $tmp_file
73
74 let content: string = (open $tmp_file | to yaml)
75 rm -f $tmp_file
76 $content
77}
78
79export alias encrypt_secret_from_stdin = encrypt secret manifest
80
81
82# Decrypt with SOPS a manifest of a Kubernetes secret received from stdin
83export def "decrypt secret manifest" [private_key: string]: [
84 string -> string
85] {
86 # Saves the input to preserve it from multiple invokes
87 let encrypted_manifest: string = $in
88
89 # If the input empty, just returns an empty string
90 if $encrypted_manifest == "" {
91 return ""
92 }
93
94 # Decrypt using temporary file
95 let tmp_encrypted_file = (mktemp -t --suffix .yaml)
96 $encrypted_manifest | save -f $tmp_encrypted_file
97 let decrypted_manifest: string = (
98 $private_key
99 | SOPS_AGE_KEY_FILE="/dev/stdin" sops --decrypt $tmp_encrypted_file
100 )
101 rm $tmp_encrypted_file # Clean up temporary key file
102
103 # Returns the decrypted secret
104 $decrypted_manifest
105}