// scanHandler is an HTTP handler that accepts GET parameters for host (required) // family and scanner, and uses these to perform scans, returning a JSON blob result. func scanHandler(w http.ResponseWriter, r *http.Request) error { if err := r.ParseForm(); err != nil { log.Warningf("failed to parse body: %v", err) return errors.NewBadRequest(err) } family := r.Form.Get("family") scanner := r.Form.Get("scanner") ip := r.Form.Get("ip") host := r.Form.Get("host") if host == "" { log.Warningf("no host given") return errors.NewBadRequestString("no host given") } results, err := scan.Default.RunScans(host, ip, family, scanner, 0) if err != nil { log.Warningf("%v", err) return errors.NewBadRequest(err) } response := api.NewSuccessResponse(results) enc := json.NewEncoder(w) return enc.Encode(response) }
// 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 } log.Info("Initializing signer") if s, err = sign.SignerFromConfig(c); 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)) log.Info("Now listening on ", addr) return http.ListenAndServe(addr, nil) }
// Handle responds to requests for the CA to generate a new private // key and certificate request on behalf of the client. The format for // these requests is documented in the API documentation. func (g *GeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error { log.Info("request for CSR") req := new(csr.CertificateRequest) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } key, csr, err := g.generator.ProcessRequest(req) if err != nil { log.Warningf("failed to process CSR: %v", err) // The validator returns a *cfssl/errors.HttpError return err } // Both key and csr are returned PEM-encoded. response := newSuccessResponse(&CertRequest{string(key), string(csr)}) w.Header().Set("Content-Type", "application/json") enc := json.NewEncoder(w) err = enc.Encode(response) return err }
// Handle listens for incoming requests for CA information, and returns // a list containing information on each root certificate. func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error { req := new(info.Req) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } r.Body.Close() err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } resp, err := h.sign.Info(*req) if err != nil { return err } response := api.NewSuccessResponse(resp) w.Header().Set("Content-Type", "application/json") enc := json.NewEncoder(w) return enc.Encode(response) }
// initialCAHandler is an HTTP handler that accepts a JSON blob in the // same format as the CSR endpoint; this blob should contain the // identity information for the CA's root key. This endpoint is not // suitable for creating intermediate certificates. func initialCAHandler(w http.ResponseWriter, r *http.Request) error { log.Info("setting up initial CA handler") body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } r.Body.Close() req := new(csr.CertificateRequest) req.KeyRequest = csr.NewBasicKeyRequest() err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } cert, _, key, err := initca.New(req) if err != nil { log.Warningf("failed to initialise new CA: %v", err) return err } response := api.NewSuccessResponse(&NewCA{string(key), string(cert)}) enc := json.NewEncoder(w) err = enc.Encode(response) return err }
// Handle implements an http.Handler interface for the bundle handler. func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) (err error) { blob, matched, err := api.ProcessRequestFirstMatchOf(r, [][]string{ []string{"certificate"}, []string{"domain"}, }) if err != nil { log.Warningf("invalid request: %v", err) return err } var cert *certinfo.Certificate switch matched[0] { case "domain": if cert, err = certinfo.ParseCertificateDomain(blob["domain"]); err != nil { log.Warningf("couldn't parse remote certificate: %v", err) return err } case "certificate": if cert, err = certinfo.ParseCertificatePEM([]byte(blob["certificate"])); err != nil { log.Warningf("bad PEM certifcate: %v", err) return err } } return api.SendResponse(w, cert) }
// scanHandler is an HTTP handler that accepts GET parameters for host (required) // family and scanner, and uses these to perform scans, returning a JSON blob result. func scanHandler(w http.ResponseWriter, r *http.Request) error { if err := r.ParseForm(); err != nil { log.Warningf("failed to parse body: %v", err) return errors.NewBadRequest(err) } if len(r.Form["host"]) == 0 { log.Warningf("no host given") return errors.NewBadRequestString("no host given") } host := r.Form["host"][0] var family, scanner string if len(r.Form["family"]) > 0 { family = r.Form["family"][0] } if len(r.Form["scanner"]) > 0 { scanner = r.Form["scanner"][0] } results, err := scan.Default.RunScans(host, family, scanner) if err != nil { log.Warningf("%v", err) return errors.NewBadRequest(err) } response := api.NewSuccessResponse(results) enc := json.NewEncoder(w) return enc.Encode(response) }
// Handle accepts client information requests, and uses the label to // look up the signer whose public certificate should be retrieved. If // the label is empty, the default label is used. func (h *MultiHandler) Handle(w http.ResponseWriter, r *http.Request) error { req := new(info.Req) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } log.Debug("checking label") if req.Label == "" { req.Label = h.defaultLabel } if _, ok := h.signers[req.Label]; !ok { log.Warningf("request for invalid endpoint") return errors.NewBadRequestString("bad label") } log.Debug("getting info") resp, err := h.signers[req.Label].Info(*req) if err != nil { log.Infof("error getting certificate: %v", err) return err } response := api.NewSuccessResponse(resp) w.Header().Set("Content-Type", "application/json") enc := json.NewEncoder(w) return enc.Encode(response) }
func (rcg *RemoteCertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error { req := new(genSignRequest) body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } csrPEM, key, err := rcg.generator.ProcessRequest(req.Request) if err != nil { log.Warningf("failed to process CSR: %v", err) // The validator returns a *cfssl/errors.HttpError return err } certPEM, err := rcg.remote.Sign(req.Hostname, csrPEM, req.Profile) if err != nil { log.Warningf("failed to send CSR to remote signer: %v", err) return err } result := map[string]string{ "private_key": string(key), "certificate": string(certPEM), } return sendResponse(w, result) }
// Handle implements an http.Handler interface for the bundle handler. func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error { blob, matched, err := api.ProcessRequestFirstMatchOf(r, [][]string{ {"certificate"}, {"domain"}, }) if err != nil { log.Warningf("invalid request: %v", err) return err } flavor := blob["flavor"] bf := bundler.Ubiquitous if flavor != "" { bf = bundler.BundleFlavor(flavor) } log.Infof("request for flavor %v", bf) var result *bundler.Bundle switch matched[0] { case "domain": bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], bf) if err != nil { log.Warningf("couldn't bundle from remote: %v", err) return err } result = bundle case "certificate": bundle, err := h.bundler.BundleFromPEMorDER([]byte(blob["certificate"]), []byte(blob["private_key"]), bf, "") if err != nil { log.Warning("bad PEM certifcate or private key") return err } serverName := blob["domain"] ip := blob["ip"] if serverName != "" { err := bundle.Cert.VerifyHostname(serverName) if err != nil { return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err) } } if ip != "" { err := bundle.Cert.VerifyHostname(ip) if err != nil { return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err) } } result = bundle } log.Info("wrote response") return api.SendResponse(w, result) }
// registerHandlers instantiates various handlers and assoicate them to corresponding endpoints. func registerHandlers() error { log.Info("Setting up signer endpoint") signHandler, err := api.NewSignHandler(Config.caFile, Config.caKeyFile) if err != nil { log.Warningf("endpoint '/api/v1/cfssl/sign' is disabled: %v", err) } else { http.Handle("/api/v1/cfssl/sign", signHandler) } log.Info("Setting up bundler endpoint") bundleHandler, err := api.NewBundleHandler(Config.caBundleFile, Config.intBundleFile) if err != nil { log.Warningf("endpoint '/api/v1/cfssl/bundle' is disabled: %v", err) } else { http.Handle("/api/v1/cfssl/bundle", bundleHandler) } log.Info("Setting up CSR endpoint") generatorHandler, err := api.NewGeneratorHandler(api.CSRValidate) if err != nil { log.Errorf("Failed to set up CSR endpoint: %v", err) return err } http.Handle("/api/v1/cfssl/newkey", generatorHandler) log.Info("Setting up new cert endpoint") newCertGenerator, err := api.NewCertGeneratorHandler(api.CSRValidate, Config.caFile, Config.caKeyFile) if err != nil { log.Errorf("endpoint '/api/v1/cfssl/newcert' is disabled") } else { http.Handle("/api/v1/cfssl/newcert", newCertGenerator) } log.Info("Setting up initial CA endpoint") http.Handle("/api/v1/cfssl/init_ca", api.NewInitCAHandler()) if Config.remote != "" { log.Info("Remote CFSSL endpoint given, setting up remote certificate generator") if rcg, err := api.NewRemoteCertGenerator(api.CSRValidate, Config.remote); err != nil { log.Errorf("Failed to set up remote certificate generator: %v", err) return err } else { http.Handle("/api/v1/cfssl/remotecert", rcg) } } log.Info("Handler set up complete.") return nil }
// check a cert against a specific CRL. Returns the same bool pair // as revCheck. func certIsRevokedCRL(cert *x509.Certificate, url string) (revoked, ok bool) { crl, ok := CRLSet[url] if ok && crl == nil { ok = false crlLock.Lock() delete(CRLSet, url) crlLock.Unlock() } var shouldFetchCRL = true if ok { if !crl.HasExpired(time.Now()) { shouldFetchCRL = false } } issuer := getIssuer(cert) if shouldFetchCRL { var err error crl, err = fetchCRL(url) if err != nil { log.Warningf("failed to fetch CRL: %v", err) return false, false } // check CRL signature if issuer != nil { err = issuer.CheckCRLSignature(crl) if err != nil { log.Warningf("failed to verify CRL: %v", err) return false, false } } crlLock.Lock() CRLSet[url] = crl crlLock.Unlock() } for _, revoked := range crl.TBSCertList.RevokedCertificates { if cert.SerialNumber.Cmp(revoked.SerialNumber) == 0 { log.Info("Serial number match: intermediate is revoked.") return true, true } } return false, true }
// worker does all the parsing and validation of the certificate(s) // contained in a single file. It first reads all the data in the // file, then begins parsing certificates in the file. Those // certificates are then checked for revocation. func worker(paths chan string, bundler chan *x509.Certificate, pool *sync.WaitGroup) { defer (*pool).Done() for { path, ok := <-paths if !ok { return } log.Infof("Loading %s", path) fileData, err := ioutil.ReadFile(path) if err != nil { log.Warningf("%v", err) continue } for { var block *pem.Block if len(fileData) == 0 { break } block, fileData = pem.Decode(fileData) if block == nil { log.Warningf("%s: no PEM data found", path) break } else if block.Type != "CERTIFICATE" { log.Info("Skipping non-certificate") continue } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { log.Warningf("Invalid certificate: %v", err) continue } log.Infof("Validating %+v", cert.Subject) revoked, ok := revoke.VerifyCertificate(cert) if !ok { log.Warning("Failed to verify certificate.") } else if !revoked { bundler <- cert } else { log.Info("Skipping revoked certificate") } } } }
// check a cert against a specific CRL. Returns the same bool pair // as revCheck. func certIsRevokedCRL(cert *x509.Certificate, url string) (revoked, ok bool) { crl, ok := CRLSet[url] if ok && crl == nil { ok = false delete(CRLSet, url) } var shouldFetchCRL = true if ok { if !crl.HasExpired(time.Now()) { shouldFetchCRL = false } } if shouldFetchCRL { var err error crl, err = fetchCRL(url) if err != nil { log.Warningf("failed to fetch CRL: %v", err) return false, false } CRLSet[url] = crl } for _, revoked := range crl.TBSCertList.RevokedCertificates { if cert.SerialNumber.Cmp(revoked.SerialNumber) == 0 { log.Info("Serial number match: intermediate is revoked.") return true, true } } return false, true }
func scanMain(args []string, c cli.Config) (err error) { if c.List { printJSON(scan.Default) } else { if err = scan.LoadRootCAs(c.CABundleFile); err != nil { return } if len(args) >= c.MaxHosts { log.Warningf("Only scanning max-hosts=%d out of %d args given", c.MaxHosts, len(args)) args = args[:c.MaxHosts] } else if c.CSVFile != "" { args, err = parseCSV(args, c.CSVFile, c.MaxHosts) if err != nil { return } } ctx := newContext(c, c.NumWorkers) // Execute for each HOST argument given for len(args) > 0 { var host string host, args, err = cli.PopFirstArgument(args) if err != nil { return } ctx.hosts <- host } close(ctx.hosts) ctx.Wait() } return }
// registerHandlers instantiates various handlers and associate them to corresponding endpoints. func registerHandlers() { for path, getHandler := range endpoints { log.Debugf("getHandler for %s", path) if handler, err := getHandler(); err != nil { log.Warningf("endpoint '%s' is disabled: %v", path, err) } else { if path, handler, err = wrapHandler(path, handler, err); err != nil { log.Warningf("endpoint '%s' is disabled by wrapper: %v", path, err) } else { log.Infof("endpoint '%s' is enabled", path) http.Handle(path, handler) } } } log.Info("Handler set up complete.") }
func (ctx *context) copyResults(timeout time.Duration) map[string]FamilyResult { var timedOut bool done := make(chan bool, 1) results := make(map[string]FamilyResult) go func() { for result := range ctx.resultChan { if timedOut { log.Debugf("Received result after timeout: %v", result) continue } if results[result.Family] == nil { results[result.Family] = make(FamilyResult) } results[result.Family][result.Scanner] = result.ScannerResult } done <- true }() select { case <-done: case <-time.After(timeout): timedOut = true log.Warningf("Scan timed out after %v", timeout) } return results }
// RunScans iterates over AllScans, running scans matching the family and scanner // regular expressions. func (fs FamilySet) RunScans(host, family, scanner string, dur time.Duration) (map[string]FamilyResult, error) { if _, _, err := net.SplitHostPort(host); err != nil { host = net.JoinHostPort(host, "443") } familyRegexp, err := regexp.Compile(family) if err != nil { return nil, err } scannerRegexp, err := regexp.Compile(scanner) if err != nil { return nil, err } results := make(chan map[string]FamilyResult) timeout := make(chan bool) if dur > 0 { go startTimer(dur, timeout) } familyResults := make(map[string]FamilyResult) go func() { for familyName, family := range fs { if familyRegexp.MatchString(familyName) { scannerResults := make(map[string]ScannerResult) for scannerName, scanner := range family.Scanners { if scannerRegexp.MatchString(scannerName) { grade, output, err := scanner.Scan(host) result := ScannerResult{ Grade: grade.String(), Output: output, } if err != nil { result.Error = err.Error() } scannerResults[scannerName] = result } } familyResults[familyName] = scannerResults } } results <- familyResults }() select { case <-timeout: log.Warningf("scan: %s timed out after %v", host, dur) return nil, nil case res := <-results: return res, nil } }
// Handle responds to requests for the CA to generate a new private // key and certificate request on behalf of the client. The format for // these requests is documented in the API documentation. func (g *Handler) Handle(w http.ResponseWriter, r *http.Request) error { log.Info("request for CSR") body, err := ioutil.ReadAll(r.Body) if err != nil { log.Warningf("failed to read request body: %v", err) return errors.NewBadRequest(err) } r.Body.Close() req := new(csr.CertificateRequest) req.KeyRequest = csr.NewBasicKeyRequest() err = json.Unmarshal(body, req) if err != nil { log.Warningf("failed to unmarshal request: %v", err) return errors.NewBadRequest(err) } if req.CA != nil { log.Warningf("request received with CA section") return errors.NewBadRequestString("ca section only permitted in initca") } csr, key, err := g.generator.ProcessRequest(req) if err != nil { log.Warningf("failed to process CSR: %v", err) // The validator returns a *cfssl/errors.HttpError return err } sum, err := computeSum(csr) if err != nil { return errors.NewBadRequest(err) } // Both key and csr are returned PEM-encoded. response := api.NewSuccessResponse(&CertRequest{ Key: string(key), CSR: string(csr), Sums: map[string]Sum{"certificate_request": sum}, }) w.Header().Set("Content-Type", "application/json") enc := json.NewEncoder(w) err = enc.Encode(response) return err }
// We can't handle LDAP certificates, so this checks to see if the // URL string points to an LDAP resource so that we can ignore it. func ldapURL(url string) bool { u, err := neturl.Parse(url) if err != nil { log.Warningf("error parsing url %s: %v", url, err) return false } if u.Scheme == "ldap" { return true } return false }
// registerHandlers instantiates various handlers and associate them to corresponding endpoints. func registerHandlers() { for path, getHandler := range v1Endpoints { path = "/api/v1/cfssl/" + path log.Infof("Setting up '%s' endpoint", path) if handler, err := getHandler(); err != nil { log.Warningf("endpoint '%s' is disabled: %v", path, err) } else { http.Handle(path, handler) } } for path, getHandler := range staticEndpoints { log.Infof("Setting up '%s' endpoint", path) if handler, err := getHandler(); err != nil { log.Warningf("endpoint '%s' is disabled: %v", path, err) } else { http.Handle(path, handler) } } log.Info("Handler set up complete.") }
func (h *BundlerHandler) Handle(w http.ResponseWriter, r *http.Request) error { blob, matched, err := processRequestOneOf(r, [][]string{ {"domain"}, {"certificate"}, }) if err != nil { log.Warningf("invalid request: %v", err) return err } var result *bundler.Bundle switch matched[0] { case "domain": bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"]) if err != nil { log.Warningf("couldn't bundle from remote: %v", err) return errors.NewBadRequest(err) } result = bundle case "certificate": flavor := blob["flavor"] var bf bundler.BundleFlavor = bundler.Ubiquitous if flavor != "" { bf = bundler.BundleFlavor(flavor) } bundle, err := h.bundler.BundleFromPEM([]byte(blob["certificate"]), []byte(blob["private_key"]), bf) if err != nil { log.Warning("bad PEM certifcate or private key") return errors.NewBadRequest(err) } log.Infof("request for flavour %v", flavor) result = bundle } response := newSuccessResponse(result) w.Header().Set("Content-Type", "application/json") enc := json.NewEncoder(w) err = enc.Encode(response) return err }
// registerHandlers instantiates various handlers and associate them to corresponding endpoints. func registerHandlers() { for path, getHandler := range endpoints { path = v1APIPath(path) log.Infof("Setting up '%s' endpoint", path) if handler, err := getHandler(); err != nil { log.Warningf("endpoint '%s' is disabled: %v", path, err) } else { http.Handle(path, handler) } } log.Info("Handler set up complete.") }
func (keys *defaultKeystore) Get(op *gokeyless.Operation) (priv crypto.Signer, ok bool) { keys.RLock() defer keys.RUnlock() ski := op.SKI if ski.Valid() { priv, ok = keys.skis[ski] } else { if !ok { log.Debug("Couldn't look up key based on SKI, trying Digest.") if ski, ok = keys.digests[op.Digest]; ok { priv, ok = keys.skis[ski] } } if !ok { log.Debug("Couldn't look up key based on Digest, trying SNI.") if ski, ok = keys.snis[op.SNI]; ok { priv, ok = keys.skis[ski] } } if !ok { if op.ServerIP != nil { log.Debug("Couldn't look up key based on SNI, trying Server IP.") if ski, ok = keys.serverIPs[op.ServerIP.String()]; ok { priv, ok = keys.skis[ski] } } } if !ok { if op.ClientIP != nil { log.Debug("Couldn't look up key based on Server IP, trying Client IP.") if ski, ok = keys.clientIPs[op.ClientIP.String()]; ok { priv, ok = keys.skis[ski] } } } } if !ok { log.Infof("Couldn't look up key for %s.", op) } else if len(keys.validAKIs[ski]) > 0 && !keys.validAKIs[ski].Contains(op.AKI) { log.Warningf("Attempt to access key with invalid AKI: %s", op.AKI) return nil, false } return }
// Handle responds to requests for the CA to sign the certificate request // present in the "certificate_request" parameter for the host named // in the "hostname" parameter. The certificate should be PEM-encoded. If // provided, subject information from the "subject" parameter will be used // in place of the subject information from the CSR. func (h *SignHandler) Handle(w http.ResponseWriter, r *http.Request) error { log.Info("signature request received") body, err := ioutil.ReadAll(r.Body) if err != nil { return err } r.Body.Close() var req signer.SignRequest err = json.Unmarshal(body, &req) if err != nil { return err } if len(req.Hosts) == 0 { return errors.NewBadRequestString("missing paratmeter 'hosts'") } if req.Request == "" { return errors.NewBadRequestString("missing parameter 'certificate_request'") } var cert []byte var profile *config.SigningProfile policy := h.signer.Policy() if policy != nil && policy.Profiles != nil && req.Profile != "" { profile = policy.Profiles[req.Profile] } if profile == nil && policy != nil { profile = policy.Default } if profile.Provider != nil { log.Error("profile requires authentication") return errors.NewBadRequestString("authentication required") } cert, err = h.signer.Sign(req) if err != nil { log.Warningf("failed to sign request: %v", err) return err } result := map[string]string{"certificate": string(cert)} log.Info("wrote response") return api.SendResponse(w, result) }
// scanHandler is an HTTP handler that accepts GET parameters for host (required) // family and scanner, and uses these to perform scans, returning a JSON blob result. func scanHandler(w http.ResponseWriter, r *http.Request) error { if err := r.ParseForm(); err != nil { log.Warningf("failed to parse body: %v", err) return errors.NewBadRequest(err) } family := r.Form.Get("family") scanner := r.Form.Get("scanner") ip := r.Form.Get("ip") timeoutStr := r.Form.Get("timeout") var timeout time.Duration var err error if timeoutStr != "" { if timeout, err = time.ParseDuration(timeoutStr); err != nil { return errors.NewBadRequest(err) } if timeout < time.Second || timeout > 5*time.Minute { return errors.NewBadRequestString("invalid timeout given") } } else { timeout = time.Minute } host := r.Form.Get("host") if host == "" { log.Warningf("no host given") return errors.NewBadRequestString("no host given") } results, err := scan.Default.RunScans(host, ip, family, scanner, timeout) if err != nil { return errors.NewBadRequest(err) } return json.NewEncoder(w).Encode(api.NewSuccessResponse(results)) }
// ProcessRequest validates and processes the incoming request. It is // a wrapper around a validator and the ParseRequest function. func (g *Generator) ProcessRequest(req *CertificateRequest) (csr, key []byte, err error) { log.Info("generate received request") err = g.Validator(req) if err != nil { log.Warningf("invalid request: %v", err) return } csr, key, err = ParseRequest(req) if err != nil { return nil, nil, err } return }
// warnSkippedSettings prints a log warning message about skipped settings // in a SigningProfile, usually due to remote signer. func (p *Signing) warnSkippedSettings() { const warningMessage = `The configuration value by "usages", "issuer_urls", "ocsp_url", "crl_url", "ca_constraint", "expiry", "backdate", "not_before", "not_after", "cert_store" and "ct_log_servers" are skipped` if p == nil { return } if p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "" { log.Warning("default profile points to a remote signer: ", warningMessage) } for name, profile := range p.Profiles { if profile.RemoteName != "" || profile.AuthRemote.RemoteName != "" { log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage) } } }
// Handle responds to requests for the CA to sign the certificate // present in the "cert" parameter for the host named in the "hostname" // parameter. The certificate should be PEM-encoded. func (h *SignHandler) Handle(w http.ResponseWriter, r *http.Request) error { log.Info("signature request received") blob, err := processRequestRequired(r, []string{"hostname", "certificate_request"}) if err != nil { return err } certificate := []byte(blob["certificate_request"]) cert, err := h.signer.Sign(blob["hostname"], certificate, blob["profile"]) if err != nil { log.Warningf("failed to sign request: %v", err) return errors.NewBadRequest(err) } result := map[string]string{"certificate": string(cert)} log.Info("wrote response") return sendResponse(w, result) }
func main() { var s *server.Server if initToken != "" { s = initializeServer() } else { s, err := server.NewServerFromFile(certFile, keyFile, caFile, net.JoinHostPort("", port), net.JoinHostPort("", metricsPort)) if err != nil { log.Warningf("Could not create server. Run with `gokeyless -init-token=XXX` to get %s and %s", keyFile, certFile) log.Fatal(err) } if err := s.LoadKeysFromDir(keyDir, LoadKey); err != nil { log.Fatal(err) } // Start server in background, then listen for SIGHUPs to reload keys. go func() { log.Fatal(s.ListenAndServe()) }() } if pidFile != "" { if f, err := os.Create(pidFile); err != nil { log.Errorf("error creating pid file: %v", err) } else { fmt.Fprintf(f, "%d", os.Getpid()) f.Close() } } c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGHUP) for { select { case <-c: log.Info("Received SIGHUP, reloading keys...") if err := s.LoadKeysFromDir(keyDir, LoadKey); err != nil { log.Fatal(err) } } } }