Exemplo n.º 1
0
func gencertMain(args []string, c cli.Config) error {
	if c.RenewCA {
		log.Infof("re-generate a CA certificate from CA cert and key")
		cert, err := initca.RenewFromPEM(c.CAFile, c.CAKeyFile)
		if err != nil {
			log.Errorf("%v\n", err)
			return err
		}
		cli.PrintCert(nil, nil, cert)
		return nil
	}

	csrJSONFile, args, err := cli.PopFirstArgument(args)
	if err != nil {
		return err
	}

	csrJSONFileBytes, err := cli.ReadStdin(csrJSONFile)
	if err != nil {
		return err
	}

	req := csr.CertificateRequest{
		KeyRequest: csr.NewBasicKeyRequest(),
	}
	err = json.Unmarshal(csrJSONFileBytes, &req)
	if err != nil {
		return err
	}
	if c.CNOverride != "" {
		req.CN = c.CNOverride
	}
	switch {
	case c.IsCA:
		var key, csrPEM, cert []byte
		if c.CAKeyFile != "" {
			log.Infof("re-generate a CA certificate from CSR and CA key")
			cert, csrPEM, err = initca.NewFromPEM(&req, c.CAKeyFile)
			if err != nil {
				log.Errorf("%v\n", err)
				return err
			}
		} else {
			log.Infof("generating a new CA key and certificate from CSR")
			cert, csrPEM, key, err = initca.New(&req)
			if err != nil {
				return err
			}

		}
		cli.PrintCert(key, csrPEM, cert)

	default:
		if req.CA != nil {
			err = errors.New("ca section only permitted in initca")
			return err
		}

		if c.Hostname != "" {
			req.Hosts = signer.SplitHosts(c.Hostname)
		}
		// Remote can be forced on the command line or in the config
		if c.Remote == "" && c.CFG == nil {
			if c.CAFile == "" {
				log.Error("need a CA certificate (provide one with -ca)")
				return nil
			}

			if c.CAKeyFile == "" {
				log.Error("need a CA key (provide one with -ca-key)")
				return nil
			}
		}

		var key, csrBytes []byte
		g := &csr.Generator{Validator: genkey.Validator}
		csrBytes, key, err = g.ProcessRequest(&req)
		if err != nil {
			key = nil
			return err
		}

		s, err := sign.SignerFromConfig(c)
		if err != nil {
			return err
		}

		var cert []byte
		signReq := signer.SignRequest{
			Request: string(csrBytes),
			Hosts:   signer.SplitHosts(c.Hostname),
			Profile: c.Profile,
			Label:   c.Label,
		}

		if c.CRL != "" {
			signReq.CRLOverride = c.CRL
		}
		cert, err = s.Sign(signReq)
		if err != nil {
			return err
		}

		// This follows the Baseline Requirements for the Issuance and
		// Management of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser
		// Forum (https://cabforum.org). Specifically, section 10.2.3 ("Information
		// Requirements"), states:
		//
		// "Applicant information MUST include, but not be limited to, at least one
		// Fully-Qualified Domain Name or IP address to be included in the Certificate’s
		// SubjectAltName extension."
		if len(signReq.Hosts) == 0 && len(req.Hosts) == 0 {
			log.Warning(generator.CSRNoHostMessage)
		}

		cli.PrintCert(key, csrBytes, cert)
	}
	return nil
}
Exemplo n.º 2
0
func dispatchRequest(w http.ResponseWriter, req *http.Request) {
	incRequests()

	if req.Method != "POST" {
		fail(w, req, http.StatusMethodNotAllowed, 1, "only POST is permitted", "")
		return
	}

	body, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, err.Error(), "while reading request body")
		return
	}
	defer req.Body.Close()

	var authReq auth.AuthenticatedRequest
	err = json.Unmarshal(body, &authReq)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshaling request body")
		return
	}

	var sigRequest signer.SignRequest
	err = json.Unmarshal(authReq.Request, &sigRequest)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, err.Error(), "while unmarshalling authenticated request")
		return
	}

	if sigRequest.Label == "" {
		sigRequest.Label = defaultLabel
	}

	s, ok := signers[sigRequest.Label]
	if !ok {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "request is for non-existent label "+sigRequest.Label)
		return
	}

	stats.Requests[sigRequest.Label].Counter.Inc(1)
	stats.Requests[sigRequest.Label].Rate.Mark(1)

	// Sanity checks to ensure that we have a valid policy. This
	// should have been checked in NewAuthSignHandler.
	policy := s.Policy()
	if policy == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid policy", "signer was initialised without a signing policy")
		return
	}
	profile := policy.Default

	if policy.Profiles != nil && sigRequest.Profile != "" {
		profile = policy.Profiles[sigRequest.Profile]
		if profile == nil {
			fail(w, req, http.StatusBadRequest, 1, "invalid profile", "failed to look up profile with name: "+sigRequest.Profile)
			return
		}
	}

	if profile == nil {
		fail(w, req, http.StatusInternalServerError, 1, "invalid profile", "signer was initialised without any valid profiles")
		return
	}

	if profile.Provider == nil {
		fail(w, req, http.StatusUnauthorized, 1, "authorisation required", "received unauthenticated request")
		return
	}

	if !profile.Provider.Verify(&authReq) {
		fail(w, req, http.StatusBadRequest, 1, "invalid token", "received authenticated request with invalid token")
		return
	}

	if sigRequest.Request == "" {
		fail(w, req, http.StatusBadRequest, 1, "invalid request", "empty request")
		return
	}

	cert, err := s.Sign(sigRequest)
	if err != nil {
		fail(w, req, http.StatusBadRequest, 1, "bad request", "signature failed: "+err.Error())
		return
	}

	x509Cert, err := helpers.ParseCertificatePEM(cert)
	if err != nil {
		fail(w, req, http.StatusInternalServerError, 1, "bad certificate", err.Error())
	}

	log.Infof("signature: requester=%s, label=%s, profile=%s, serialno=%s",
		req.RemoteAddr, sigRequest.Label, sigRequest.Profile, x509Cert.SerialNumber)

	res := api.NewSuccessResponse(&SignatureResponse{Certificate: string(cert)})
	jenc := json.NewEncoder(w)
	err = jenc.Encode(res)
	if err != nil {
		log.Errorf("error writing response: %v", err)
	}
}