github.com/openshift/installer@v1.4.17/pkg/asset/manifests/additionaltrustbundleconfig.go (about) 1 package manifests 2 3 import ( 4 "context" 5 "crypto/x509" 6 "encoding/pem" 7 "fmt" 8 "path/filepath" 9 "strings" 10 11 "github.com/pkg/errors" 12 "github.com/sirupsen/logrus" 13 corev1 "k8s.io/api/core/v1" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "sigs.k8s.io/yaml" 16 17 "github.com/openshift/api/annotations" 18 "github.com/openshift/installer/pkg/asset" 19 "github.com/openshift/installer/pkg/asset/installconfig" 20 ) 21 22 var ( 23 additionalTrustBundleConfigFileName = filepath.Join(manifestDir, "user-ca-bundle-config.yaml") 24 ) 25 26 const ( 27 additionalTrustBundleConfigDataKey = "ca-bundle.crt" 28 additionalTrustBundleConfigMapName = "user-ca-bundle" 29 ) 30 31 // AdditionalTrustBundleConfig generates the additional-trust-bundle-config.yaml files. 32 type AdditionalTrustBundleConfig struct { 33 ConfigMap *corev1.ConfigMap 34 File *asset.File 35 } 36 37 var _ asset.WritableAsset = (*AdditionalTrustBundleConfig)(nil) 38 39 // Name returns a human friendly name for the asset. 40 func (*AdditionalTrustBundleConfig) Name() string { 41 return "Additional Trust Bundle Config" 42 } 43 44 // Dependencies returns all of the dependencies directly needed to generate 45 // the asset. 46 func (*AdditionalTrustBundleConfig) Dependencies() []asset.Asset { 47 return []asset.Asset{ 48 &installconfig.InstallConfig{}, 49 } 50 } 51 52 // Generate generates the CloudProviderConfig. 53 func (atbc *AdditionalTrustBundleConfig) Generate(_ context.Context, dependencies asset.Parents) error { 54 installConfig := &installconfig.InstallConfig{} 55 dependencies.Get(installConfig) 56 57 if installConfig.Config.AdditionalTrustBundle == "" { 58 return nil 59 } 60 data, err := ParseCertificates(installConfig.Config.AdditionalTrustBundle) 61 62 if err != nil { 63 return err 64 } 65 66 cm := &corev1.ConfigMap{ 67 TypeMeta: metav1.TypeMeta{ 68 APIVersion: corev1.SchemeGroupVersion.String(), 69 Kind: "ConfigMap", 70 }, 71 ObjectMeta: metav1.ObjectMeta{ 72 Namespace: "openshift-config", 73 Name: additionalTrustBundleConfigMapName, 74 Annotations: map[string]string{ 75 annotations.OpenShiftComponent: "End User", 76 }, 77 }, 78 Data: data, 79 } 80 81 cmData, err := yaml.Marshal(cm) 82 if err != nil { 83 return errors.Wrapf(err, "failed to create %s manifest", atbc.Name()) 84 } 85 atbc.ConfigMap = cm 86 atbc.File = &asset.File{ 87 Filename: additionalTrustBundleConfigFileName, 88 Data: cmData, 89 } 90 return nil 91 } 92 93 // Files returns the files generated by the asset. 94 func (atbc *AdditionalTrustBundleConfig) Files() []*asset.File { 95 if atbc.File != nil { 96 return []*asset.File{atbc.File} 97 } 98 return []*asset.File{} 99 } 100 101 // Load loads the already-rendered files back from disk. 102 func (atbc *AdditionalTrustBundleConfig) Load(f asset.FileFetcher) (bool, error) { 103 return false, nil 104 } 105 106 // ParseCertificates parses and verifies a PEM certificate bundle 107 func ParseCertificates(certificates string) (map[string]string, error) { 108 rest := []byte(certificates) 109 var sb strings.Builder 110 for { 111 var block *pem.Block 112 block, rest = pem.Decode(rest) 113 if block == nil { 114 return nil, fmt.Errorf("unable to parse certificate, please check the additionalTrustBundle section of install-config.yaml") 115 } 116 117 cert, err := x509.ParseCertificate(block.Bytes) 118 119 if err != nil { 120 return nil, err 121 } 122 123 if cert.Version < 3 { 124 logrus.Warnf("Certificate %X from additionalTrustBundle is x509 v%d", cert.SerialNumber, cert.Version) 125 } else if !cert.IsCA { 126 logrus.Warnf("Certificate %X from additionalTrustBundle is x509 v%d but not a certificate authority", cert.SerialNumber, cert.Version) 127 } 128 129 sb.WriteString(string(pem.EncodeToMemory(block))) 130 131 if len(rest) == 0 { 132 break 133 } 134 } 135 return map[string]string{additionalTrustBundleConfigDataKey: sb.String()}, nil 136 }