1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
package nosql
import (
"context"
"encoding/base64"
"time"
"github.com/pkg/errors"
"github.com/smallstep/certificates/acme"
"github.com/smallstep/nosql"
"github.com/smallstep/nosql/database"
)
// dbNonce contains nonce metadata used in the ACME protocol.
type dbNonce struct {
ID string
CreatedAt time.Time
DeletedAt time.Time
}
// CreateNonce creates, stores, and returns an ACME replay-nonce.
// Implements the acme.DB interface.
func (db *DB) CreateNonce(ctx context.Context) (acme.Nonce, error) {
_id, err := randID()
if err != nil {
return "", err
}
id := base64.RawURLEncoding.EncodeToString([]byte(_id))
n := &dbNonce{
ID: id,
CreatedAt: clock.Now(),
}
if err := db.save(ctx, id, n, nil, "nonce", nonceTable); err != nil {
return "", err
}
return acme.Nonce(id), nil
}
// DeleteNonce verifies that the nonce is valid (by checking if it exists),
// and if so, consumes the nonce resource by deleting it from the database.
func (db *DB) DeleteNonce(ctx context.Context, nonce acme.Nonce) error {
err := db.db.Update(&database.Tx{
Operations: []*database.TxEntry{
{
Bucket: nonceTable,
Key: []byte(nonce),
Cmd: database.Get,
},
{
Bucket: nonceTable,
Key: []byte(nonce),
Cmd: database.Delete,
},
},
})
switch {
case nosql.IsErrNotFound(err):
return acme.NewError(acme.ErrorBadNonceType, "nonce %s not found", string(nonce))
case err != nil:
return errors.Wrapf(err, "error deleting nonce %s", string(nonce))
default:
return nil
}
}
|