func newHTTPSTransport(tlsCertFile, tlsKeyFile, tlsCACertFile string) etcd.CancelableTransport { var cc *tls.Config = nil if tlsCertFile != "" && tlsKeyFile != "" { var rpool *x509.CertPool if tlsCACertFile != "" { if pemBytes, err := ioutil.ReadFile(tlsCACertFile); err == nil { rpool = x509.NewCertPool() rpool.AppendCertsFromPEM(pemBytes) } } if tlsCert, err := tls.LoadX509KeyPair(tlsCertFile, tlsKeyFile); err == nil { cc = &tls.Config{ RootCAs: rpool, Certificates: []tls.Certificate{tlsCert}, InsecureSkipVerify: true, } } } tr := &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: cc, } return tr }
// NewRemoteServer generates a RemoteServer with the server address and // the root CA the server uses to authenticate itself. func NewRemoteServer(serverAddress, CAFile string) (*RemoteServer, error) { var rootCAs *x509.CertPool // populate a root CA pool from input CAfile // otherwise, use the system's default root CA set if CAFile != "" { rootCAs = x509.NewCertPool() pemBytes, err := ioutil.ReadFile(CAFile) if err != nil { return nil, errors.New("fail to read CA file: " + err.Error()) } ok := rootCAs.AppendCertsFromPEM(pemBytes) if !ok { return nil, errors.New("fail to populate CA root pool.") } } tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: rootCAs}, DisableCompression: true, } server := &RemoteServer{ client: &http.Client{Transport: tr}, serverAddress: serverAddress, } return server, nil }
// getTLSConfig constructs a tls.Config that uses keys/certificates in the given files. func getTLSConfig(certFile, keyFile, caFile string) (*tls.Config, error) { var certs []tls.Certificate if certFile != "" || keyFile != "" { if certFile == "" || keyFile == "" { return nil, util.Errorf("TLS client requires both cert file and key file") } cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, util.Errorf("Could not load keypair: %s", err) } certs = append(certs, cert) } var cas *x509.CertPool if caFile != "" { cas = x509.NewCertPool() caBytes, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } ok := cas.AppendCertsFromPEM(caBytes) if !ok { return nil, util.Errorf("Could not parse certificate file: %s", caFile) } } tlsConfig := &tls.Config{ Certificates: certs, ClientCAs: cas, RootCAs: cas, } return tlsConfig, nil }
func loadCertFile(roots *x509.CertPool, fname string) error { data, err := ioutil.ReadFile(fname) if err == nil { roots.AppendCertsFromPEM(data) } return err }
/* main registers this RP's HTTP request handlers; creates the HTTPS client for issuing OP ID Token requests and starts its HTTP server. */ func main() { var ( certPool *x509.CertPool server http.Server err error ) //This aeadCipher is used to encrypt/decrypt the Authn Request Cookie that is used to pass the Authn Request State value //from the Authn Request to the Authn Response. aeadCipher, err = aead.NewAEADCipher() if err != nil { return } //Initialize an HTTPS capable client and replace the default aws HTTP client that doesn't support HTTPS certPool = x509.NewCertPool() certPool.AppendCertsFromPEM([]byte(certbndl.PemCerts)) opClient = &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: certPool}, }, } //Start the service server = http.Server{Addr: ":443", ReadTimeout: 10 * time.Minute, WriteTimeout: 10 * time.Minute, ErrorLog: logger.Logger()} http.HandleFunc("/login", handleLogin) http.HandleFunc("/authn-token", handleAuthnToken) logger.Println("Starting oidc on " + exthost + ":443") err = server.ListenAndServeTLS("resilient-networks.crt", "resilient-networks.key") if err != nil { logger.Fatal(err) } }
func (a *ldapAuther) Dial() error { var err error var certPool *x509.CertPool if a.server.RootCACert != "" { certPool := x509.NewCertPool() for _, caCertFile := range strings.Split(a.server.RootCACert, " ") { if pem, err := ioutil.ReadFile(caCertFile); err != nil { return err } else { if !certPool.AppendCertsFromPEM(pem) { return errors.New("Failed to append CA certificate " + caCertFile) } } } } for _, host := range strings.Split(a.server.Host, " ") { address := fmt.Sprintf("%s:%d", host, a.server.Port) if a.server.UseSSL { tlsCfg := &tls.Config{ InsecureSkipVerify: a.server.SkipVerifySSL, ServerName: host, RootCAs: certPool, } a.conn, err = ldap.DialTLS("tcp", address, tlsCfg) } else { a.conn, err = ldap.Dial("tcp", address) } if err == nil { return nil } } return err }
// loadTLSClientConfig initializes a *tls.Config using the given WebhookNotifierConfiguration. // // If no certificates are given, (nil, nil) is returned. // The CA certificate is optional and falls back to the system default. func loadTLSClientConfig(cfg *WebhookNotifierConfiguration) (*tls.Config, error) { if cfg.CertFile == "" || cfg.KeyFile == "" { return nil, nil } cert, err := tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile) if err != nil { return nil, err } var caCertPool *x509.CertPool if cfg.CAFile != "" { caCert, err := ioutil.ReadFile(cfg.CAFile) if err != nil { return nil, err } caCertPool = x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) } tlsConfig := &tls.Config{ ServerName: cfg.ServerName, Certificates: []tls.Certificate{cert}, RootCAs: caCertPool, } return tlsConfig, nil }
func GetHttpClient() *http.Client { if client != nil { return client } else { var certPool *x509.CertPool if pemfile := setting.KeystoneRootCAPEMFile; pemfile != "" { certPool = x509.NewCertPool() pemFileContent, err := ioutil.ReadFile(pemfile) if err != nil { panic(err) } if !certPool.AppendCertsFromPEM(pemFileContent) { log.Error(3, "Failed to load any certificates from Root CA PEM file %s", pemfile) } else { log.Info("Successfully loaded certificate(s) from %s", pemfile) } } tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: certPool, InsecureSkipVerify: !setting.KeystoneVerifySSLCert}, } tr.Proxy = http.ProxyFromEnvironment client = &http.Client{Transport: tr} return client } }
//func (ck *CertKit) GetTLSConfig(AuthRequired bool) (*tls.Config, error) { func (ck *CertKit) GetTLSConfig(Access uint8) (*tls.Config, error) { var atype tls.ClientAuthType var tlsConfig *tls.Config var roots *x509.CertPool switch Access { case stonelizard.AccessNone: atype = tls.NoClientCert case stonelizard.AccessAuth, stonelizard.AccessAuthInfo: atype = tls.RequestClientCert case stonelizard.AccessVerifyAuth, stonelizard.AccessVerifyAuthInfo: atype = tls.RequireAndVerifyClientCert // Code adapted from crypto/x509/root_unix.go roots = x509.NewCertPool() for _, directory := range CertDirectories { fis, err := ioutil.ReadDir(directory) if err != nil { Goose.Auth.Logf(5, "Error scanning certificate directory %s: %s", directory, err) continue } for _, fi := range fis { data, err := ioutil.ReadFile(fmt.Sprintf("%s%c%s", directory, os.PathSeparator, fi.Name())) if err != nil { Goose.Auth.Logf(5, "Error load CA certificate from %s%c%s: %s", directory, os.PathSeparator, fi.Name(), err) continue } Goose.Auth.Logf(5, "Loaded CA certificate from %s%c%s: %s", directory, os.PathSeparator, fi.Name(), err) roots.AppendCertsFromPEM(data) } } } Goose.Auth.Logf(6, "authtype: %#v", atype) Goose.Auth.Logf(6, "CAs: %#v", roots) tlsConfig = &tls.Config{ ClientAuth: atype, ClientCAs: roots, // InsecureSkipVerify: true, Certificates: make([]tls.Certificate, 1), } /* srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(svc.PemPath + "/server.crt", svc.PemPath + "/server.key") if err != nil { Goose.InitServe.Logf(1,"Failed reading server certificates: %s",err) return err } */ tlsConfig.Certificates[0] = ck.ServerX509KeyPair Goose.Auth.Logf(5, "X509KeyPair used: %#v", tlsConfig.Certificates[0]) tlsConfig.BuildNameToCertificate() return tlsConfig, nil }
// ExtendedValidateRoute performs an extended validation on the route // including checking that the TLS config is valid. func ExtendedValidateRoute(route *routeapi.Route) field.ErrorList { tlsConfig := route.Spec.TLS result := field.ErrorList{} if tlsConfig == nil { return result } tlsFieldPath := field.NewPath("spec").Child("tls") if errs := validateTLS(route, tlsFieldPath); len(errs) != 0 { result = append(result, errs...) } // TODO: Check if we can be stricter with validating the certificate // is for the route hostname. Don't want existing routes to // break, so disable the hostname validation for now. // hostname := route.Spec.Host hostname := "" var certPool *x509.CertPool if len(tlsConfig.CACertificate) > 0 { certPool = x509.NewCertPool() if ok := certPool.AppendCertsFromPEM([]byte(tlsConfig.CACertificate)); !ok { result = append(result, field.Invalid(tlsFieldPath.Child("caCertificate"), tlsConfig.CACertificate, "failed to parse CA certificate")) } } verifyOptions := &x509.VerifyOptions{ DNSName: hostname, Roots: certPool, } if len(tlsConfig.Certificate) > 0 { if _, err := validateCertificatePEM(tlsConfig.Certificate, verifyOptions); err != nil { result = append(result, field.Invalid(tlsFieldPath.Child("certificate"), tlsConfig.Certificate, err.Error())) } certKeyBytes := []byte{} certKeyBytes = append(certKeyBytes, []byte(tlsConfig.Certificate)...) if len(tlsConfig.Key) > 0 { certKeyBytes = append(certKeyBytes, byte('\n')) certKeyBytes = append(certKeyBytes, []byte(tlsConfig.Key)...) } if _, err := tls.X509KeyPair(certKeyBytes, certKeyBytes); err != nil { result = append(result, field.Invalid(tlsFieldPath.Child("key"), tlsConfig.Key, err.Error())) } } if len(tlsConfig.DestinationCACertificate) > 0 { roots := x509.NewCertPool() if ok := roots.AppendCertsFromPEM([]byte(tlsConfig.DestinationCACertificate)); !ok { result = append(result, field.Invalid(tlsFieldPath.Child("destinationCACertificate"), tlsConfig.DestinationCACertificate, "failed to parse destination CA certificate")) } } return result }
// LoadTLSConfig will load a certificate from config with all TLS based keys // defined. If Certificate and CertificateKey are configured, client authentication // will be configured. If no CAs are configured, the host CA will be used by go // built-in TLS support. func LoadTLSConfig(config MothershipConfig) (*tls.Config, error) { certificate := config.Certificate key := config.CertificateKey rootCAs := config.CAs hasCertificate := certificate != "" hasKey := key != "" var certs []tls.Certificate switch { case hasCertificate && !hasKey: return nil, ErrCertificateNoKey case !hasCertificate && hasKey: return nil, ErrKeyNoCertificate case hasCertificate && hasKey: cert, err := tls.LoadX509KeyPair(certificate, key) if err != nil { logp.Critical("Failed loading client certificate", err) return nil, err } certs = []tls.Certificate{cert} } var roots *x509.CertPool if len(rootCAs) > 0 { roots = x509.NewCertPool() for _, caFile := range rootCAs { pemData, err := ioutil.ReadFile(caFile) if err != nil { logp.Critical("Failed reading CA certificate: %s", err) return nil, err } if ok := roots.AppendCertsFromPEM(pemData); !ok { return nil, ErrNotACertificate } } } insecureSkipVerify := false if config.TLSInsecure != nil { insecureSkipVerify = *config.TLSInsecure } // Support minimal TLS 1.0. // TODO: check supported JRuby versions for logstash supported // TLS 1.1 and switch tlsConfig := tls.Config{ MinVersion: tls.VersionTLS10, Certificates: certs, RootCAs: roots, InsecureSkipVerify: insecureSkipVerify, } return &tlsConfig, nil }
func addCertsFromKeychain(pool *x509.CertPool, keychain string) error { cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", keychain) data, err := cmd.Output() if err != nil { return err } pool.AppendCertsFromPEM(data) return nil }
func (kvc *KVClient) prepareClient() error { hasCA := kvc.certificateAuthority != "" hasCert := kvc.clientCertificate != "" hasKey := kvc.clientKey != "" config := &store.Config{ ConnectionTimeout: 5 * time.Second, } if hasCA || hasCert || hasKey { var cacert *x509.CertPool if kvc.certificateAuthority != "" { capem, err := ioutil.ReadFile(kvc.certificateAuthority) if err != nil { return err } cacert = x509.NewCertPool() if !cacert.AppendCertsFromPEM(capem) { return errors.New("unable to load certificate authority") } } var cert tls.Certificate if kvc.clientCertificate != "" && kvc.clientKey != "" { c := kvc.clientCertificate k := kvc.clientKey var err error cert, err = tls.LoadX509KeyPair(c, k) if err != nil { return err } } config.ClientTLS = &store.ClientTLSConfig{ CertFile: kvc.clientCertificate, KeyFile: kvc.clientKey, CACertFile: kvc.certificateAuthority, } config.TLS = &tls.Config{ RootCAs: cacert, Certificates: []tls.Certificate{cert}, } } store, err := libkv.NewStore(kvc.backend, kvc.addresses, config) if err != nil { fmt.Println(err) logrus.Error("unable to create kvclient. ", err) return err } kvc.store = store return nil }
func NewClient() *Client { var caData []byte = nil var pool *x509.CertPool ac := new(Client) ac.insecure = false ac.host = os.Getenv("KUBERNETES_SERVICE_HOST") if ac.host != "" { // assume we are always on https ac.host = fmt.Sprintf("https://%s", ac.host) port := os.Getenv("KUBERNETES_SERVICE_PORT") if port != "" { ac.host = fmt.Sprintf("%s:%s", ac.host, port) } } ac.userAPI = os.Getenv("KUBERNETES_USER_API") if ac.userAPI == "" { ac.userAPI = "oapi" } ac.requireOpenshift, _ = strconv.ParseBool(os.Getenv("REGISTRY_ONLY")) ac.insecure, _ = strconv.ParseBool(os.Getenv("KUBERNETES_INSECURE")) if !ac.insecure { data := os.Getenv("KUBERNETES_CA_DATA") if data != "" { caData = []byte(data) } if caData == nil { var err error caData, err = ioutil.ReadFile(CA_PATH) if err != nil { log.Println(fmt.Sprintf("Couldn't load CA data: %s", err)) } } if caData != nil { pool = x509.NewCertPool() pool.AppendCertsFromPEM(caData) ac.caData = base64.StdEncoding.EncodeToString(caData) } } tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: pool, InsecureSkipVerify: ac.insecure}, } ac.client = &http.Client{Transport: tr} return ac }
func main() { configPath := flag.String("config", "", "config file") flag.Parse() var configs Config if _, err := toml.DecodeFile(*configPath, &configs); err != nil { log.Fatal(err) } // TODO: consider supporting multiple endpoints. for now just always // use the first one config := configs.Endpoint[0] var roots *x509.CertPool roots = nil if len(config.RootCAs) > 0 { roots = x509.NewCertPool() for _, CA := range config.RootCAs { pem, err := ioutil.ReadFile(CA) if err != nil { log.Fatal(err) } ok := roots.AppendCertsFromPEM(pem) if !ok { log.Fatal("failed to parse CA certificate") } } } tr := &http.Transport{ TLSClientConfig: &tls.Config{RootCAs: roots}, DisableCompression: true, } client = &http.Client{Transport: tr} plugin := &SplunkPlugin{Client: client, Token: config.AuthToken, Url: "https://" + config.Host + ":" + strconv.Itoa(config.Port) + config.URL} p, err := loggerplugin.NewLoggerPlugin(plugin) if err != nil { log.Fatal(err) } err = p.Run() if err != nil { log.Fatal(err) } }
// New creates a new JSON-RPC over HTTPS client which uses the given // certificate file to communicate with the server if the scheme of the URL is // https. func New(URL string, cert []byte) (*URLClient, error) { var pool *x509.CertPool transport := new(http.Transport) urlparsed, err := url.Parse(URL) if err != nil { return nil, err } if urlparsed.Scheme == "https" { pool = x509.NewCertPool() if !pool.AppendCertsFromPEM(cert) { return nil, ErrCertLoad } transport.TLSClientConfig = &tls.Config{RootCAs: pool} } return &URLClient{transport: transport, curl: URL}, nil }
// AppendCA opens and parses the CA file and adds the certificates to // the provided CertPool. func (c *Config) AppendCA(pool *x509.CertPool) error { if c.CAFile == "" { return nil } // Read the file data, err := ioutil.ReadFile(c.CAFile) if err != nil { return fmt.Errorf("Failed to read CA file: %v", err) } if !pool.AppendCertsFromPEM(data) { return fmt.Errorf("Failed to parse any CA certificates") } return nil }
func addCACert(path string, roots *x509.CertPool) *x509.CertPool { f, err := os.Open(path) if err != nil { log.Printf("Could not open CA cert: %v", err) return roots } fBytes, err := ioutil.ReadAll(f) if err != nil { log.Printf("Failed to read CA cert: %v", err) return roots } if !roots.AppendCertsFromPEM(fBytes) { log.Printf("Could not add client CA to pool: %v", err) } return roots }
// getTLSClient constructs an HTTP client that uses keys/certificates in the given files. func getTLSClient(certFile, keyFile, caFile string) (*http.Client, error) { var certs []tls.Certificate if certFile != "" || keyFile != "" { if certFile == "" || keyFile == "" { return nil, util.Errorf("TLS client requires both cert file and key file") } cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, err } certs = append(certs, cert) } var cas *x509.CertPool if caFile != "" { cas = x509.NewCertPool() caBytes, err := ioutil.ReadFile(caFile) if err != nil { return nil, err } ok := cas.AppendCertsFromPEM(caBytes) if !ok { return nil, util.Errorf("Could not parse certificate file: %s", caFile) } } if len(certs) == 0 && cas == nil { return http.DefaultClient, nil } tlsConfig := &tls.Config{ Certificates: certs, ClientCAs: cas, RootCAs: cas, } return &http.Client{Transport: &http.Transport{ TLSClientConfig: tlsConfig, // same dialer as http.DefaultTransport Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).Dial, }}, nil }
func (n *ng) newHttpTransport() etcd.CancelableTransport { var cc *tls.Config = nil if n.options.EtcdCertFile != "" && n.options.EtcdKeyFile != "" { var rpool *x509.CertPool = nil if n.options.EtcdCaFile != "" { if pemBytes, err := ioutil.ReadFile(n.options.EtcdCaFile); err == nil { rpool = x509.NewCertPool() rpool.AppendCertsFromPEM(pemBytes) } else { log.Errorf("Error reading Etcd Cert CA File: %v", err) } } if tlsCert, err := tls.LoadX509KeyPair(n.options.EtcdCertFile, n.options.EtcdKeyFile); err == nil { cc = &tls.Config{ RootCAs: rpool, Certificates: []tls.Certificate{tlsCert}, InsecureSkipVerify: true, } } else { log.Errorf("Error loading KeyPair for TLS client: %v", err) } } //Copied from etcd.DefaultTransport declaration //Wasn't sure how to make a clean reliable deep-copy, and instead //creating a new object was the safest and most reliable assurance //that we aren't overwriting some global struct potentially //shared by other etcd users. tr := &http.Transport{ Proxy: http.ProxyFromEnvironment, Dial: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).Dial, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: cc, } return tr }
func loadSystemCertificates(certPool *x509.CertPool) error { if _, err := os.Stat(systemCertPath); os.IsNotExist(err) { return nil } log.Debugf("loading system certificates: dir=%s", systemCertPath) return filepath.Walk(systemCertPath, func(path string, fi os.FileInfo, err error) error { if !fi.IsDir() { cert, err := ioutil.ReadFile(path) if err != nil { return err } certPool.AppendCertsFromPEM(cert) } return nil }) }
func appendCertsFromPEMData(pool *x509.CertPool, data []byte) *x509.CertPool { if len(data) == 0 { return pool } // Bit of a dance, need to ensure if AppendCertsFromPEM fails we still return // nil and not an empty pool, so system roots still get used var ret *x509.CertPool if pool == nil { ret = x509.NewCertPool() } else { ret = pool } if !ret.AppendCertsFromPEM(data) { // Return unmodified input pool (may be nil, do not replace with empty) return pool } return ret }
func (a *ApiClient) prepareClient() error { var cacert *x509.CertPool if a.certificateAuthority != "" { capem, err := ioutil.ReadFile(a.certificateAuthority) if err != nil { return err } cacert = x509.NewCertPool() if !cacert.AppendCertsFromPEM(capem) { return errors.New("unable to load certificate authority") } } var cert tls.Certificate if a.clientCertificate != "" && a.clientKey != "" { c := a.clientCertificate k := a.clientKey var err error cert, err = tls.LoadX509KeyPair(c, k) if err != nil { return err } } if cacert != nil || &cert != nil { config := &tls.Config{ RootCAs: cacert, Certificates: []tls.Certificate{cert}, } transport := &http.Transport{ TLSClientConfig: config, TLSHandshakeTimeout: 5 * time.Second, } client := &http.Client{Transport: transport} a.Client = client } else { a.Client = &http.Client{} } return nil }
func loadCertificates(caCertPool *x509.CertPool) error { securityDir, err := getJfrogSecurityDir() if err != nil { return err } if !ioutils.IsPathExists(securityDir) { return nil } files, err := ioutil.ReadDir(securityDir) err = cliutils.CheckError(err) if err != nil { return err } for _, file := range files { caCert, err := ioutil.ReadFile(securityDir + file.Name()) err = cliutils.CheckError(err) if err != nil { return err } caCertPool.AppendCertsFromPEM(caCert) } return nil }
// sslConnect establishes a SSL connection with the server. func (c *Conn) sslConnect() error { var ( cert tls.Certificate certPool *x509.CertPool pemCerts []byte conn *tls.Conn err error ) if c.p.sslCA != "" { certPool = x509.NewCertPool() if pemCerts, err = ioutil.ReadFile(c.p.sslCA); err != nil { return myError(ErrSSLConnection, err) } else { certPool.AppendCertsFromPEM(pemCerts) } } if cert, err = tls.LoadX509KeyPair(c.p.sslCert, c.p.sslKey); err != nil { return myError(ErrSSLConnection, err) } config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true, RootCAs: certPool} conn = tls.Client(c.conn, &config) if err = conn.Handshake(); err != nil { return myError(ErrSSLConnection, err) } // update the connection handle c.conn = conn return nil }
func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType, secure bool) (*http.Response, *http.Client, error) { var ( pool *x509.CertPool certs []tls.Certificate ) if secure && req.URL.Scheme == "https" { hasFile := func(files []os.FileInfo, name string) bool { for _, f := range files { if f.Name() == name { return true } } return false } hostDir := path.Join("/etc/docker/certs.d", req.URL.Host) log.Debugf("hostDir: %s", hostDir) fs, err := ioutil.ReadDir(hostDir) if err != nil && !os.IsNotExist(err) { return nil, nil, err } for _, f := range fs { if strings.HasSuffix(f.Name(), ".crt") { if pool == nil { pool = x509.NewCertPool() } log.Debugf("crt: %s", hostDir+"/"+f.Name()) data, err := ioutil.ReadFile(path.Join(hostDir, f.Name())) if err != nil { return nil, nil, err } pool.AppendCertsFromPEM(data) } if strings.HasSuffix(f.Name(), ".cert") { certName := f.Name() keyName := certName[:len(certName)-5] + ".key" log.Debugf("cert: %s", hostDir+"/"+f.Name()) if !hasFile(fs, keyName) { return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName) } cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName)) if err != nil { return nil, nil, err } certs = append(certs, cert) } if strings.HasSuffix(f.Name(), ".key") { keyName := f.Name() certName := keyName[:len(keyName)-4] + ".cert" log.Debugf("key: %s", hostDir+"/"+f.Name()) if !hasFile(fs, certName) { return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName) } } } } if len(certs) == 0 { client := newClient(jar, pool, nil, timeout, secure) res, err := client.Do(req) if err != nil { return nil, nil, err } return res, client, nil } client := newClient(jar, pool, certs, timeout, secure) res, err := client.Do(req) return res, client, err }
func main() { fs := flag.NewFlagSet("otsimo-accounts", flag.ExitOnError) listen := fs.String("listen", "http://127.0.0.1:18856", "") redirectURL := fs.String("redirect-url", "http://127.0.0.1:18856/callback", "") clientID := fs.String("client-id", "", "") clientSecret := fs.String("client-secret", "", "") caFile := fs.String("trusted-ca-file", "", "the TLS CA file, if empty then the host's root CA will be used") discovery := fs.String("discovery", "https://connect.otsimo.com", "") connectService := fs.String("dex", "127.0.0.1:18849", "Otsimo connect grpc url") apiService := fs.String("api", "127.0.0.1:18854", "Otsimo api grpc url") logDebug := fs.Bool("log-debug", false, "log debug-level information") logTimestamps := fs.Bool("log-timestamps", false, "prefix log lines with timestamps") if err := fs.Parse(os.Args[1:]); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } if err := pflag.SetFlagsFromEnv(fs, "OTSIMO_ACCOUNTS"); err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } if *logDebug { log.EnableDebug() } if *logTimestamps { log.EnableTimestamps() } if *clientID == "" { log.Fatal("--client-id must be set") } if *clientSecret == "" { log.Fatal("--client-secret must be set") } l, err := url.Parse(*listen) if err != nil { log.Fatalf("Unable to use --listen flag: %v", err) } _, p, err := net.SplitHostPort(l.Host) if err != nil { log.Fatalf("Unable to parse host from --listen flag: %v", err) } var tlsConfig tls.Config var roots *x509.CertPool if *caFile != "" { roots = x509.NewCertPool() pemBlock, err := ioutil.ReadFile(*caFile) if err != nil { log.Fatalf("Unable to read ca file: %v", err) } roots.AppendCertsFromPEM(pemBlock) tlsConfig.RootCAs = roots } client, tokenMan := NewClient(*clientID, *clientSecret, *discovery, *redirectURL, &tlsConfig) redirectURLParsed, err := url.Parse(*redirectURL) if err != nil { log.Fatalf("Unable to parse url from --redirect-url flag: %v", err) } accounts := NewOtsimoAccounts(client, tokenMan, roots) accounts.ConnectToServices(*connectService, *apiService) mux := NewClientHandler(accounts, *discovery, *redirectURLParsed) mux.Handle("/update/password", negroni.New( newTokenValidator(accounts), negroni.Wrap(handleChangePasswordFunc(accounts)), )) mux.Handle("/update/email", negroni.New( newTokenValidator(accounts), negroni.Wrap(handleChangeEmailFunc(accounts)), )) n := negroni.New(negroni.NewRecovery(), NewLogger()) n.UseHandler(mux) log.Infof("Binding to :%s...", p) //TODO(sercan) add TLS option log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", p), n)) }
// DRAGONS(tiborvass): If someone wonders why do we set tlsconfig in a roundtrip, // it's because it's so as to match the current behavior in master: we generate the // certpool on every-goddam-request. It's not great, but it allows people to just put // the certs in /etc/docker/certs.d/.../ and let docker "pick it up" immediately. Would // prefer an fsnotify implementation, but that was out of scope of my refactoring. func (m *httpsRequestModifier) ModifyRequest(req *http.Request) error { var ( roots *x509.CertPool certs []tls.Certificate hostDir string ) if req.URL.Scheme == "https" { hasFile := func(files []os.FileInfo, name string) bool { for _, f := range files { if f.Name() == name { return true } } return false } if runtime.GOOS == "windows" { hostDir = path.Join(os.TempDir(), "/docker/certs.d", req.URL.Host) } else { hostDir = path.Join("/etc/docker/certs.d", req.URL.Host) } logrus.Debugf("hostDir: %s", hostDir) fs, err := ioutil.ReadDir(hostDir) if err != nil && !os.IsNotExist(err) { return nil } for _, f := range fs { if strings.HasSuffix(f.Name(), ".crt") { if roots == nil { roots = x509.NewCertPool() } logrus.Debugf("crt: %s", hostDir+"/"+f.Name()) data, err := ioutil.ReadFile(filepath.Join(hostDir, f.Name())) if err != nil { return err } roots.AppendCertsFromPEM(data) } if strings.HasSuffix(f.Name(), ".cert") { certName := f.Name() keyName := certName[:len(certName)-5] + ".key" logrus.Debugf("cert: %s", hostDir+"/"+f.Name()) if !hasFile(fs, keyName) { return fmt.Errorf("Missing key %s for certificate %s", keyName, certName) } cert, err := tls.LoadX509KeyPair(filepath.Join(hostDir, certName), path.Join(hostDir, keyName)) if err != nil { return err } certs = append(certs, cert) } if strings.HasSuffix(f.Name(), ".key") { keyName := f.Name() certName := keyName[:len(keyName)-4] + ".cert" logrus.Debugf("key: %s", hostDir+"/"+f.Name()) if !hasFile(fs, certName) { return fmt.Errorf("Missing certificate %s for key %s", certName, keyName) } } } m.mu.Lock() m.tlsConfig.RootCAs = roots m.tlsConfig.Certificates = certs m.mu.Unlock() } return nil }
func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType) (*http.Response, *http.Client, error) { hasFile := func(files []os.FileInfo, name string) bool { for _, f := range files { if f.Name() == name { return true } } return false } hostDir := path.Join("/etc/docker/certs.d", req.URL.Host) fs, err := ioutil.ReadDir(hostDir) if err != nil && !os.IsNotExist(err) { return nil, nil, err } var ( pool *x509.CertPool certs []*tls.Certificate ) for _, f := range fs { if strings.HasSuffix(f.Name(), ".crt") { if pool == nil { pool = x509.NewCertPool() } data, err := ioutil.ReadFile(path.Join(hostDir, f.Name())) if err != nil { return nil, nil, err } pool.AppendCertsFromPEM(data) } if strings.HasSuffix(f.Name(), ".cert") { certName := f.Name() keyName := certName[:len(certName)-5] + ".key" if !hasFile(fs, keyName) { return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName) } cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName)) if err != nil { return nil, nil, err } certs = append(certs, &cert) } if strings.HasSuffix(f.Name(), ".key") { keyName := f.Name() certName := keyName[:len(keyName)-4] + ".cert" if !hasFile(fs, certName) { return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName) } } } if len(certs) == 0 { client := newClient(jar, pool, nil, timeout) res, err := client.Do(req) if err != nil { return nil, nil, err } return res, client, nil } for i, cert := range certs { client := newClient(jar, pool, cert, timeout) res, err := client.Do(req) // If this is the last cert, otherwise, continue to next cert if 403 or 5xx if i == len(certs)-1 || err == nil && res.StatusCode != 403 && res.StatusCode < 500 { return res, client, err } } return nil, nil, nil }
// LoadTLSConfig will load a certificate from config with all TLS based keys // defined. If Certificate and CertificateKey are configured, client authentication // will be configured. If no CAs are configured, the host CA will be used by go // built-in TLS support. func LoadTLSConfig(config *TLSConfig) (*tls.Config, error) { if config == nil || config.Disabled { return nil, nil } certificate := config.Certificate key := config.CertificateKey rootCAs := config.CAs hasCertificate := certificate != "" hasKey := key != "" var certs []tls.Certificate switch { case hasCertificate && !hasKey: return nil, ErrCertificateNoKey case !hasCertificate && hasKey: return nil, ErrKeyNoCertificate case hasCertificate && hasKey: cert, err := tls.LoadX509KeyPair(certificate, key) if err != nil { logp.Critical("Failed loading client certificate", err) return nil, err } certs = []tls.Certificate{cert} } var roots *x509.CertPool if len(rootCAs) > 0 { roots = x509.NewCertPool() for _, caFile := range rootCAs { pemData, err := ioutil.ReadFile(caFile) if err != nil { logp.Critical("Failed reading CA certificate: %s", err) return nil, err } if ok := roots.AppendCertsFromPEM(pemData); !ok { return nil, ErrNotACertificate } } } insecureSkipVerify := false if config.TLSInsecure != nil { insecureSkipVerify = *config.TLSInsecure } minVersion, err := parseTLSVersion(config.MinVersion) if err != nil { return nil, err } maxVersion, err := parseTLSVersion(config.MaxVersion) if err != nil { return nil, err } cipherSuites, err := parseTLSCipherSuites(config.CipherSuites) if err != nil { return nil, err } curveIDs, err := parseCurveTypes(config.CurveTypes) if err != nil { return nil, err } tlsConfig := tls.Config{ MinVersion: minVersion, MaxVersion: maxVersion, Certificates: certs, RootCAs: roots, InsecureSkipVerify: insecureSkipVerify, CipherSuites: cipherSuites, CurvePreferences: curveIDs, } return &tlsConfig, nil }