-
Notifications
You must be signed in to change notification settings - Fork 20
/
truststore.go
143 lines (128 loc) · 3.77 KB
/
truststore.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package generator
import (
"context"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"software.sslmate.com/src/go-pkcs12"
"github.com/ForgeRock/secret-agent/api/v1alpha1"
"github.com/ForgeRock/secret-agent/pkg/secretsmanager"
)
func parseRootChain(bundle []byte) []*x509.Certificate {
var parsed []*x509.Certificate
for len(bundle) > 0 {
var block *pem.Block
block, bundle = pem.Decode(bundle)
if block == nil {
break
}
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
continue
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
continue
}
parsed = append(parsed, cert)
}
return parsed
}
// NewTrustStore create an new trust store object
func NewTrustStore(key *v1alpha1.KeyConfig) *TrustStore {
store := &TrustStore{
V1Spec: key.Spec,
Name: key.Name,
}
return store
}
// TrustStore a KeyMgr for managing truststores
type TrustStore struct {
Name string
refKeys []string
refDataKeys []string
refData []byte
V1Spec *v1alpha1.KeySpec
Value []byte
}
// References all names the ids of references required for generation
func (ts *TrustStore) References() ([]string, []string) {
for _, path := range ts.V1Spec.TruststoreImportPaths {
secretName, secretDataKey := handleRefPath(path)
ts.refKeys = append(ts.refKeys, secretName)
// root "certs" magically have a .pem in their data key.
ts.refDataKeys = append(ts.refDataKeys, fmt.Sprintf("%s.pem", secretDataKey))
}
return ts.refKeys, ts.refDataKeys
}
// LoadReferenceData load all alias reference data
func (ts *TrustStore) LoadReferenceData(data map[string][]byte) error {
for index, key := range ts.refDataKeys {
if value, ok := data[fmt.Sprintf("%s/%s", ts.refKeys[index], key)]; ok {
ts.refData = append(ts.refData, value...)
} else {
return errors.New(fmt.Sprintf("Reference Data Not Foundi for key: %s", key))
}
}
return nil
}
// LoadSecretFromManager load from secret manager
func (ts *TrustStore) LoadSecretFromManager(context context.Context, sm secretsmanager.SecretManager, namespace, secretName string) error {
return nil
}
// EnsureSecretManager adds to secret manager
func (ts *TrustStore) EnsureSecretManager(context context.Context, sm secretsmanager.SecretManager, namespace, secretName string) error {
return nil
}
// Generate and all of its aliases
func (ts *TrustStore) Generate() error {
// PEM certs - only support adding trusstore paths
if ts.V1Spec.PEMFormat {
ts.Value = append(ts.Value, ts.refData...)
return nil
}
systemBundle, err := ioutil.ReadFile("/etc/ssl/certs/ca-certificates.crt")
if err != nil {
return errors.WithMessage(err, "error occurred when attempting to read system trust store")
}
pemBytes := append(ts.Value, systemBundle...)
pemBytes = append(pemBytes, ts.refData...)
parsedCerts := parseRootChain(pemBytes)
if err != nil {
return errors.WithStack(err)
}
ts.Value, err = pkcs12.EncodeTrustStore(rand.Reader, parsedCerts, "changeit")
if err != nil {
return errors.WithStack(err)
}
return nil
}
// LoadFromData from from bytes
func (ts *TrustStore) LoadFromData(secData map[string][]byte) {
if value, ok := secData[ts.Name]; ok {
ts.Value = value
}
}
// IsEmpty test if empty
func (ts *TrustStore) IsEmpty() bool {
return len(ts.Value) == 0
}
// ToKubernetes serializes data to kubernetes secret
func (ts *TrustStore) ToKubernetes(secObject *corev1.Secret) {
if secObject.Data == nil {
secObject.Data = make(map[string][]byte, 1)
}
if empty := ts.IsEmpty(); !empty {
secObject.Data[ts.Name] = ts.Value
}
}
// InSecret return true if the key is one found in the secret
func (ts *TrustStore) InSecret(secObject *corev1.Secret) bool {
if _, ok := secObject.Data[ts.Name]; ok {
return true
}
return false
}