Skip to content

Commit

Permalink
feat: added binaryFiles option (#211)
Browse files Browse the repository at this point in the history
* feat: added binaryFiles option

* test: added legacy test

* docs: updated README's with binaryFiles example

* chore: remove modification from legacy README

* style: add sections for different file types

* chore: remove modification from legacy README

---------

Co-authored-by: Devin Stein <devstein@seas.upenn.edu>
Co-authored-by: Devin Stein <devstein@alumni.upenn.edu>
  • Loading branch information
3 people committed Oct 31, 2023
1 parent 9895763 commit 980b683
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 7 deletions.
32 changes: 30 additions & 2 deletions README.md
Expand Up @@ -199,8 +199,9 @@ https://github.com/viaduct-ai/kustomize-sops/issues

`KSOPS` can also generate a Kubernetes Secret directly from encrypted files or dotenv files.

#### Create a Kubernetes Secret from encrypted text-based file

```bash
# Create a Kubernetes Secret from encrypted file
cat <<EOF > secret-generator.yaml
apiVersion: viaduct.ai/v1
kind: ksops
Expand All @@ -224,8 +225,35 @@ secretFrom:
EOF
```

#### Create a Kubernetes Secret from encrypted binary file

```bash
cat <<EOF > secret-generator.yaml
apiVersion: viaduct.ai/v1
kind: ksops
metadata:
name: example-secret-generator
annotations:
config.kubernetes.io/function: |
exec:
path: ksops
secretFrom:
- metadata:
name: secret-name
labels:
app: foo
annotations:
kustomize.config.k8s.io/needs-hash: "false"
type: Opaque
binaryFiles:
- ./secret.enc
- secret=./secret.enc
EOF
```

#### Create a Kubernetes Secret from an encrypted dotenv file

```bash
# Create a Kubernetes Secret from encrypted dotenv file
cat <<EOF > secret-generator.yaml
apiVersion: viaduct.ai/v1
kind: ksops
Expand Down
25 changes: 20 additions & 5 deletions ksops.go
Expand Up @@ -10,6 +10,7 @@ package main

import (
"bytes"
"encoding/base64"
"fmt"
"io/ioutil"
"os"
Expand All @@ -29,14 +30,16 @@ type kubernetesSecret struct {
Kind string `json:"kind" yaml:"kind"`
Metadata types.ObjectMeta `json:"metadata" yaml:"metadata"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
StringData map[string]string `json:"stringData" yaml:"stringData"`
StringData map[string]string `json:"stringData,omitempty" yaml:"stringData,omitempty"`
Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"`
}

type secretFrom struct {
Files []string `json:"files,omitempty" yaml:"files,omitempty"`
Envs []string `json:"envs,omitempty" yaml:"envs,omitempty"`
Metadata types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
Files []string `json:"files,omitempty" yaml:"files,omitempty"`
BinaryFiles []string `json:"binaryFiles,omitempty" yaml:"binaryFiles,omitempty"`
Envs []string `json:"envs,omitempty" yaml:"envs,omitempty"`
Metadata types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Type string `json:"type,omitempty" yaml:"type,omitempty"`
}

type ksops struct {
Expand Down Expand Up @@ -157,6 +160,7 @@ func generate(raw []byte) (string, error) {

for i, secretFrom := range manifest.SecretFrom {
stringData := make(map[string]string)
binaryData := make(map[string]string)

for _, file := range secretFrom.Files {
key, path := fileKeyPath(file)
Expand All @@ -168,6 +172,16 @@ func generate(raw []byte) (string, error) {
stringData[key] = string(data)
}

for _, file := range secretFrom.BinaryFiles {
key, path := fileKeyPath(file)
data, err := decryptFile(path)
if err != nil {
return "", fmt.Errorf("error decrypting file %q from secretFrom.Files: %w", path, err)
}

binaryData[key] = base64.StdEncoding.EncodeToString(data)
}

for _, file := range secretFrom.Envs {
data, err := decryptFile(file)
if err != nil {
Expand All @@ -189,6 +203,7 @@ func generate(raw []byte) (string, error) {
Metadata: secretFrom.Metadata,
Type: secretFrom.Type,
StringData: stringData,
Data: binaryData,
}
d, err := yaml.Marshal(&s)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions ksops_test.go
Expand Up @@ -63,6 +63,10 @@ func TestKSOPSPluginInstallation(t *testing.T) {
name: "Legacy From File",
dir: "test/legacy/file",
},
{
name: "Legacy From Binary File",
dir: "test/legacy/binaryfile",
},
{
name: "Legacy From Envs",
dir: "test/legacy/envs",
Expand Down Expand Up @@ -95,6 +99,10 @@ func TestKSOPSPluginInstallation(t *testing.T) {
name: "KRM From File",
dir: "test/krm/file",
},
{
name: "KRM From Binary File",
dir: "test/krm/binaryfile",
},
{
name: "KRM From Envs",
dir: "test/krm/envs",
Expand Down
17 changes: 17 additions & 0 deletions test/krm/binaryfile/generate-resources.yaml
@@ -0,0 +1,17 @@
apiVersion: viaduct.ai/v1
kind: ksops
metadata:
name: ksops-secret-from-generator
annotations:
config.kubernetes.io/function: |
exec:
# if the binary is your PATH, you can do
path: ksops
# otherwise, path should be relative to manifest files, like
# path: ../../../ksops
secretFrom:
- metadata:
name: mysecret
type: Opaque
binaryFiles:
- ./secret.enc.yaml
2 changes: 2 additions & 0 deletions test/krm/binaryfile/kustomization.yaml
@@ -0,0 +1,2 @@
generators:
- ./generate-resources.yaml
28 changes: 28 additions & 0 deletions test/krm/binaryfile/secret.enc.yaml
@@ -0,0 +1,28 @@
username: ENC[AES256_GCM,data:wm8jYTk=,iv:uODPx9IQmb2gQi2oZ6gpmIGddMN7n2ogKdweMjIZIHw=,tag:xnfYKwnirnOV3tV7CFvlvA==,type:str]
password: ENC[AES256_GCM,data:Lpu0v6Qjt6wLmYZv,iv:P7kfBIuJ7M86Oh43q9FpUDgUCK4REColGTTFGFdhjD0=,tag:wSNv3kOLhdNxBK0r3MNLpw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age: []
lastmodified: "2022-12-14T18:15:56Z"
mac: ENC[AES256_GCM,data:mJUZQ0L26QeAkip3WnGxE/p3JAfgLbF5F2MXElcQRLvKberT0cF6MiOXXXCXFyc1/G/HMYVFGMevEuqFEMwAzZCp4oa70KclZTnE3r8/7lmtvNsF+YbLvRRy5Ib5pwpVYBSFp3RNeRHXmw+lUjz2q61DBK40tyHbRrbXvq0ITy4=,iv:shT/5S+8sjj3gdVSYTNX1r0y0db3rNiQ3YIjIP/0BUM=,tag:VPXX7gTNpsnQDe2U++hexA==,type:str]
pgp:
- created_at: "2022-12-14T18:15:50Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQEMAyUpShfNkFB/AQf/eWYqsnyMtmf1DpllbYFgViTaxTfZNbS+qF9BJeGoL/Q4
etjpXqqkl61RBzuLxj7KlM00fFpXCwTLnhaUzGIPaAvojHhk3xIT3lBBci3tshlP
qZ8PVzKIhVfBT8zoZ5hhR5mH7iT0SwZaD6RLepe1ygwXcS33WSf7srvuIydeAaTE
nxOcszcw+1/gZ88rcqmNQ8EnD4gZeswOLQiLOCliHAmZBaW3yybwp3GWbbqiJLYl
RsKCOkIfX0gQVI+BXb8wB1FukXl3ZiefO0zDoTZzV/hP8tq2MEhYyMMb/w/5qJo5
O49kCAo0nItiTFzMI1jKH3GdO9HSdAEvm4RZPGQSEdJeAWyJxw8Hy9HaecQchwCh
PU5nil4v656adnP+gAcmnUvjvq3WQESNkSYqGttXsxCN+0REP0mR2OuaK1LQJkY4
zr6Ky43znNJ33mgVYF1NKKJN00Ip8GF4l/Km24FnvQ==
=4non
-----END PGP MESSAGE-----
fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
unencrypted_regex: ^(apiVersion|metadata|kind|type)$
version: 3.7.2
7 changes: 7 additions & 0 deletions test/krm/binaryfile/want.yaml
@@ -0,0 +1,7 @@
apiVersion: v1
data:
secret.enc.yaml: dXNlcm5hbWU6IGFkbWluCnBhc3N3b3JkOiAxZjJkMWUyZTY3ZGYK
kind: Secret
metadata:
name: mysecret
type: Opaque
10 changes: 10 additions & 0 deletions test/legacy/binaryfile/generate-resources.yaml
@@ -0,0 +1,10 @@
apiVersion: viaduct.ai/v1
kind: ksops
metadata:
name: ksops-secret-from-generator
secretFrom:
- metadata:
name: mysecret
type: Opaque
binaryFiles:
- ./secret.enc.yaml
2 changes: 2 additions & 0 deletions test/legacy/binaryfile/kustomization.yaml
@@ -0,0 +1,2 @@
generators:
- ./generate-resources.yaml
28 changes: 28 additions & 0 deletions test/legacy/binaryfile/secret.enc.yaml
@@ -0,0 +1,28 @@
username: ENC[AES256_GCM,data:wm8jYTk=,iv:uODPx9IQmb2gQi2oZ6gpmIGddMN7n2ogKdweMjIZIHw=,tag:xnfYKwnirnOV3tV7CFvlvA==,type:str]
password: ENC[AES256_GCM,data:Lpu0v6Qjt6wLmYZv,iv:P7kfBIuJ7M86Oh43q9FpUDgUCK4REColGTTFGFdhjD0=,tag:wSNv3kOLhdNxBK0r3MNLpw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age: []
lastmodified: "2022-12-14T18:15:56Z"
mac: ENC[AES256_GCM,data:mJUZQ0L26QeAkip3WnGxE/p3JAfgLbF5F2MXElcQRLvKberT0cF6MiOXXXCXFyc1/G/HMYVFGMevEuqFEMwAzZCp4oa70KclZTnE3r8/7lmtvNsF+YbLvRRy5Ib5pwpVYBSFp3RNeRHXmw+lUjz2q61DBK40tyHbRrbXvq0ITy4=,iv:shT/5S+8sjj3gdVSYTNX1r0y0db3rNiQ3YIjIP/0BUM=,tag:VPXX7gTNpsnQDe2U++hexA==,type:str]
pgp:
- created_at: "2022-12-14T18:15:50Z"
enc: |
-----BEGIN PGP MESSAGE-----
hQEMAyUpShfNkFB/AQf/eWYqsnyMtmf1DpllbYFgViTaxTfZNbS+qF9BJeGoL/Q4
etjpXqqkl61RBzuLxj7KlM00fFpXCwTLnhaUzGIPaAvojHhk3xIT3lBBci3tshlP
qZ8PVzKIhVfBT8zoZ5hhR5mH7iT0SwZaD6RLepe1ygwXcS33WSf7srvuIydeAaTE
nxOcszcw+1/gZ88rcqmNQ8EnD4gZeswOLQiLOCliHAmZBaW3yybwp3GWbbqiJLYl
RsKCOkIfX0gQVI+BXb8wB1FukXl3ZiefO0zDoTZzV/hP8tq2MEhYyMMb/w/5qJo5
O49kCAo0nItiTFzMI1jKH3GdO9HSdAEvm4RZPGQSEdJeAWyJxw8Hy9HaecQchwCh
PU5nil4v656adnP+gAcmnUvjvq3WQESNkSYqGttXsxCN+0REP0mR2OuaK1LQJkY4
zr6Ky43znNJ33mgVYF1NKKJN00Ip8GF4l/Km24FnvQ==
=4non
-----END PGP MESSAGE-----
fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4
unencrypted_regex: ^(apiVersion|metadata|kind|type)$
version: 3.7.2
7 changes: 7 additions & 0 deletions test/legacy/binaryfile/want.yaml
@@ -0,0 +1,7 @@
apiVersion: v1
data:
secret.enc.yaml: dXNlcm5hbWU6IGFkbWluCnBhc3N3b3JkOiAxZjJkMWUyZTY3ZGYK
kind: Secret
metadata:
name: mysecret
type: Opaque

0 comments on commit 980b683

Please sign in to comment.