Example #1
0
func fail(w http.ResponseWriter, req *http.Request, status, code int, msg, ad string) {
	incErrors()

	if ad != "" {
		ad = " (" + ad + ")"
	}
	log.Errorf("[HTTP %d] %d - %s%s", status, code, msg, ad)

	dumpReq, err := httputil.DumpRequest(req, true)
	if err != nil {
		fmt.Printf("%v#v\n", req)
	} else {
		fmt.Printf("%s\n", dumpReq)
	}

	res := api.NewErrorResponse(msg, code)
	w.WriteHeader(status)
	jenc := json.NewEncoder(w)
	jenc.Encode(res)
}
Example #2
0
func (h *signHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if atomic.LoadUint32(h.flaky) == 1 {
		w.WriteHeader(http.StatusInternalServerError)
	}

	// Check client authentication via mutual TLS.
	if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 {
		cfsslErr := cfsslerrors.New(cfsslerrors.APIClientError, cfsslerrors.AuthenticationFailure)
		errResponse := api.NewErrorResponse("must authenticate sign request with mutual TLS", cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	clientSub := r.TLS.PeerCertificates[0].Subject

	// The client certificate OU should be for a swarm manager.
	if len(clientSub.OrganizationalUnit) == 0 || clientSub.OrganizationalUnit[0] != ca.ManagerRole {
		cfsslErr := cfsslerrors.New(cfsslerrors.APIClientError, cfsslerrors.AuthenticationFailure)
		errResponse := api.NewErrorResponse(fmt.Sprintf("client certificate OU must be %q", ca.ManagerRole), cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	// The client certificate must have an Org.
	if len(clientSub.Organization) == 0 {
		cfsslErr := cfsslerrors.New(cfsslerrors.APIClientError, cfsslerrors.AuthenticationFailure)
		errResponse := api.NewErrorResponse("client certificate must have an Organization", cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}
	clientOrg := clientSub.Organization[0]

	// Decode the certificate signing request.
	var signReq signer.SignRequest
	if err := json.NewDecoder(r.Body).Decode(&signReq); err != nil {
		cfsslErr := cfsslerrors.New(cfsslerrors.APIClientError, cfsslerrors.JSONError)
		errResponse := api.NewErrorResponse(fmt.Sprintf("unable to decode sign request: %s", err), cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	// The signReq should have additional subject info.
	reqSub := signReq.Subject
	if reqSub == nil {
		cfsslErr := cfsslerrors.New(cfsslerrors.CSRError, cfsslerrors.BadRequest)
		errResponse := api.NewErrorResponse("sign request must contain a subject field", cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	// The client's Org should match the Org in the sign request subject.
	if len(reqSub.Name().Organization) == 0 || reqSub.Name().Organization[0] != clientOrg {
		cfsslErr := cfsslerrors.New(cfsslerrors.CSRError, cfsslerrors.BadRequest)
		errResponse := api.NewErrorResponse("sign request subject org does not match client certificate org", cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	// Finally, sign the requested certificate.
	certPEM, err := h.rootCA.Signer.Sign(signReq)
	if err != nil {
		cfsslErr := cfsslerrors.New(cfsslerrors.APIClientError, cfsslerrors.ServerRequestFailed)
		errResponse := api.NewErrorResponse(fmt.Sprintf("unable to sign requested certificate: %s", err), cfsslErr.ErrorCode)
		json.NewEncoder(w).Encode(errResponse)
		return
	}

	result := map[string]string{
		"certificate": string(certPEM),
	}

	// Increment the number of certs issued.
	atomic.AddUint64(h.numIssued, 1)

	// Return a successful JSON response.
	json.NewEncoder(w).Encode(api.NewSuccessResponse(result))
}