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  }