-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
additionaltrustbundleconfig.go
135 lines (113 loc) · 3.51 KB
/
additionaltrustbundleconfig.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
package manifests
import (
"crypto/x509"
"encoding/pem"
"fmt"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/yaml"
"github.com/openshift/api/annotations"
"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/installconfig"
)
var (
additionalTrustBundleConfigFileName = filepath.Join(manifestDir, "user-ca-bundle-config.yaml")
)
const (
additionalTrustBundleConfigDataKey = "ca-bundle.crt"
additionalTrustBundleConfigMapName = "user-ca-bundle"
)
// AdditionalTrustBundleConfig generates the additional-trust-bundle-config.yaml files.
type AdditionalTrustBundleConfig struct {
ConfigMap *corev1.ConfigMap
File *asset.File
}
var _ asset.WritableAsset = (*AdditionalTrustBundleConfig)(nil)
// Name returns a human friendly name for the asset.
func (*AdditionalTrustBundleConfig) Name() string {
return "Additional Trust Bundle Config"
}
// Dependencies returns all of the dependencies directly needed to generate
// the asset.
func (*AdditionalTrustBundleConfig) Dependencies() []asset.Asset {
return []asset.Asset{
&installconfig.InstallConfig{},
}
}
// Generate generates the CloudProviderConfig.
func (atbc *AdditionalTrustBundleConfig) Generate(dependencies asset.Parents) error {
installConfig := &installconfig.InstallConfig{}
dependencies.Get(installConfig)
if installConfig.Config.AdditionalTrustBundle == "" {
return nil
}
data, err := ParseCertificates(installConfig.Config.AdditionalTrustBundle)
if err != nil {
return err
}
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "ConfigMap",
},
ObjectMeta: metav1.ObjectMeta{
Namespace: "openshift-config",
Name: additionalTrustBundleConfigMapName,
Annotations: map[string]string{
annotations.OpenShiftComponent: "End User",
},
},
Data: data,
}
cmData, err := yaml.Marshal(cm)
if err != nil {
return errors.Wrapf(err, "failed to create %s manifest", atbc.Name())
}
atbc.ConfigMap = cm
atbc.File = &asset.File{
Filename: additionalTrustBundleConfigFileName,
Data: cmData,
}
return nil
}
// Files returns the files generated by the asset.
func (atbc *AdditionalTrustBundleConfig) Files() []*asset.File {
if atbc.File != nil {
return []*asset.File{atbc.File}
}
return []*asset.File{}
}
// Load loads the already-rendered files back from disk.
func (atbc *AdditionalTrustBundleConfig) Load(f asset.FileFetcher) (bool, error) {
return false, nil
}
// ParseCertificates parses and verifies a PEM certificate bundle
func ParseCertificates(certificates string) (map[string]string, error) {
rest := []byte(certificates)
var sb strings.Builder
for {
var block *pem.Block
block, rest = pem.Decode(rest)
if block == nil {
return nil, fmt.Errorf("unable to parse certificate, please check the additionalTrustBundle section of install-config.yaml")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
return nil, err
}
if cert.Version < 3 {
logrus.Warnf("Certificate %X from additionalTrustBundle is x509 v%d", cert.SerialNumber, cert.Version)
} else if !cert.IsCA {
logrus.Warnf("Certificate %X from additionalTrustBundle is x509 v%d but not a certificate authority", cert.SerialNumber, cert.Version)
}
sb.WriteString(string(pem.EncodeToMemory(block)))
if len(rest) == 0 {
break
}
}
return map[string]string{additionalTrustBundleConfigDataKey: sb.String()}, nil
}