This repository has been archived by the owner on May 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
patch_secrets.go
127 lines (115 loc) · 4.51 KB
/
patch_secrets.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package qust
import (
"encoding/base64"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/qlik-oss/k-apis/pkg/config"
"gopkg.in/yaml.v2"
"sigs.k8s.io/kustomize/api/types"
)
const serviceSecretKustomizationFileYaml = `apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- selectivepatch.yaml
transformers:
- ../gomplate.yaml
`
const patchedSecretsGomplateFileYaml = `apiVersion: qlik.com/v1
kind: Gomplate
metadata:
name: patched-secrets-gomplate
labels:
key: gomplate
dataSource:
ejson:
filePath: edata.json
`
func ProcessSecrets(cr *config.CRSpec, ejsonPublicKey string) error {
baseSecretDir := filepath.Join(cr.GetManifestsRoot(), operatorPatchBaseFolder, "secrets")
if _, err := os.Stat(baseSecretDir); os.IsNotExist(err) {
return fmt.Errorf("%v does not exist", baseSecretDir)
} else if err := ioutil.WriteFile(filepath.Join(baseSecretDir, "gomplate.yaml"), []byte(patchedSecretsGomplateFileYaml), os.ModePerm); err != nil {
return errors.Wrapf(err, "error writing out the secrets' gomplate.yaml file: %v", filepath.Join(baseSecretDir, "gomplate.yaml"))
} else if pm, err := createSupperSecretSelectivePatch(cr.Secrets); err != nil {
return errors.Wrap(err, "error creating the selective patches map")
} else {
for svc, sps := range pm {
dir := filepath.Join(baseSecretDir, svc)
if err := addResourceToKustomization(svc, filepath.Join(baseSecretDir, "kustomization.yaml")); err != nil {
return errors.Wrapf(err, "error adding resource: %v to kustomization file: %v", svc, filepath.Join(baseSecretDir, "kustomization.yaml"))
} else if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return errors.Wrapf(err, "error creating directory: %v", dir)
} else if err := ioutil.WriteFile(filepath.Join(dir, "kustomization.yaml"), []byte(serviceSecretKustomizationFileYaml), os.ModePerm); err != nil {
return errors.Wrapf(err, "error writing out service secret kustomization.yaml file: %v", filepath.Join(dir, "kustomization.yaml"))
} else if err := writeSelectivePatchFile(dir, sps); err != nil {
return errors.Wrap(err, "error writing out secret selective patch")
} else if err := writeEjsonFile(dir, cr.Secrets[svc], ejsonPublicKey); err != nil {
return errors.Wrap(err, "error writing out secret selective patch")
}
}
}
return nil
}
func writeEjsonFile(dir string, secrets config.NameValues, ejsonPublicKey string) error {
if ejsonPublicKey == "" {
return nil
}
ejsonDataMap := make(map[string]string)
ejsonDataMap["_public_key"] = ejsonPublicKey
for _, secret := range secrets {
ejsonDataMap[secret.Name] = base64.StdEncoding.EncodeToString([]byte(secret.GetSecretValue()))
}
return writeToEjsonFile(ejsonDataMap, filepath.Join(dir, "edata.json"))
}
func writeSelectivePatchFile(dir string, sps *config.SelectivePatch) error {
if selectivePatchData, err := yaml.Marshal(sps); err != nil {
return err
} else {
return ioutil.WriteFile(filepath.Join(dir, "selectivepatch.yaml"), selectivePatchData, os.ModePerm)
}
}
// create a selectivepatch map for each service for a secretKey
func createSupperSecretSelectivePatch(sec map[string]config.NameValues) (map[string]*config.SelectivePatch, error) {
spMap := make(map[string]*config.SelectivePatch)
for svc, data := range sec {
spMap[svc] = getSuperSecretSPTemplate(svc)
for _, conf := range data {
sp := getSuperSecretSPTemplate(svc)
sp.Patches = []types.Patch{getSecretPatchBody(svc, conf)}
if _, err := mergeSelectivePatches(spMap[svc], sp); err != nil {
return nil, err
}
}
}
return spMap, nil
}
// create a patch section to be added to the selective patch
func getSecretPatchBody(svc string, nv config.NameValue) types.Patch {
ph := getSuperSecretTemplate(svc)
ph.StringData = map[string]string{
nv.Name: fmt.Sprintf(`((- "\n"))(( index (ds "data") "%s" | base64.Decode | indent 8 ))`, nv.Name) + "\n",
}
phb, _ := yaml.Marshal(ph)
p1 := types.Patch{
Patch: strings.Replace(string(phb), ": |", ": |-", -1), // when load again the |- will disappaer and the value will be on one line
Target: getSelector("SuperSecret", svc),
}
return p1
}
// a SelectivePatch object with service name in it
func getSuperSecretSPTemplate(svc string) *config.SelectivePatch {
return getSelectivePatchTemplate(svc + "-generated-operator-secrets")
}
func getSuperSecretTemplate(svc string) *config.SupperSecret {
return &config.SupperSecret{
ApiVersion: "qlik.com/v1",
Kind: "SuperSecret",
Metadata: map[string]string{
"name": svc + "-secrets",
},
}
}