Add linting, test coverage, code of conduct, lint fixes. (#215)
* WFE: remove unused vars * db: format file * ca: format file * wfe: fix misspells * wfe: remove unnecessary []byte conversion. * db: prefer ++ for incrementing by 1 * va: use challtestsrv's exported IdPeAcmeIdentifier. * wfe: remove throwaway resultUrl var * wfe: rename writeJsonResponse -> writeJSONResponse * ci: add golangci-lint and test coverage collection * repo: add CODE_OF_CONDUCT * README: Add standard badges * ci: use go mod download hack * ci: install goveralls tooling * ci: fix linter exclude typo
This commit is contained in:
parent
f5c27ebdc3
commit
08b2d7a611
|
|
@ -0,0 +1,32 @@
|
|||
linters-settings:
|
||||
gocyclo:
|
||||
min-complexity: 25
|
||||
govet:
|
||||
check-shadowing: false
|
||||
misspell:
|
||||
locale: "US"
|
||||
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- stylecheck
|
||||
- gosec
|
||||
- dupl
|
||||
- maligned
|
||||
- depguard
|
||||
- lll
|
||||
- prealloc
|
||||
- scopelint
|
||||
- gocritic
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
|
||||
issues:
|
||||
exclude:
|
||||
# The following excludes are considered false-positives/known-OK.
|
||||
# ca/ca.go:
|
||||
- "type name will be used as ca.CAImpl by other packages, and that stutters; consider calling this Impl"
|
||||
# va/va.go:
|
||||
- "type name will be used as va.VAImpl by other packages, and that stutters; consider calling this Impl"
|
||||
# wfe/wfe.go: L1647 and L1878
|
||||
- "if` block ends with a `return` statement, so drop this `else` and outdent its block"
|
||||
17
.travis.yml
17
.travis.yml
|
|
@ -27,6 +27,13 @@ before_install:
|
|||
# Override the base install phase so that the project can be installed using
|
||||
# `-mod=vendor` to use the vendored dependencies
|
||||
install:
|
||||
# Install `golangci-lint` using their installer script
|
||||
- curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.15.0
|
||||
# Install `cover` and `goveralls` without `GO111MODULE` enabled so that we
|
||||
# don't download ct-woodpecker dependencies and just put the tools in our
|
||||
# gobin.
|
||||
- GO111MODULE=off go get golang.org/x/tools/cmd/cover
|
||||
- GO111MODULE=off go get github.com/mattn/goveralls
|
||||
- go install -v -mod=vendor ./...
|
||||
|
||||
before_script:
|
||||
|
|
@ -35,7 +42,15 @@ before_script:
|
|||
- until </dev/tcp/localhost/14000 ; do sleep 0.1 ; done
|
||||
|
||||
script:
|
||||
- go vet -mod=vendor ./...
|
||||
- go mod download
|
||||
# Vet Go source code using the linter config (see .golang-ci.yml)
|
||||
- golangci-lint run
|
||||
# Run project unit tests (with the race detector enabled and atomic
|
||||
# coverage profile collection)
|
||||
- go test -mod=vendor -v -race -covermode=atomic -coverprofile=coverage.out ./...
|
||||
# Upload collected coverage profile to goveralls
|
||||
- goveralls -coverprofile=coverage.out -service=travis-ci
|
||||
# Perform a test issuance with chisel2.py
|
||||
- REQUESTS_CA_BUNDLE=./test/certs/pebble.minica.pem python ./test/chisel2.py example.letsencrypt.org elpmaxe.letsencrypt.org
|
||||
|
||||
deploy:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
The contributor code of conduct is available for reference [on the community forum](https://community.letsencrypt.org/guidelines).
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
# Pebble
|
||||
|
||||
[](https://travis-ci.org/letsencrypt/pebble)
|
||||
[](https://coveralls.io/github/letsencrypt/pebble?branch=cpu-goveralls)
|
||||
[](https://goreportcard.com/report/github.com/letsencrypt/pebble)
|
||||
[](https://golangci.com/r/github.com/letsencrypt/pebble)
|
||||
|
||||
A miniature version of [Boulder](https://github.com/letsencrypt/boulder), Pebble
|
||||
is a small [ACME](https://github.com/ietf-wg-acme/acme) test server not suited
|
||||
|
|
|
|||
4
ca/ca.go
4
ca/ca.go
|
|
@ -73,7 +73,7 @@ func (ca *CAImpl) makeRootCert(
|
|||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
IsCA: true,
|
||||
}
|
||||
|
||||
var signerKey crypto.Signer
|
||||
|
|
@ -182,7 +182,7 @@ func (ca *CAImpl) newCertificate(domains []string, key crypto.PublicKey, account
|
|||
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: false,
|
||||
IsCA: false,
|
||||
}
|
||||
der, err := x509.CreateCertificate(rand.Reader, template, issuer.cert.Cert, key, issuer.key)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ func (e ExistingAccountError) Error() string {
|
|||
return fmt.Sprintf("New public key is already in use by account %s", e.MatchingAccount.ID)
|
||||
}
|
||||
|
||||
|
||||
// Pebble keeps all of its various objects (accounts, orders, etc)
|
||||
// in-memory, not persisted anywhere. MemoryStore implements this in-memory
|
||||
// "database"
|
||||
|
|
@ -49,19 +48,19 @@ type MemoryStore struct {
|
|||
|
||||
challengesByID map[string]*core.Challenge
|
||||
|
||||
certificatesByID map[string]*core.Certificate
|
||||
certificatesByID map[string]*core.Certificate
|
||||
revokedCertificatesByID map[string]*core.Certificate
|
||||
}
|
||||
|
||||
func NewMemoryStore(clk clock.Clock) *MemoryStore {
|
||||
return &MemoryStore{
|
||||
clk: clk,
|
||||
accountIDCounter: 1,
|
||||
accountsByID: make(map[string]*core.Account),
|
||||
accountsByKeyID: make(map[string]*core.Account),
|
||||
ordersByID: make(map[string]*core.Order),
|
||||
authorizationsByID: make(map[string]*core.Authorization),
|
||||
challengesByID: make(map[string]*core.Challenge),
|
||||
clk: clk,
|
||||
accountIDCounter: 1,
|
||||
accountsByID: make(map[string]*core.Account),
|
||||
accountsByKeyID: make(map[string]*core.Account),
|
||||
ordersByID: make(map[string]*core.Order),
|
||||
authorizationsByID: make(map[string]*core.Authorization),
|
||||
challengesByID: make(map[string]*core.Challenge),
|
||||
certificatesByID: make(map[string]*core.Certificate),
|
||||
revokedCertificatesByID: make(map[string]*core.Certificate),
|
||||
}
|
||||
|
|
@ -107,7 +106,7 @@ func (m *MemoryStore) AddAccount(acct *core.Account) (int, error) {
|
|||
defer m.Unlock()
|
||||
|
||||
acctID := strconv.Itoa(m.accountIDCounter)
|
||||
m.accountIDCounter += 1
|
||||
m.accountIDCounter++
|
||||
|
||||
if acct.Key == nil {
|
||||
return 0, fmt.Errorf("account must not have a nil Key")
|
||||
|
|
|
|||
7
va/va.go
7
va/va.go
|
|
@ -22,6 +22,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/challtestsrv"
|
||||
"github.com/letsencrypt/pebble/acme"
|
||||
"github.com/letsencrypt/pebble/core"
|
||||
)
|
||||
|
|
@ -69,10 +70,6 @@ const (
|
|||
noValidateEnvVar = "PEBBLE_VA_ALWAYS_VALID"
|
||||
)
|
||||
|
||||
// This is the identifier defined in draft-04 and newer, as registered with IANA
|
||||
// (https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-04#page-4)
|
||||
var IdPeAcmeIdentifier = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 31}
|
||||
|
||||
func userAgent() string {
|
||||
return fmt.Sprintf(
|
||||
"%s (%s; %s)",
|
||||
|
|
@ -390,7 +387,7 @@ func (va VAImpl) validateTLSALPN01(task *vaTask) *core.ValidationRecord {
|
|||
h := sha256.Sum256([]byte(expectedKeyAuthorization))
|
||||
for _, ext := range leafCert.Extensions {
|
||||
if ext.Critical {
|
||||
hasAcmeIdentifier := IdPeAcmeIdentifier.Equal(ext.Id)
|
||||
hasAcmeIdentifier := challtestsrv.IdPeAcmeIdentifier.Equal(ext.Id)
|
||||
if hasAcmeIdentifier {
|
||||
var extValue []byte
|
||||
if _, err := asn1.Unmarshal(ext.Value, &extValue); err != nil {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ func keyDigest(key crypto.PublicKey) (string, error) {
|
|||
func keyDigestEquals(j, k crypto.PublicKey) bool {
|
||||
digestJ, errJ := keyDigest(j)
|
||||
digestK, errK := keyDigest(k)
|
||||
// Keys that don't have a valid digest (due to marshalling problems)
|
||||
// Keys that don't have a valid digest (due to marshaling problems)
|
||||
// are never equal. So, e.g. nil keys are not equal.
|
||||
if errJ != nil || errK != nil {
|
||||
return false
|
||||
|
|
|
|||
125
wfe/wfe.go
125
wfe/wfe.go
|
|
@ -16,7 +16,6 @@ import (
|
|||
"net/mail"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -86,22 +85,15 @@ const (
|
|||
aACompromiseRevocationReason = 10
|
||||
)
|
||||
|
||||
type requestEvent struct {
|
||||
ClientAddr string `json:",omitempty"`
|
||||
Endpoint string `json:",omitempty"`
|
||||
Method string `json:",omitempty"`
|
||||
UserAgent string `json:",omitempty"`
|
||||
}
|
||||
type wfeHandlerFunc func(context.Context, http.ResponseWriter, *http.Request)
|
||||
|
||||
type wfeHandlerFunc func(context.Context, *requestEvent, http.ResponseWriter, *http.Request)
|
||||
|
||||
func (f wfeHandlerFunc) ServeHTTP(e *requestEvent, w http.ResponseWriter, r *http.Request) {
|
||||
func (f wfeHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := context.TODO()
|
||||
f(ctx, e, w, r)
|
||||
f(ctx, w, r)
|
||||
}
|
||||
|
||||
type wfeHandler interface {
|
||||
ServeHTTP(e *requestEvent, w http.ResponseWriter, r *http.Request)
|
||||
ServeHTTP(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
type topHandler struct {
|
||||
|
|
@ -109,14 +101,7 @@ type topHandler struct {
|
|||
}
|
||||
|
||||
func (th *topHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO(@cpu): consider restoring X-Forwarded-For handling for ClientAddr
|
||||
rEvent := &requestEvent{
|
||||
ClientAddr: r.RemoteAddr,
|
||||
Method: r.Method,
|
||||
UserAgent: r.Header.Get("User-Agent"),
|
||||
}
|
||||
|
||||
th.wfe.ServeHTTP(rEvent, w, r)
|
||||
th.wfe.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
type WebFrontEndImpl struct {
|
||||
|
|
@ -194,7 +179,7 @@ func (wfe *WebFrontEndImpl) HandleFunc(
|
|||
methodsStr := strings.Join(methods, ", ")
|
||||
defaultHandler := http.StripPrefix(pattern,
|
||||
&topHandler{
|
||||
wfe: wfeHandlerFunc(func(ctx context.Context, logEvent *requestEvent, response http.ResponseWriter, request *http.Request) {
|
||||
wfe: wfeHandlerFunc(func(ctx context.Context, response http.ResponseWriter, request *http.Request) {
|
||||
// Modern ACME only sends a Replay-Nonce in responses to GET/HEAD
|
||||
// requests to the dedicated newNonce endpoint, or in replies to POST
|
||||
// requests that consumed a nonce.
|
||||
|
|
@ -210,11 +195,6 @@ func (wfe *WebFrontEndImpl) HandleFunc(
|
|||
response.Header().Add("Link", link(directoryURL, "index"))
|
||||
}
|
||||
|
||||
logEvent.Endpoint = pattern
|
||||
if request.URL != nil {
|
||||
logEvent.Endpoint = path.Join(logEvent.Endpoint, request.URL.Path)
|
||||
}
|
||||
|
||||
addNoCacheHeader(response)
|
||||
|
||||
if !methodsMap[request.Method] {
|
||||
|
|
@ -223,12 +203,12 @@ func (wfe *WebFrontEndImpl) HandleFunc(
|
|||
return
|
||||
}
|
||||
|
||||
wfe.log.Printf("%s %s -> calling handler()\n", request.Method, logEvent.Endpoint)
|
||||
wfe.log.Printf("%s %s -> calling handler()\n", request.Method, pattern)
|
||||
|
||||
// TODO(@cpu): Configurable request timeout
|
||||
timeout := 1 * time.Minute
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
handler(ctx, logEvent, response, request)
|
||||
handler(ctx, response, request)
|
||||
cancel()
|
||||
},
|
||||
)})
|
||||
|
|
@ -248,7 +228,6 @@ func (wfe *WebFrontEndImpl) sendError(prob *acme.ProblemDetails, response http.R
|
|||
|
||||
func (wfe *WebFrontEndImpl) RootCert(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
|
|
@ -288,7 +267,6 @@ func (wfe *WebFrontEndImpl) Handler() http.Handler {
|
|||
|
||||
func (wfe *WebFrontEndImpl) Directory(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
|
|
@ -324,7 +302,7 @@ func (wfe *WebFrontEndImpl) relativeDirectory(request *http.Request, directory m
|
|||
}
|
||||
|
||||
directoryJSON, err := marshalIndent(relativeDir)
|
||||
// This should never happen since we are just marshalling known strings
|
||||
// This should never happen since we are just marshaling known strings
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -352,13 +330,11 @@ func (wfe *WebFrontEndImpl) relativeEndpoint(request *http.Request, endpoint str
|
|||
host = "localhost"
|
||||
}
|
||||
|
||||
resultUrl := url.URL{Scheme: proto, Host: host, Path: endpoint}
|
||||
return resultUrl.String()
|
||||
return (&url.URL{Scheme: proto, Host: host, Path: endpoint}).String()
|
||||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) Nonce(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
statusCode := http.StatusNoContent
|
||||
|
|
@ -416,7 +392,7 @@ func (wfe *WebFrontEndImpl) parseJWS(body string) (*jose.JSONWebSignature, error
|
|||
|
||||
// jwsAuthType represents whether a given POST request is authenticated using
|
||||
// a JWS with an embedded JWK (new-account, possibly revoke-cert) or an
|
||||
// embeded Key ID or an unsupported/unknown auth type.
|
||||
// embedded Key ID or an unsupported/unknown auth type.
|
||||
type jwsAuthType int
|
||||
|
||||
const (
|
||||
|
|
@ -550,8 +526,6 @@ type authenticatedPOST struct {
|
|||
// presently handle the `regCheck` parameter or do any lookups for existing
|
||||
// accounts.
|
||||
func (wfe *WebFrontEndImpl) verifyPOST(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
request *http.Request,
|
||||
kx keyExtractor) (*authenticatedPOST, *acme.ProblemDetails) {
|
||||
|
||||
|
|
@ -596,7 +570,7 @@ func (wfe *WebFrontEndImpl) verifyJWSSignatureAndAlgorithm(
|
|||
if err != nil {
|
||||
return nil, acme.MalformedProblem(fmt.Sprintf("JWS verification error: %s", err))
|
||||
}
|
||||
return []byte(payload), nil
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
// Extracts URL header parameter from parsed JWS.
|
||||
|
|
@ -716,10 +690,9 @@ func (wfe *WebFrontEndImpl) verifyContacts(acct acme.Account) *acme.ProblemDetai
|
|||
|
||||
func (wfe *WebFrontEndImpl) UpdateAccount(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -758,7 +731,7 @@ func (wfe *WebFrontEndImpl) UpdateAccount(
|
|||
wfe.sendError(acme.MalformedProblem("Use POST-as-GET to retrieve account data instead of doing an empty update"), response)
|
||||
return
|
||||
}
|
||||
err := wfe.writeJsonResponse(response, http.StatusOK, existingAcct)
|
||||
err := wfe.writeJSONResponse(response, http.StatusOK, existingAcct)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling account"), response)
|
||||
return
|
||||
|
|
@ -802,7 +775,7 @@ func (wfe *WebFrontEndImpl) UpdateAccount(
|
|||
return
|
||||
}
|
||||
|
||||
err = wfe.writeJsonResponse(response, http.StatusOK, newAcct)
|
||||
err = wfe.writeJSONResponse(response, http.StatusOK, newAcct)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling account"), response)
|
||||
return
|
||||
|
|
@ -851,11 +824,10 @@ func (wfe *WebFrontEndImpl) verifyKeyRollover(
|
|||
|
||||
func (wfe *WebFrontEndImpl) KeyRollover(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
// Extract and parse outer JWS, and retrieve account
|
||||
outerPostData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
outerPostData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -922,14 +894,13 @@ func (wfe *WebFrontEndImpl) KeyRollover(
|
|||
|
||||
func (wfe *WebFrontEndImpl) NewAccount(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
// We use extractJWK rather than lookupJWK here because the account is not yet
|
||||
// created, so the user provides the full key in a JWS header rather than
|
||||
// referring to an existing key.
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.extractJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.extractJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -961,7 +932,7 @@ func (wfe *WebFrontEndImpl) NewAccount(
|
|||
// the account and a 200 OK response
|
||||
acctURL := wfe.relativeEndpoint(request, fmt.Sprintf("%s%s", acctPath, existingAcct.ID))
|
||||
response.Header().Set("Location", acctURL)
|
||||
_ = wfe.writeJsonResponse(response, http.StatusOK, existingAcct)
|
||||
_ = wfe.writeJSONResponse(response, http.StatusOK, existingAcct)
|
||||
}
|
||||
return
|
||||
} else if existingAcct == nil && newAcctReq.OnlyReturnExisting {
|
||||
|
|
@ -1009,7 +980,7 @@ func (wfe *WebFrontEndImpl) NewAccount(
|
|||
acctURL := wfe.relativeEndpoint(request, fmt.Sprintf("%s%s", acctPath, newAcct.ID))
|
||||
|
||||
response.Header().Add("Location", acctURL)
|
||||
err = wfe.writeJsonResponse(response, http.StatusCreated, newAcct)
|
||||
err = wfe.writeJSONResponse(response, http.StatusCreated, newAcct)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling account"), response)
|
||||
return
|
||||
|
|
@ -1223,11 +1194,10 @@ func (wfe *WebFrontEndImpl) makeChallenges(authz *core.Authorization, request *h
|
|||
// NewOrder creates a new Order request and populates its authorizations
|
||||
func (wfe *WebFrontEndImpl) NewOrder(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1305,7 +1275,7 @@ func (wfe *WebFrontEndImpl) NewOrder(
|
|||
response.Header().Add("Location", orderURL)
|
||||
|
||||
orderResp := wfe.orderForDisplay(storedOrder, request)
|
||||
err = wfe.writeJsonResponse(response, http.StatusCreated, orderResp)
|
||||
err = wfe.writeJSONResponse(response, http.StatusCreated, orderResp)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling order"), response)
|
||||
return
|
||||
|
|
@ -1357,10 +1327,9 @@ func (wfe *WebFrontEndImpl) orderForDisplay(
|
|||
// Order retrieves the details of an existing order
|
||||
func (wfe *WebFrontEndImpl) Order(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1394,7 +1363,7 @@ func (wfe *WebFrontEndImpl) Order(
|
|||
|
||||
// Prepare the order for display as JSON
|
||||
orderReq := wfe.orderForDisplay(order, request)
|
||||
err := wfe.writeJsonResponse(response, http.StatusOK, orderReq)
|
||||
err := wfe.writeJSONResponse(response, http.StatusOK, orderReq)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling order"), response)
|
||||
return
|
||||
|
|
@ -1403,12 +1372,11 @@ func (wfe *WebFrontEndImpl) Order(
|
|||
|
||||
func (wfe *WebFrontEndImpl) FinalizeOrder(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
// Verify the POST request
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1524,7 +1492,7 @@ func (wfe *WebFrontEndImpl) FinalizeOrder(
|
|||
orderReq := wfe.orderForDisplay(existingOrder, request)
|
||||
orderURL := wfe.relativeEndpoint(request, fmt.Sprintf("%s%s", orderPath, existingOrder.ID))
|
||||
response.Header().Add("Location", orderURL)
|
||||
err = wfe.writeJsonResponse(response, http.StatusOK, orderReq)
|
||||
err = wfe.writeJSONResponse(response, http.StatusOK, orderReq)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling order"), response)
|
||||
return
|
||||
|
|
@ -1571,13 +1539,12 @@ func prepAuthorizationForDisplay(authz acme.Authorization) acme.Authorization {
|
|||
|
||||
func (wfe *WebFrontEndImpl) Authz(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
// There are two types of requests we might get:
|
||||
// A) a POST to update the authorization
|
||||
// B) a POST-as-GET to get the authorization
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1642,7 +1609,7 @@ func (wfe *WebFrontEndImpl) Authz(
|
|||
}
|
||||
}
|
||||
|
||||
err := wfe.writeJsonResponse(
|
||||
err := wfe.writeJSONResponse(
|
||||
response,
|
||||
http.StatusOK,
|
||||
prepAuthorizationForDisplay(authz.Authorization))
|
||||
|
|
@ -1654,13 +1621,12 @@ func (wfe *WebFrontEndImpl) Authz(
|
|||
|
||||
func (wfe *WebFrontEndImpl) Challenge(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
// There are two possibilities:
|
||||
// A) request is a POST to begin a challenge
|
||||
// B) request is a POST-as-GET to poll a challenge
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1676,7 +1642,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
|||
// If the post isn't a POST-as-GET its case A)
|
||||
var account *core.Account
|
||||
if !postData.postAsGet {
|
||||
wfe.updateChallenge(ctx, postData, response, request)
|
||||
wfe.updateChallenge(postData, response, request)
|
||||
return
|
||||
} else {
|
||||
// Otherwise it is case B)
|
||||
|
|
@ -1698,7 +1664,7 @@ func (wfe *WebFrontEndImpl) Challenge(
|
|||
return
|
||||
}
|
||||
|
||||
err := wfe.writeJsonResponse(response, http.StatusOK, chal.Challenge)
|
||||
err := wfe.writeJSONResponse(response, http.StatusOK, chal.Challenge)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling challenge"), response)
|
||||
return
|
||||
|
|
@ -1725,8 +1691,7 @@ func (wfe *WebFrontEndImpl) getAcctByKey(key crypto.PublicKey) (*core.Account, *
|
|||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) validateChallengeUpdate(
|
||||
chal *core.Challenge,
|
||||
acct *core.Account) (*core.Authorization, *acme.ProblemDetails) {
|
||||
chal *core.Challenge) (*core.Authorization, *acme.ProblemDetails) {
|
||||
// Lock the challenge for reading to do validation
|
||||
chal.RLock()
|
||||
defer chal.RUnlock()
|
||||
|
|
@ -1775,7 +1740,6 @@ func (wfe *WebFrontEndImpl) validateAuthzForChallenge(authz *core.Authorization)
|
|||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) updateChallenge(
|
||||
ctx context.Context,
|
||||
postData *authenticatedPOST,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
|
@ -1816,7 +1780,7 @@ func (wfe *WebFrontEndImpl) updateChallenge(
|
|||
return
|
||||
}
|
||||
|
||||
authz, prob := wfe.validateChallengeUpdate(existingChal, existingAcct)
|
||||
authz, prob := wfe.validateChallengeUpdate(existingChal)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1870,7 +1834,7 @@ func (wfe *WebFrontEndImpl) updateChallenge(
|
|||
existingChal.RLock()
|
||||
defer existingChal.RUnlock()
|
||||
response.Header().Add("Link", link(existingChal.Authz.URL, "up"))
|
||||
err = wfe.writeJsonResponse(response, http.StatusOK, existingChal.Challenge)
|
||||
err = wfe.writeJSONResponse(response, http.StatusOK, existingChal.Challenge)
|
||||
if err != nil {
|
||||
wfe.sendError(acme.InternalErrorProblem("Error marshalling challenge"), response)
|
||||
return
|
||||
|
|
@ -1879,10 +1843,9 @@ func (wfe *WebFrontEndImpl) updateChallenge(
|
|||
|
||||
func (wfe *WebFrontEndImpl) Certificate(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
postData, prob := wfe.verifyPOST(ctx, logEvent, request, wfe.lookupJWK)
|
||||
postData, prob := wfe.verifyPOST(request, wfe.lookupJWK)
|
||||
if prob != nil {
|
||||
wfe.sendError(prob, response)
|
||||
return
|
||||
|
|
@ -1912,7 +1875,7 @@ func (wfe *WebFrontEndImpl) Certificate(
|
|||
_, _ = response.Write(cert.Chain())
|
||||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) writeJsonResponse(response http.ResponseWriter, status int, v interface{}) error {
|
||||
func (wfe *WebFrontEndImpl) writeJSONResponse(response http.ResponseWriter, status int, v interface{}) error {
|
||||
jsonReply, err := marshalIndent(v)
|
||||
if err != nil {
|
||||
return err // All callers are responsible for handling this error
|
||||
|
|
@ -1965,7 +1928,6 @@ func uniqueLowerNames(names []string) []string {
|
|||
// This method does not percolate to a CRL or an OCSP response.
|
||||
func (wfe *WebFrontEndImpl) RevokeCert(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
response http.ResponseWriter,
|
||||
request *http.Request) {
|
||||
|
||||
|
|
@ -2005,9 +1967,9 @@ func (wfe *WebFrontEndImpl) RevokeCert(
|
|||
// Handle the revocation request according to how it is authenticated, or if
|
||||
// the authentication type is unknown, error immediately
|
||||
if authType == embeddedKeyID {
|
||||
prob = wfe.revokeCertByKeyID(ctx, logEvent, parsedJWS, request)
|
||||
prob = wfe.revokeCertByKeyID(parsedJWS, request)
|
||||
} else if authType == embeddedJWK {
|
||||
prob = wfe.revokeCertByJWK(ctx, logEvent, parsedJWS, request)
|
||||
prob = wfe.revokeCertByJWK(parsedJWS, request)
|
||||
} else {
|
||||
prob = acme.MalformedProblem("Malformed JWS, no KeyID or embedded JWK")
|
||||
}
|
||||
|
|
@ -2020,8 +1982,6 @@ func (wfe *WebFrontEndImpl) RevokeCert(
|
|||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) revokeCertByKeyID(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
jws *jose.JSONWebSignature,
|
||||
request *http.Request) *acme.ProblemDetails {
|
||||
|
||||
|
|
@ -2056,12 +2016,10 @@ func (wfe *WebFrontEndImpl) revokeCertByKeyID(
|
|||
"The certificate being revoked is not associated with account %q",
|
||||
existingAcct.ID))
|
||||
}
|
||||
return wfe.processRevocation(ctx, postData.body, authorizedToRevoke, request, logEvent)
|
||||
return wfe.processRevocation(postData.body, authorizedToRevoke)
|
||||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) revokeCertByJWK(
|
||||
ctx context.Context,
|
||||
logEvent *requestEvent,
|
||||
jws *jose.JSONWebSignature,
|
||||
request *http.Request) *acme.ProblemDetails {
|
||||
|
||||
|
|
@ -2086,7 +2044,7 @@ func (wfe *WebFrontEndImpl) revokeCertByJWK(
|
|||
return acme.UnauthorizedProblem(
|
||||
"JWK embedded in revocation request must be the same public key as the cert to be revoked")
|
||||
}
|
||||
return wfe.processRevocation(ctx, postData.body, authorizedToRevoke, request, logEvent)
|
||||
return wfe.processRevocation(postData.body, authorizedToRevoke)
|
||||
}
|
||||
|
||||
// authorizedToRevokeCert is a callback function that can be used to validate if
|
||||
|
|
@ -2098,11 +2056,8 @@ func (wfe *WebFrontEndImpl) revokeCertByJWK(
|
|||
type authorizedToRevokeCert func(*core.Certificate) *acme.ProblemDetails
|
||||
|
||||
func (wfe *WebFrontEndImpl) processRevocation(
|
||||
ctx context.Context,
|
||||
jwsBody []byte,
|
||||
authorizedToRevoke authorizedToRevokeCert,
|
||||
request *http.Request,
|
||||
logEvent *requestEvent) *acme.ProblemDetails {
|
||||
authorizedToRevoke authorizedToRevokeCert) *acme.ProblemDetails {
|
||||
|
||||
// revokeCertReq is the ACME certificate information submitted by the client
|
||||
var revokeCertReq struct {
|
||||
|
|
|
|||
Loading…
Reference in New Issue