plugin/lib/certs/tls.go (118 lines of code) (raw):

package certs /* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved */ import ( "crypto/tls" "crypto/x509" "encoding/pem" "fmt" "runtime" "github.com/facebookincubator/go2chef" "github.com/mitchellh/mapstructure" ) type TLSConfiguration struct { TrustedCACerts []*x509.Certificate ClientCerts []tls.Certificate DisableCertVerification bool } func NewTLSConfiguration() *TLSConfiguration { return &TLSConfiguration{ TrustedCACerts: nil, ClientCerts: nil, DisableCertVerification: false, } } var TLS = NewTLSConfiguration() func (t *TLSConfiguration) GetTLSClientConf() (*tls.Config, error) { var rcaPool *x509.CertPool // pull the system cert pool as a base...unless we're on windows if runtime.GOOS != "windows" { if p, err := x509.SystemCertPool(); err != nil { return nil, err } else { rcaPool = p } } else { // only set the cert pool if we have CAs to trust // because windows will work if len(t.TrustedCACerts) > 0 { rcaPool = x509.NewCertPool() } } if len(t.TrustedCACerts) > 0 && rcaPool != nil { for _, rca := range t.TrustedCACerts { rcaPool.AddCert(rca) } } return &tls.Config{ Certificates: t.ClientCerts, RootCAs: rcaPool, }, nil } type tlsParse struct { TrustedCACerts []string `mapstructure:"trusted_ca_certs"` ClientCerts []tlsParseClientCert `mapstructure:"client_certs"` DisableCertVerification bool `mapstructure:"disable_cert_verification"` } type tlsParseClientCert struct { Certificate string `mapstructure:"certificate"` Key string `mapstructure:"key"` } func LoadTLSConfigurationFromMap(data interface{}) (*TLSConfiguration, error) { parse := tlsParse{} if err := mapstructure.Decode(data, &parse); err != nil { return nil, err } out := NewTLSConfiguration() tcc, err := loadCertStringArray(parse.TrustedCACerts) if err != nil { return nil, err } cc, err := loadClientCerts(parse.ClientCerts) if err != nil { return nil, err } out.TrustedCACerts = tcc out.ClientCerts = cc out.DisableCertVerification = parse.DisableCertVerification return out, nil } func loadCertStringArray(certSA []string) ([]*x509.Certificate, error) { var dest []*x509.Certificate for i, certPEM := range certSA { block, _ := pem.Decode([]byte(certPEM)) if block == nil { return nil, fmt.Errorf("error decoding trusted_ca_certs element %d", i) } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err } dest = append(dest, cert) } return dest, nil } func loadClientCerts(in []tlsParseClientCert) ([]tls.Certificate, error) { var out []tls.Certificate for _, kp := range in { crt, err := tls.X509KeyPair([]byte(kp.Certificate), []byte(kp.Key)) if err != nil { return nil, err } out = append(out, crt) } return out, nil } func tlsProcessor(f string, data interface{}) error { t, err := LoadTLSConfigurationFromMap(data) if err != nil { return err } TLS = t return nil } func toFullCerts(in []*x509.Certificate) []x509.Certificate { var fc []x509.Certificate for _, c := range in { fc = append(fc, *c) } return fc } func init() { go2chef.GlobalConfiguration.MustRegister("tls", tlsProcessor) }