switch authz and pending_authz to store registration ID instead of key (and update all the random stuff they touched)
This commit is contained in:
parent
672f0b1fbe
commit
e233fdaa61
|
@ -53,7 +53,7 @@ type RegistrationAuthority interface {
|
|||
NewRegistration(Registration, jose.JsonWebKey) (Registration, error)
|
||||
|
||||
// [WebFrontEnd]
|
||||
NewAuthorization(Authorization, jose.JsonWebKey) (Authorization, error)
|
||||
NewAuthorization(Authorization, int) (Authorization, error)
|
||||
|
||||
// [WebFrontEnd]
|
||||
NewCertificate(CertificateRequest, jose.JsonWebKey) (Certificate, error)
|
||||
|
@ -88,7 +88,7 @@ type PolicyAuthority interface {
|
|||
}
|
||||
|
||||
type StorageGetter interface {
|
||||
GetRegistration(string) (Registration, error)
|
||||
GetRegistration(int) (Registration, error)
|
||||
GetRegistrationByKey(jose.JsonWebKey) (Registration, error)
|
||||
GetAuthorization(string) (Authorization, error)
|
||||
GetCertificate(string) ([]byte, error)
|
||||
|
|
|
@ -100,7 +100,7 @@ func (cr CertificateRequest) MarshalJSON() ([]byte, error) {
|
|||
// to account keys.
|
||||
type Registration struct {
|
||||
// Unique identifier
|
||||
ID string `json:"-" db:"id"`
|
||||
ID int `json:"-" db:"id"`
|
||||
|
||||
// Account key to which the details are attached
|
||||
Key jose.JsonWebKey `json:"key" db:"key"`
|
||||
|
@ -261,7 +261,9 @@ type Authorization struct {
|
|||
Identifier AcmeIdentifier `json:"identifier,omitempty" db:"identifier"`
|
||||
|
||||
// The account key that is authorized for the identifier
|
||||
Key jose.JsonWebKey `json:"key,omitempty" db:"key"`
|
||||
// Key jose.JsonWebKey `json:"key,omitempty" db:"key"`
|
||||
// The registration ID associated with the authorization
|
||||
RegID int `json:"regID,omitempty" db:"regID"`
|
||||
|
||||
// The status of the validation of this authorization
|
||||
Status AcmeStatus `json:"status,omitempty" db:"status"`
|
||||
|
|
|
@ -58,7 +58,7 @@ func (ra *RegistrationAuthorityImpl) NewRegistration(init core.Registration, key
|
|||
return
|
||||
}
|
||||
|
||||
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, key jose.JsonWebKey) (authz core.Authorization, err error) {
|
||||
func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization, regID int) (authz core.Authorization, err error) {
|
||||
identifier := request.Identifier
|
||||
|
||||
// Check that the identifier is present and appropriate
|
||||
|
@ -88,7 +88,7 @@ func (ra *RegistrationAuthorityImpl) NewAuthorization(request core.Authorization
|
|||
authz = core.Authorization{
|
||||
ID: authID,
|
||||
Identifier: identifier,
|
||||
Key: key,
|
||||
RegID: regID,
|
||||
Status: core.StatusPending,
|
||||
Challenges: challenges,
|
||||
Combinations: combinations,
|
||||
|
@ -120,6 +120,11 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
|||
return emptyCert, err
|
||||
}
|
||||
|
||||
registration, err := ra.SA.GetRegistrationByKey(requestKey)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
|
||||
// Gather authorized domains from the referenced authorizations
|
||||
authorizedDomains := map[string]bool{}
|
||||
now := time.Now()
|
||||
|
@ -127,7 +132,7 @@ func (ra *RegistrationAuthorityImpl) NewCertificate(req core.CertificateRequest,
|
|||
id := lastPathSegment(url)
|
||||
authz, err := ra.SA.GetAuthorization(id)
|
||||
if err != nil || // Couldn't find authorization
|
||||
!core.KeyDigestEquals(authz.Key, requestKey) ||
|
||||
authz.RegID != registration.ID || // Key doesn't match
|
||||
authz.Status != core.StatusValid || // Not finalized or not successful
|
||||
authz.Expires.Before(now) || // Expired
|
||||
authz.Identifier.Type != core.IdentifierDNS {
|
||||
|
|
|
@ -127,14 +127,14 @@ func assertAuthzEqual(t *testing.T, a1, a2 core.Authorization) {
|
|||
test.Assert(t, a1.ID == a2.ID, "ret != DB: ID")
|
||||
test.Assert(t, a1.Identifier == a2.Identifier, "ret != DB: Identifier")
|
||||
test.Assert(t, a1.Status == a2.Status, "ret != DB: Status")
|
||||
test.Assert(t, core.KeyDigestEquals(a1.Key, a2.Key), "ret != DB: Key")
|
||||
test.Assert(t, a1.RegID == a2.RegID, "ret != DB: Key")
|
||||
// Not testing: Contact, Challenges
|
||||
}
|
||||
|
||||
func TestNewAuthorization(t *testing.T) {
|
||||
_, _, sa, ra := initAuthorities(t)
|
||||
|
||||
authz, err := ra.NewAuthorization(AuthzRequest, AccountKey)
|
||||
authz, err := ra.NewAuthorization(AuthzRequest, 1)
|
||||
test.AssertNotError(t, err, "NewAuthorization failed")
|
||||
|
||||
// Verify that returned authz same as DB
|
||||
|
@ -143,7 +143,7 @@ func TestNewAuthorization(t *testing.T) {
|
|||
assertAuthzEqual(t, authz, dbAuthz)
|
||||
|
||||
// Verify that the returned authz has the right information
|
||||
test.Assert(t, core.KeyDigestEquals(authz.Key, AccountKey), "Initial authz did not get the right key")
|
||||
test.Assert(t, authz.RegID == 1, "Initial authz did not get the right key")
|
||||
test.Assert(t, authz.Identifier == AuthzRequest.Identifier, "Initial authz had wrong identifier")
|
||||
test.Assert(t, authz.Status == core.StatusPending, "Initial authz not pending")
|
||||
|
||||
|
@ -216,6 +216,8 @@ func TestOnValidationUpdate(t *testing.T) {
|
|||
|
||||
func TestNewCertificate(t *testing.T) {
|
||||
_, _, sa, ra := initAuthorities(t)
|
||||
sa.NewRegistration(core.Registration{Key: AccountKey})
|
||||
AuthzFinal.RegID = 1
|
||||
AuthzFinal.ID, _ = sa.NewPendingAuthorization()
|
||||
sa.UpdatePendingAuthorization(AuthzFinal)
|
||||
sa.FinalizeAuthorization(AuthzFinal)
|
||||
|
@ -225,6 +227,7 @@ func TestNewCertificate(t *testing.T) {
|
|||
AuthzFinalWWW.Identifier.Value = "www.example.com"
|
||||
AuthzFinalWWW.ID, _ = sa.NewPendingAuthorization()
|
||||
sa.FinalizeAuthorization(AuthzFinalWWW)
|
||||
sa.DumpTables()
|
||||
|
||||
// Construct a cert request referencing the two authorizations
|
||||
url1, _ := url.Parse("http://doesnt.matter/" + AuthzFinal.ID)
|
||||
|
|
|
@ -70,7 +70,7 @@ type registrationRequest struct {
|
|||
|
||||
type authorizationRequest struct {
|
||||
Authz core.Authorization
|
||||
Key jose.JsonWebKey
|
||||
RegID int
|
||||
}
|
||||
|
||||
type certificateRequest struct {
|
||||
|
@ -106,7 +106,7 @@ func NewRegistrationAuthorityServer(serverQueue string, channel *amqp.Channel, i
|
|||
return nil
|
||||
}
|
||||
|
||||
authz, err := impl.NewAuthorization(ar.Authz, ar.Key)
|
||||
authz, err := impl.NewAuthorization(ar.Authz, ar.RegID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -239,8 +239,8 @@ func (rac RegistrationAuthorityClient) NewRegistration(reg core.Registration, ke
|
|||
return
|
||||
}
|
||||
|
||||
func (rac RegistrationAuthorityClient) NewAuthorization(authz core.Authorization, key jose.JsonWebKey) (newAuthz core.Authorization, err error) {
|
||||
data, err := json.Marshal(authorizationRequest{authz, key})
|
||||
func (rac RegistrationAuthorityClient) NewAuthorization(authz core.Authorization, regID int) (newAuthz core.Authorization, err error) {
|
||||
data, err := json.Marshal(authorizationRequest{authz, regID})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -436,7 +436,15 @@ func NewStorageAuthorityServer(serverQueue string, channel *amqp.Channel, impl c
|
|||
rpc := NewAmqpRPCServer(serverQueue, channel)
|
||||
|
||||
rpc.Handle(MethodGetRegistration, func(req []byte) (response []byte) {
|
||||
reg, err := impl.GetRegistration(string(req))
|
||||
var intReq struct {
|
||||
ID int
|
||||
}
|
||||
err := json.Unmarshal(req, &intReq)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
reg, err := impl.GetRegistration(intReq.ID)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -635,8 +643,18 @@ func NewStorageAuthorityClient(clientQueue, serverQueue string, channel *amqp.Ch
|
|||
return
|
||||
}
|
||||
|
||||
func (cac StorageAuthorityClient) GetRegistration(id string) (reg core.Registration, err error) {
|
||||
jsonReg, err := cac.rpc.DispatchSync(MethodGetRegistration, []byte(id))
|
||||
func (cac StorageAuthorityClient) GetRegistration(id int) (reg core.Registration, err error) {
|
||||
var intReq struct {
|
||||
ID int
|
||||
}
|
||||
intReq.ID = id
|
||||
|
||||
data, err := json.Marshal(intReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
jsonReg, err := cac.rpc.DispatchSync(MethodGetRegistration, data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -175,7 +175,7 @@ func NewSQLStorageAuthority(driver string, name string) (ssa *SQLStorageAuthorit
|
|||
}
|
||||
|
||||
func (ssa *SQLStorageAuthority) InitTables() (err error) {
|
||||
ssa.dbMap.AddTableWithName(core.Registration{}, "registrations").SetKeys(false, "ID").SetVersionCol("LockCol")
|
||||
ssa.dbMap.AddTableWithName(core.Registration{}, "registrations").SetKeys(true, "ID").SetVersionCol("LockCol")
|
||||
ssa.dbMap.AddTableWithName(pendingauthzModel{}, "pending_authz").SetKeys(false, "ID").SetVersionCol("LockCol")
|
||||
ssa.dbMap.AddTableWithName(authzModel{}, "authz").SetKeys(false, "ID")
|
||||
ssa.dbMap.AddTableWithName(core.Certificate{}, "certificates").SetKeys(false, "Serial")
|
||||
|
@ -305,19 +305,19 @@ func existingFinal(tx *gorp.Transaction, id string) (bool) {
|
|||
return count > 0
|
||||
}
|
||||
|
||||
func existingRegistration(tx *gorp.Transaction, id string) (bool) {
|
||||
func existingRegistration(tx *gorp.Transaction, id int) (bool) {
|
||||
var count int64
|
||||
_ = tx.SelectOne(&count, "SELECT count(*) FROM registrations WHERE id = :id", map[string]interface{} {"id": id})
|
||||
return count > 0
|
||||
}
|
||||
|
||||
func (ssa *SQLStorageAuthority) GetRegistration(id string) (reg core.Registration, err error) {
|
||||
func (ssa *SQLStorageAuthority) GetRegistration(id int) (reg core.Registration, err error) {
|
||||
regObj, err := ssa.dbMap.Get(core.Registration{}, id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if regObj == nil {
|
||||
err = fmt.Errorf("No registrations with ID %s", id)
|
||||
err = fmt.Errorf("No registrations with ID %d", id)
|
||||
return
|
||||
}
|
||||
reg = *regObj.(*core.Registration)
|
||||
|
@ -432,11 +432,11 @@ func (ssa *SQLStorageAuthority) NewRegistration(reg core.Registration) (output c
|
|||
}
|
||||
|
||||
// Check that it doesn't exist already
|
||||
id := core.NewToken()
|
||||
/*id := core.NewToken()
|
||||
for existingRegistration(tx, id) {
|
||||
id = core.NewToken()
|
||||
}
|
||||
reg.ID = id
|
||||
reg.ID = id*/
|
||||
|
||||
err = tx.Insert(®)
|
||||
if err != nil {
|
||||
|
@ -506,7 +506,7 @@ func (ssa *SQLStorageAuthority) UpdateRegistration(reg core.Registration) (err e
|
|||
}
|
||||
|
||||
if !existingRegistration(tx, reg.ID) {
|
||||
err = errors.New("Requested registration not found " + reg.ID)
|
||||
err = fmt.Errorf("Requested registration not found %v", reg.ID)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -53,10 +54,10 @@ func TestAddRegistration(t *testing.T) {
|
|||
Key: jwk,
|
||||
})
|
||||
test.AssertNotError(t, err, "Couldn't create new registration")
|
||||
test.Assert(t, reg.ID != "", "ID shouldn't be blank")
|
||||
// test.Assert(t, reg.ID != "", "ID shouldn't be blank")
|
||||
|
||||
dbReg, err := sa.GetRegistration(reg.ID)
|
||||
test.AssertNotError(t, err, "Couldn't get registration with ID "+reg.ID)
|
||||
test.AssertNotError(t, err, fmt.Sprintf("Couldn't get registration with ID %v", reg.ID))
|
||||
|
||||
expectedReg := core.Registration{
|
||||
ID: reg.ID,
|
||||
|
@ -70,7 +71,7 @@ func TestAddRegistration(t *testing.T) {
|
|||
|
||||
newReg := core.Registration{ID: reg.ID, Key: jwk, RecoveryToken: "RBNvo1WzZ4oRRq0W9", Contact: []core.AcmeURL{u}, Agreement: "yes"}
|
||||
err = sa.UpdateRegistration(newReg)
|
||||
test.AssertNotError(t, err, "Couldn't update registration with ID "+reg.ID)
|
||||
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")
|
||||
|
@ -109,7 +110,7 @@ func TestAddAuthorization(t *testing.T) {
|
|||
combos[0] = []int{0,1}
|
||||
|
||||
|
||||
newPa := core.Authorization{ID: paID, Identifier: core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "wut.com"}, Key: jwk, Status: core.StatusPending, Expires: time.Now().AddDate(0, 0, 1), Challenges: []core.Challenge{chall}, Combinations: combos, Contact: []core.AcmeURL{u}}
|
||||
newPa := core.Authorization{ID: paID, Identifier: core.AcmeIdentifier{Type: core.IdentifierDNS, Value: "wut.com"}, RegID: 0, Status: core.StatusPending, Expires: time.Now().AddDate(0, 0, 1), Challenges: []core.Challenge{chall}, Combinations: combos, Contact: []core.AcmeURL{u}}
|
||||
err = sa.UpdatePendingAuthorization(newPa)
|
||||
test.AssertNotError(t, err, "Couldn't update pending authorization with ID "+paID)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cactus/go-statsd-client/statsd"
|
||||
|
@ -248,7 +249,6 @@ func (wfe *WebFrontEndImpl) NewRegistration(response http.ResponseWriter, reques
|
|||
}
|
||||
|
||||
regURL := wfe.RegBase + string(reg.ID)
|
||||
reg.ID = ""
|
||||
responseBody, err := json.Marshal(reg)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Error marshaling authz", http.StatusInternalServerError)
|
||||
|
@ -275,7 +275,7 @@ func (wfe *WebFrontEndImpl) NewAuthorization(response http.ResponseWriter, reque
|
|||
return
|
||||
}
|
||||
|
||||
body, key, _, err := wfe.verifyPOST(request, true)
|
||||
body, _, currReg, err := wfe.verifyPOST(request, true)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
wfe.sendError(response, "No registration exists matching provided key", http.StatusForbidden)
|
||||
|
@ -293,7 +293,7 @@ func (wfe *WebFrontEndImpl) NewAuthorization(response http.ResponseWriter, reque
|
|||
}
|
||||
|
||||
// Create new authz and return
|
||||
authz, err := wfe.RA.NewAuthorization(init, *key)
|
||||
authz, err := wfe.RA.NewAuthorization(init, currReg.ID)
|
||||
if err != nil {
|
||||
wfe.sendError(response,
|
||||
fmt.Sprintf("Error creating new authz: %+v", err),
|
||||
|
@ -408,7 +408,7 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
|||
return
|
||||
|
||||
case "POST":
|
||||
body, key, _, err := wfe.verifyPOST(request, true)
|
||||
body, _, currReg, err := wfe.verifyPOST(request, true)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
wfe.sendError(response, "No registration exists matching provided key", http.StatusForbidden)
|
||||
|
@ -426,7 +426,7 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
|||
}
|
||||
|
||||
// Check that the signing key is the right key
|
||||
if !core.KeyDigestEquals(key, authz.Key) {
|
||||
if currReg.ID != authz.RegID {
|
||||
wfe.sendError(response, "Signing key does not match key in authorization", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
@ -462,7 +462,12 @@ func (wfe *WebFrontEndImpl) Challenge(authz core.Authorization, response http.Re
|
|||
func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *http.Request) {
|
||||
// Requests to this handler should have a path that leads to a known
|
||||
// registration
|
||||
id := parseIDFromPath(request.URL.Path)
|
||||
idStr := parseIDFromPath(request.URL.Path)
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Registration ID must be an integer", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
reg, err := wfe.SA.GetRegistration(id)
|
||||
if err != nil {
|
||||
wfe.sendError(response,
|
||||
|
@ -488,7 +493,7 @@ func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *
|
|||
response.Write(jsonReply)
|
||||
|
||||
case "POST":
|
||||
body, _, _, err := wfe.verifyPOST(request, true)
|
||||
body, _, currReg, err := wfe.verifyPOST(request, true)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
wfe.sendError(response, "No registration exists matching provided key", http.StatusForbidden)
|
||||
|
@ -506,7 +511,7 @@ func (wfe *WebFrontEndImpl) Registration(response http.ResponseWriter, request *
|
|||
}
|
||||
|
||||
// Ask the RA to update this authorization
|
||||
updatedReg, err := wfe.RA.UpdateRegistration(reg, update)
|
||||
updatedReg, err := wfe.RA.UpdateRegistration(currReg, update)
|
||||
if err != nil {
|
||||
wfe.sendError(response, "Unable to update registration", http.StatusInternalServerError)
|
||||
return
|
||||
|
|
|
@ -29,7 +29,7 @@ type MockSA struct {
|
|||
// empty
|
||||
}
|
||||
|
||||
func (sa *MockSA) GetRegistration(string) (core.Registration, error) {
|
||||
func (sa *MockSA) GetRegistration(int) (core.Registration, error) {
|
||||
return core.Registration{}, nil
|
||||
}
|
||||
|
||||
|
@ -244,8 +244,8 @@ func (ra *MockRegistrationAuthority) NewRegistration(reg core.Registration, jwk
|
|||
return reg, nil
|
||||
}
|
||||
|
||||
func (ra *MockRegistrationAuthority) NewAuthorization(authz core.Authorization, jwk jose.JsonWebKey) (core.Authorization, error) {
|
||||
authz.Key = jwk
|
||||
func (ra *MockRegistrationAuthority) NewAuthorization(authz core.Authorization, regID int) (core.Authorization, error) {
|
||||
authz.RegID = regID
|
||||
return authz, nil
|
||||
}
|
||||
|
||||
|
@ -296,7 +296,7 @@ func TestChallenge(t *testing.T) {
|
|||
URI: core.AcmeURL(*challengeURL),
|
||||
},
|
||||
},
|
||||
Key: key,
|
||||
RegID: 0,
|
||||
}
|
||||
|
||||
wfe.Challenge(authz, responseWriter, &http.Request{
|
||||
|
@ -500,7 +500,7 @@ func TestAuthorization(t *testing.T) {
|
|||
Body: makeBody(signRequest(t, "{\"identifier\":{\"type\":\"dns\",\"value\":\"test.com\"}}")),
|
||||
})
|
||||
|
||||
test.AssertEquals(t, responseWriter.Body.String(), "{\"identifier\":{\"type\":\"dns\",\"value\":\"test.com\"},\"key\":{\"kty\":\"RSA\",\"n\":\"z2NsNdHeqAiGdPP8KuxfQXat_uatOK9y12SyGpfKw1sfkizBIsNxERjNDke6Wp9MugN9srN3sr2TDkmQ-gK8lfWo0v1uG_QgzJb1vBdf_hH7aejgETRGLNJZOdaKDsyFnWq1WGJq36zsHcd0qhggTk6zVwqczSxdiWIAZzEakIUZ13KxXvoepYLY0Q-rEEQiuX71e4hvhfeJ4l7m_B-awn22UUVvo3kCqmaRlZT-36vmQhDGoBsoUo1KBEU44jfeK5PbNRk7vDJuH0B7qinr_jczHcvyD-2TtPzKaCioMtNh_VZbPNDaG67sYkQlC15-Ff3HPzKKJW2XvkVG91qMvQ\",\"e\":\"AAEAAQ\"},\"expires\":\"0001-01-01T00:00:00Z\"}")
|
||||
test.AssertEquals(t, responseWriter.Body.String(), "{\"identifier\":{\"type\":\"dns\",\"value\":\"test.com\"},\"expires\":\"0001-01-01T00:00:00Z\"}")
|
||||
|
||||
var authz core.Authorization
|
||||
err := json.Unmarshal([]byte(responseWriter.Body.String()), &authz)
|
||||
|
|
Loading…
Reference in New Issue