-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathsecret.go
More file actions
127 lines (110 loc) · 3.37 KB
/
secret.go
File metadata and controls
127 lines (110 loc) · 3.37 KB
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 common
import (
"context"
"fmt"
"github.com/awnumar/memguard"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
type LockedBufferSecret struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
LockedData SecretMap `json:"lockedData,omitempty"`
}
type SecretMap map[string]*memguard.LockedBuffer
func (sm SecretMap) Destroy() {
for _, buffer := range sm {
buffer.Destroy()
}
}
func (sm SecretMap) Get(key string) ([]byte, bool) {
if buffer, found := sm[key]; found {
return buffer.Bytes(), true
}
return []byte{}, false
}
// SetCopy stores a copy of value in SecretMap at the specified key. The original
// value's memory is securely wiped before the copy is made to prevent data leakage.
func (sm SecretMap) SetCopy(key string, value []byte) {
if buffer, found := sm[key]; found {
buffer.Destroy()
}
valueCopy := make([]byte, len(value))
copy(valueCopy, value)
sm[key] = memguard.NewBufferFromBytes(valueCopy)
}
// Set stores the value in SecretMap at the specified key. The original
// value's memory is securely wiped before the copy is made to prevent data leakage.
func (sm SecretMap) Set(key string, value []byte) {
if buffer, found := sm[key]; found {
buffer.Destroy()
}
sm[key] = memguard.NewBufferFromBytes(value)
}
func (lockedSecret LockedBufferSecret) Destroy() {
if lockedSecret.LockedData != nil {
lockedSecret.LockedData.Destroy()
}
}
// Gets a Secret from the k8s client loaded as a LockedBufferSecret
func GetSecret(client client.Client, name string, ns string) (*LockedBufferSecret, error) {
if client == nil {
return nil, fmt.Errorf("the reconciler client could not be found")
}
secret := &corev1.Secret{}
secret.Name = name
secret.Namespace = ns
lockedSecret := &LockedBufferSecret{}
lockedSecret.Name = secret.Name
lockedSecret.Namespace = secret.Namespace
err := client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: ns}, secret)
if err != nil {
return lockedSecret, err
}
lockedSecret.TypeMeta = secret.TypeMeta
lockedSecret.ObjectMeta = secret.ObjectMeta
if lockedSecret.LockedData == nil {
lockedSecret.LockedData = SecretMap{}
}
if secret.Data != nil {
for secretKey, secretValue := range secret.Data {
lockedSecret.LockedData.Set(secretKey, secretValue)
}
}
return lockedSecret, nil
}
// Copies a Locked Buffer Secret into a core Secret with a corresponding cleanup func
func CopySecret(in *LockedBufferSecret, out *corev1.Secret) func() {
out.TypeMeta = in.TypeMeta
out.ObjectMeta = in.ObjectMeta
out.Data = make(map[string][]byte)
for key, buffer := range in.LockedData {
out.Data[key] = buffer.Bytes()
}
return func() {
if out == nil {
return
}
for key := range out.Data {
delete(out.Data, key)
}
out.Data = nil
}
}
// Returns the client.Get status of Secret name in namespace ns after clearing sensitive byte array content
func CheckSecret(client client.Client, name string, ns string) error {
if client == nil {
return fmt.Errorf("the reconciler client could not be found")
}
secret := &corev1.Secret{}
secret.Name = name
secret.Namespace = ns
err := client.Get(context.TODO(), types.NamespacedName{Name: name, Namespace: ns}, secret)
for key, value := range secret.Data {
clear(value)
delete(secret.Data, key)
}
return err
}