func getInfoFromRemote(c cli.Config) (resp *info.Resp, err error) { req := new(info.Req) req.Label = c.Label req.Profile = c.Profile cert, err := helpers.LoadClientCertificate(c.MutualTLSCertFile, c.MutualTLSKeyFile) if err != nil { return } remoteCAs, err := helpers.LoadPEMCertPool(c.TLSRemoteCAs) if err != nil { return } serv := client.NewServerTLS(c.Remote, helpers.CreateTLSConfig(remoteCAs, cert)) reqJSON, _ := json.Marshal(req) resp, err = serv.Info(reqJSON) if err != nil { return } _, err = helpers.ParseCertificatePEM([]byte(resp.Certificate)) if err != nil { return } return }
// LoadRootCAs loads the default root certificate authorities from file. func LoadRootCAs(caBundleFile string) (err error) { if caBundleFile != "" { log.Debugf("Loading scan RootCAs: %s", caBundleFile) RootCAs, err = helpers.LoadPEMCertPool(caBundleFile) } return }
func TestParseBundles(t *testing.T) { for _, file := range bundleFiles { if _, err := helpers.LoadPEMCertPool(file); err != nil { t.Fatal(err) } } }
// NewCFSSL produces a new CFSSL root. func NewCFSSL(metadata map[string]string) ([]*x509.Certificate, error) { host, ok := metadata["host"] if !ok { return nil, errors.New("transport: CFSSL root provider requires a host") } label := metadata["label"] profile := metadata["profile"] cert, err := helpers.LoadClientCertificate(metadata["mutual-tls-cert"], metadata["mutual-tls-key"]) if err != nil { return nil, err } remoteCAs, err := helpers.LoadPEMCertPool(metadata["tls-remote-ca"]) if err != nil { return nil, err } srv := client.NewServerTLS(host, helpers.CreateTLSConfig(remoteCAs, cert)) data, err := json.Marshal(info.Req{Label: label, Profile: profile}) if err != nil { return nil, err } resp, err := srv.Info(data) if err != nil { return nil, err } return helpers.ParseCertificatesPEM([]byte(resp.Certificate)) }
// SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS // remote requests func (p *Signing) SetRemoteCAsFromFile(caFile string) error { if caFile != "" { remoteCAs, err := helpers.LoadPEMCertPool(caFile) if err != nil { return err } p.SetRemoteCAs(remoteCAs) } return nil }
func remoteTLSSign(t *testing.T, isMutual bool) { certPool, err := helpers.LoadPEMCertPool(testCaFile) if err != nil { t.Fatal(err) } var clientCA *x509.CertPool if isMutual { clientCA = certPool } remoteServer := newTestSignServer(t, true, clientCA) defer closeTestServer(t, remoteServer) remoteConfig := testsuite.NewConfig(t, []byte(validMinimalRemoteConfig)) // override with full server URL to get https in protocol" remoteConfig.Signing.OverrideRemotes(remoteServer.URL) remoteConfig.Signing.SetRemoteCAs(certPool) if isMutual { remoteConfig.Signing.SetClientCertKeyPairFromFile(testClientFile, testClientKeyFile) } verifyRemoteSign(t, remoteConfig) }
// NewCFSSLProvider takes the configuration information from an // Identity (and an optional default remote), returning a CFSSL // instance. There should be a profile in id called "cfssl", which // should contain label and profile fields as needed. func NewCFSSLProvider(id *core.Identity, defaultRemote client.Remote) (*CFSSL, error) { if id == nil { return nil, errors.New("transport: the identity hasn't been initialised. Has it been loaded from disk?") } cap := &CFSSL{ DefaultRemote: defaultRemote, } cfssl := id.Profiles["cfssl"] if cfssl != nil { cap.Label = cfssl["label"] cap.Profile = cfssl["profile"] if cap.DefaultRemote == nil { cert, err := helpers.LoadClientCertificate(cfssl["mutual-tls-cert"], cfssl["mutual-tls-key"]) if err != nil { return nil, err } remoteCAs, err := helpers.LoadPEMCertPool(cfssl["tls-remote-ca"]) if err != nil { return nil, err } cap.DefaultRemote = client.NewServerTLS(cfssl["remote"], helpers.CreateTLSConfig(remoteCAs, cert)) } cap.DefaultAuth.Type = cfssl["auth-type"] cap.DefaultAuth.Key = cfssl["auth-key"] } err := cap.setRemoteAndAuth() if err != nil { return nil, err } return cap, nil }
// serverMain is the command line entry point to the API server. It sets up a // new HTTP server to handle sign, bundle, and validate requests. func serverMain(args []string, c cli.Config) error { conf = c // serve doesn't support arguments. if len(args) > 0 { return errors.New("argument is provided but not defined; please refer to the usage by flag -h") } bundler.IntermediateStash = conf.IntDir var err error if err = ubiquity.LoadPlatforms(conf.Metadata); err != nil { return err } if c.DBConfigFile != "" { db, err = dbconf.DBFromConfig(c.DBConfigFile) if err != nil { return err } } log.Info("Initializing signer") if s, err = sign.SignerFromConfigAndDB(c, db); err != nil { log.Warningf("couldn't initialize signer: %v", err) } if ocspSigner, err = ocspsign.SignerFromConfig(c); err != nil { log.Warningf("couldn't initialize ocsp signer: %v", err) } registerHandlers() addr := net.JoinHostPort(conf.Address, strconv.Itoa(conf.Port)) if conf.TLSCertFile == "" || conf.TLSKeyFile == "" { log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) } if conf.MutualTLSCAFile != "" { clientPool, err := helpers.LoadPEMCertPool(conf.MutualTLSCAFile) if err != nil { return fmt.Errorf("failed to load mutual TLS CA file: %s", err) } server := http.Server{ Addr: addr, TLSConfig: &tls.Config{ ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientPool, }, } if conf.MutualTLSCNRegex != "" { log.Debugf(`Requiring CN matches regex "%s" for client connections`, conf.MutualTLSCNRegex) re, err := regexp.Compile(conf.MutualTLSCNRegex) if err != nil { return fmt.Errorf("malformed CN regex: %s", err) } server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r != nil && r.TLS != nil && len(r.TLS.PeerCertificates) > 0 { if re.MatchString(r.TLS.PeerCertificates[0].Subject.CommonName) { http.DefaultServeMux.ServeHTTP(w, r) return } log.Warningf(`Rejected client cert CN "%s" does not match regex %s`, r.TLS.PeerCertificates[0].Subject.CommonName, conf.MutualTLSCNRegex) } http.Error(w, "Invalid CN", http.StatusForbidden) }) } log.Info("Now listening with mutual TLS on https://", addr) return server.ListenAndServeTLS(conf.TLSCertFile, conf.TLSKeyFile) } log.Info("Now listening on https://", addr) return http.ListenAndServeTLS(addr, conf.TLSCertFile, conf.TLSKeyFile, nil) }
func main() { var caFile, intFile string var forceIntermediateBundle, revexp, verbose bool flag.StringVar(&caFile, "ca", "", "CA certificate `bundle`") flag.StringVar(&intFile, "i", "", "intermediate `bundle`") flag.BoolVar(&forceIntermediateBundle, "f", false, "force the use of the intermediate bundle, ignoring any intermediates bundled with certificate") flag.BoolVar(&revexp, "r", false, "print revocation and expiry information") flag.BoolVar(&verbose, "v", false, "verbose") flag.Parse() var roots *x509.CertPool if caFile != "" { var err error if verbose { fmt.Println("[+] loading root certificates from", caFile) } roots, err = helpers.LoadPEMCertPool(caFile) die.If(err) } var ints *x509.CertPool if intFile != "" { var err error if verbose { fmt.Println("[+] loading intermediate certificates from", intFile) } ints, err = helpers.LoadPEMCertPool(caFile) die.If(err) } else { ints = x509.NewCertPool() } if flag.NArg() != 1 { fmt.Fprintf(os.Stderr, "Usage: %s [-ca bundle] [-i bundle] cert", lib.ProgName()) } fileData, err := ioutil.ReadFile(flag.Arg(0)) die.If(err) chain, err := helpers.ParseCertificatesPEM(fileData) die.If(err) if verbose { fmt.Printf("[+] %s has %d certificates\n", flag.Arg(0), len(chain)) } cert := chain[0] if len(chain) > 1 { if !forceIntermediateBundle { for _, intermediate := range chain[1:] { if verbose { fmt.Printf("[+] adding intermediate with SKI %x\n", intermediate.SubjectKeyId) } ints.AddCert(intermediate) } } } opts := x509.VerifyOptions{ Intermediates: ints, Roots: roots, KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, } _, err = cert.Verify(opts) if err != nil { fmt.Fprintf(os.Stderr, "Verification failed: %v\n", err) os.Exit(1) } if verbose { fmt.Println("OK") } if revexp { printRevocation(cert) } }