Merge upstream/master
This commit is contained in:
commit
74ecad349b
|
|
@ -96,11 +96,9 @@ func NewCertificateAuthorityImpl(cadb core.CertificateAuthorityDatabase, config
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// In test mode, load a private key from a file. In production, use an HSM.
|
||||
if !config.TestMode {
|
||||
err = errors.New("OCSP signing with a PKCS#11 key not yet implemented.")
|
||||
return nil, err
|
||||
}
|
||||
// In test mode, load a private key from a file.
|
||||
// TODO: This should rely on the CFSSL config, to make it easy to use a key
|
||||
// from a file vs an HSM. https://github.com/letsencrypt/boulder/issues/163
|
||||
issuerKey, err := loadIssuerKey(config.IssuerKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -352,13 +352,6 @@ func TestFailNoSerial(t *testing.T) {
|
|||
test.AssertError(t, err, "CA should have failed with no SerialPrefix")
|
||||
}
|
||||
|
||||
func TestFailNoTestMode(t *testing.T) {
|
||||
cadb, _, caConfig := setup(t)
|
||||
caConfig.TestMode = false
|
||||
_, err := NewCertificateAuthorityImpl(cadb, caConfig)
|
||||
test.AssertError(t, err, "CA should have failed with TestMode = false, but key provided")
|
||||
}
|
||||
|
||||
func TestRevoke(t *testing.T) {
|
||||
cadb, storageAuthority, caConfig := setup(t)
|
||||
ca, err := NewCertificateAuthorityImpl(cadb, caConfig)
|
||||
|
|
|
|||
|
|
@ -77,15 +77,16 @@ func (ra *RegistrationAuthorityImpl) NewRegistration(init core.Registration, key
|
|||
}
|
||||
|
||||
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int64) (authz core.Authorization, err error) {
|
||||
if regID == 0 {
|
||||
err = fmt.Errorf("Registration ID cannot be 0")
|
||||
if regID <= 0 {
|
||||
err = fmt.Errorf("Invalid registration ID")
|
||||
return authz, err
|
||||
}
|
||||
|
||||
identifier := request.Identifier
|
||||
|
||||
// Check that the identifier is present and appropriate
|
||||
if err = ra.PA.WillingToIssue(identifier); err != nil {
|
||||
return
|
||||
return authz, err
|
||||
}
|
||||
|
||||
// Create validations
|
||||
|
|
@ -93,7 +94,7 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
|||
challenges, combinations := ra.PA.ChallengesFor(identifier)
|
||||
authID, err := ra.SA.NewPendingAuthorization()
|
||||
if err != nil {
|
||||
return
|
||||
return authz, err
|
||||
}
|
||||
for i := range challenges {
|
||||
// Ignoring these errors because we construct the URLs to be correct
|
||||
|
|
@ -102,7 +103,7 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
|||
|
||||
if !challenges[i].IsSane(false) {
|
||||
err = fmt.Errorf("Challenge didn't pass sanity check: %+v", challenges[i])
|
||||
return
|
||||
return authz, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +119,7 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
|||
|
||||
// Store the authorization object, then return it
|
||||
err = ra.SA.UpdatePendingAuthorization(authz)
|
||||
return
|
||||
return authz, err
|
||||
}
|
||||
|
||||
func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest, regID int64) (core.Certificate, error) {
|
||||
|
|
@ -150,6 +151,11 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
|||
ra.log.Audit(fmt.Sprintf("Certificate request %s - %s", logEventResult, string(jsonLogEvent)))
|
||||
}()
|
||||
|
||||
if regID <= 0 {
|
||||
err = fmt.Errorf("Invalid registration ID")
|
||||
return emptyCert, err
|
||||
}
|
||||
|
||||
// Verify the CSR
|
||||
// TODO: Verify that other aspects of the CSR are appropriate
|
||||
csr := req.CSR
|
||||
|
|
|
|||
|
|
@ -154,6 +154,9 @@ func assertAuthzEqual(t *testing.T, a1, a2 core.Authorization) {
|
|||
func TestNewAuthorization(t *testing.T) {
|
||||
_, _, sa, ra := initAuthorities(t)
|
||||
|
||||
_, err := ra.NewAuthorization(AuthzRequest, 0)
|
||||
test.AssertError(t, err, "Authorization cannot have registrationID == 0")
|
||||
|
||||
authz, err := ra.NewAuthorization(AuthzRequest, 1)
|
||||
test.AssertNotError(t, err, "NewAuthorization failed")
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ func TestAddRegistration(t *testing.T) {
|
|||
test.AssertNotError(t, err, "Couldn't create new registration")
|
||||
test.Assert(t, reg.ID != 0, "ID shouldn't be 0")
|
||||
|
||||
_, err = sa.GetRegistration(0)
|
||||
test.AssertError(t, err, "Registration object for ID 0 was returned")
|
||||
|
||||
dbReg, err := sa.GetRegistration(reg.ID)
|
||||
test.AssertNotError(t, err, fmt.Sprintf("Couldn't get registration with ID %v", reg.ID))
|
||||
|
||||
|
|
@ -74,11 +77,15 @@ func TestAddRegistration(t *testing.T) {
|
|||
test.AssertNotError(t, err, fmt.Sprintf("Couldn't get registration with ID %v", reg.ID))
|
||||
|
||||
dbReg, err = sa.GetRegistrationByKey(jwk)
|
||||
test.AssertNotError(t, err, "Couldn't update registration by key")
|
||||
test.AssertNotError(t, err, "Couldn't get registration by key")
|
||||
|
||||
test.AssertEquals(t, dbReg.ID, newReg.ID)
|
||||
test.AssertEquals(t, dbReg.RecoveryToken, newReg.RecoveryToken)
|
||||
test.AssertEquals(t, dbReg.Agreement, newReg.Agreement)
|
||||
|
||||
jwk.KeyID = "bad"
|
||||
_, err = sa.GetRegistrationByKey(jwk)
|
||||
test.AssertError(t, err, "Registration object for invalid key was returned")
|
||||
}
|
||||
|
||||
func TestAddAuthorization(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -132,12 +132,17 @@ function parseLink(link) {
|
|||
}
|
||||
|
||||
function post(url, body, callback) {
|
||||
var jws = crypto.generateSignature(state.accountPrivateKey, new Buffer(JSON.stringify(body)));
|
||||
var payload = JSON.stringify(jws);
|
||||
var payload = JSON.stringify(body, null, 2);
|
||||
var jws = crypto.generateSignature(state.accountPrivateKey, new Buffer(payload));
|
||||
var signed = JSON.stringify(jws, null, 2);
|
||||
|
||||
var req = request.post(url, callback);
|
||||
console.log('Posting to', url, ':\n', payload);
|
||||
req.write(payload)
|
||||
console.log('Posting to', url, ':\n', signed);
|
||||
console.log('Payload:', payload);
|
||||
req.on('response', function(response) {
|
||||
console.log(response.headers)
|
||||
})
|
||||
req.write(signed)
|
||||
req.end();
|
||||
return req;
|
||||
}
|
||||
|
|
@ -276,13 +281,13 @@ function sendAgreement(answers) {
|
|||
post(state.registrationURL, state.registration,
|
||||
function(err, resp, body) {
|
||||
if (err || Math.floor(resp.statusCode / 100) != 2) {
|
||||
console.log("Couldn't POST agreement back to server, aborting.");
|
||||
console.log("error: " + err);
|
||||
console.log(body);
|
||||
console.log("error: " + err);
|
||||
console.log("Couldn't POST agreement back to server, aborting.");
|
||||
process.exit(1);
|
||||
} else {
|
||||
inquirer.prompt(questions.domain, getChallenges);
|
||||
}
|
||||
|
||||
inquirer.prompt(questions.domain, getChallenges);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ func (wfe *WebFrontEndImpl) NewRegistration(response http.ResponseWriter, reques
|
|||
return
|
||||
}
|
||||
|
||||
regURL := wfe.RegBase + string(reg.ID)
|
||||
regURL := fmt.Sprintf("%s%d", wfe.RegBase, reg.ID)
|
||||
responseBody, err := json.Marshal(reg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Error marshaling authz", err, http.StatusInternalServerError)
|
||||
|
|
@ -485,7 +485,7 @@ func (wfe *WebFrontEndImpl) NewCertificate(response http.ResponseWriter, request
|
|||
// TODO The spec says a client should send an Accept: application/pkix-cert
|
||||
// header; either explicitly insist or tolerate
|
||||
response.Header().Add("Location", certURL)
|
||||
response.Header().Add("Link", link(wfe.IssuerPath, "up"))
|
||||
response.Header().Add("Link", link(wfe.BaseURL+wfe.IssuerPath, "up"))
|
||||
response.Header().Set("Content-Type", "application/pkix-cert")
|
||||
response.WriteHeader(http.StatusCreated)
|
||||
if _, err = response.Write(cert.DER); err != nil {
|
||||
|
|
@ -577,6 +577,24 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
|||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *http.Request) {
|
||||
if request.Method != "POST" {
|
||||
wfe.sendError(response, "Method not allowed", request.Method, http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
body, _, currReg, err := wfe.verifyPOST(request, true)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
wfe.sendError(response,
|
||||
"No registration exists matching provided key",
|
||||
err, http.StatusForbidden)
|
||||
} else {
|
||||
wfe.sendError(response,
|
||||
"Unable to read/verify body", err, http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Requests to this handler should have a path that leads to a known
|
||||
// registration
|
||||
idStr := parseIDFromPath(request.URL.Path)
|
||||
|
|
@ -587,71 +605,43 @@ func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *
|
|||
} else if id <= 0 {
|
||||
wfe.sendError(response, "Registration ID must be a positive non-zero integer", id, http.StatusBadRequest)
|
||||
return
|
||||
} else if id != currReg.ID {
|
||||
wfe.sendError(response, "Request signing key did not match registration key", "", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
reg, err := wfe.SA.GetRegistration(id)
|
||||
|
||||
var update core.Registration
|
||||
err = json.Unmarshal(body, &update)
|
||||
if err != nil {
|
||||
wfe.sendError(response,
|
||||
"Unable to find registration", err,
|
||||
http.StatusNotFound)
|
||||
wfe.sendError(response, "Error unmarshaling registration", err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
reg.ID = id
|
||||
|
||||
switch request.Method {
|
||||
default:
|
||||
wfe.sendError(response, "Method not allowed", "", http.StatusMethodNotAllowed)
|
||||
if len(update.Agreement) > 0 && update.Agreement != wfe.SubscriberAgreementURL {
|
||||
wfe.sendError(response, fmt.Sprintf("Provided agreement URL [%s] does not match current agreement URL [%s]", update.Agreement, wfe.SubscriberAgreementURL), nil, http.StatusBadRequest)
|
||||
return
|
||||
|
||||
case "GET":
|
||||
jsonReply, err := json.Marshal(reg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.Header().Set("Content-Type", "application/json")
|
||||
response.WriteHeader(http.StatusOK)
|
||||
response.Write(jsonReply)
|
||||
|
||||
case "POST":
|
||||
body, _, currReg, err := wfe.verifyPOST(request, true)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
wfe.sendError(response, "No registration exists matching provided key", err, http.StatusForbidden)
|
||||
} else {
|
||||
wfe.sendError(response, "Unable to read/verify body", err, http.StatusBadRequest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var update core.Registration
|
||||
err = json.Unmarshal(body, &update)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Error unmarshaling registration", err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(update.Agreement) > 0 && update.Agreement != wfe.SubscriberAgreementURL {
|
||||
wfe.sendError(response, fmt.Sprintf("Provided agreement URL [%s] does not match current agreement URL [%s]", update.Agreement, wfe.SubscriberAgreementURL), nil, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Ask the RA to update this authorization
|
||||
updatedReg, err := wfe.RA.UpdateRegistration(currReg, update)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Unable to update registration", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
jsonReply, err := json.Marshal(updatedReg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.Header().Set("Content-Type", "application/json")
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write(jsonReply)
|
||||
|
||||
}
|
||||
|
||||
// MergeUpdate copies over only the fields that a client is allowed to modify.
|
||||
// Note: The RA will also use MergeUpdate to filter out non-updateable fields,
|
||||
// but we do it here too, so that/ input filtering happens as early in the
|
||||
// request processing as possible.
|
||||
currReg.MergeUpdate(update)
|
||||
// Ask the RA to update this authorization.
|
||||
updatedReg, err := wfe.RA.UpdateRegistration(currReg, currReg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Unable to update registration", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
jsonReply, err := json.Marshal(updatedReg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Failed to marshal authz", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
response.Header().Set("Content-Type", "application/json")
|
||||
response.WriteHeader(http.StatusAccepted)
|
||||
response.Write(jsonReply)
|
||||
}
|
||||
|
||||
func (wfe *WebFrontEndImpl) Authorization(response http.ResponseWriter, request *http.Request) {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ func (sa *MockSA) GetRegistration(id int64) (core.Registration, error) {
|
|||
var parsedKey jose.JsonWebKey
|
||||
parsedKey.UnmarshalJSON(keyJSON)
|
||||
|
||||
return core.Registration{Key: parsedKey, Agreement: "yup"}, nil
|
||||
return core.Registration{ID: id, Key: parsedKey, Agreement: "yup"}, nil
|
||||
}
|
||||
|
||||
func (sa *MockSA) GetRegistrationByKey(jwk jose.JsonWebKey) (core.Registration, error) {
|
||||
|
|
@ -102,16 +102,16 @@ func (sa *MockSA) GetRegistrationByKey(jwk jose.JsonWebKey) (core.Registration,
|
|||
test2KeyPublic.UnmarshalJSON([]byte(test2KeyPublicJSON))
|
||||
|
||||
if core.KeyDigestEquals(jwk, test1KeyPublic) {
|
||||
return core.Registration{Key: jwk}, nil
|
||||
return core.Registration{ID: 1, Key: jwk}, nil
|
||||
}
|
||||
|
||||
if core.KeyDigestEquals(jwk, test2KeyPublic) {
|
||||
// No key found
|
||||
return core.Registration{}, sql.ErrNoRows
|
||||
return core.Registration{ID: 2}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
// Return a fake registration
|
||||
return core.Registration{Agreement: "yup"}, nil
|
||||
return core.Registration{ID: 1, Agreement: "yup"}, nil
|
||||
}
|
||||
|
||||
func (sa *MockSA) GetAuthorization(string) (core.Authorization, error) {
|
||||
|
|
@ -374,7 +374,7 @@ func TestChallenge(t *testing.T) {
|
|||
URI: core.AcmeURL(*challengeURL),
|
||||
},
|
||||
},
|
||||
RegistrationID: 0,
|
||||
RegistrationID: 1,
|
||||
}
|
||||
|
||||
wfe.Challenge(authz, responseWriter, &http.Request{
|
||||
|
|
@ -614,35 +614,15 @@ func TestRegistration(t *testing.T) {
|
|||
"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Method not allowed\"}")
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
// Test GET missing entry
|
||||
path, _ = url.Parse("/100")
|
||||
wfe.Registration(responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: path,
|
||||
})
|
||||
test.AssertEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Unable to find registration\"}")
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
// Test GET malformed entry
|
||||
path, _ = url.Parse("/101")
|
||||
wfe.Registration(responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: path,
|
||||
})
|
||||
test.AssertEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
"{\"type\":\"urn:acme:error:serverInternal\",\"detail\":\"Failed to marshal authz\"}")
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
// Test GET proper entry
|
||||
// Test GET proper entry returns 405
|
||||
path, _ = url.Parse("/1")
|
||||
wfe.Registration(responseWriter, &http.Request{
|
||||
Method: "GET",
|
||||
URL: path,
|
||||
})
|
||||
test.AssertNotContains(t, responseWriter.Body.String(), "urn:acme:error")
|
||||
test.AssertEquals(t,
|
||||
responseWriter.Body.String(),
|
||||
"{\"type\":\"urn:acme:error:malformed\",\"detail\":\"Method not allowed\"}")
|
||||
responseWriter.Body.Reset()
|
||||
|
||||
// Test POST invalid JSON
|
||||
|
|
@ -658,7 +638,7 @@ func TestRegistration(t *testing.T) {
|
|||
responseWriter.Body.Reset()
|
||||
|
||||
// Test POST valid JSON but key is not registered
|
||||
path, _ = url.Parse("/1")
|
||||
path, _ = url.Parse("/2")
|
||||
wfe.Registration(responseWriter, &http.Request{
|
||||
Method: "POST",
|
||||
Body: makeBody(`{
|
||||
|
|
@ -684,6 +664,9 @@ func TestRegistration(t *testing.T) {
|
|||
|
||||
// Test POST valid JSON with registration up in the mock (with incorrect agreement URL)
|
||||
result, err := signer.Sign([]byte("{\"agreement\":\"https://letsencrypt.org/im-bad\"}"))
|
||||
|
||||
// Test POST valid JSON with registration up in the mock
|
||||
path, _ = url.Parse("/1")
|
||||
wfe.Registration(responseWriter, &http.Request{
|
||||
Method: "POST",
|
||||
Body: makeBody(result.FullSerialize()),
|
||||
|
|
|
|||
Loading…
Reference in New Issue