2021-02-25 18:24:24 +00:00
package acme
import (
2021-03-01 06:49:20 +00:00
"crypto"
"encoding/base64"
2021-02-25 18:24:24 +00:00
"encoding/json"
2021-07-17 15:35:44 +00:00
"time"
2021-02-25 18:24:24 +00:00
"go.step.sm/crypto/jose"
)
// Account is a subset of the internal account type containing only those
// attributes required for responses in the ACME protocol.
type Account struct {
2021-07-17 17:02:47 +00:00
ID string ` json:"-" `
Key * jose . JSONWebKey ` json:"-" `
Contact [ ] string ` json:"contact,omitempty" `
Status Status ` json:"status" `
OrdersURL string ` json:"orders" `
ExternalAccountBinding interface { } ` json:"externalAccountBinding,omitempty" `
2021-02-25 18:24:24 +00:00
}
// ToLog enables response logging.
func ( a * Account ) ToLog ( ) ( interface { } , error ) {
b , err := json . Marshal ( a )
if err != nil {
2021-03-05 07:10:46 +00:00
return nil , WrapErrorISE ( err , "error marshaling account for logging" )
2021-02-25 18:24:24 +00:00
}
return string ( b ) , nil
}
// IsValid returns true if the Account is valid.
func ( a * Account ) IsValid ( ) bool {
2021-02-28 18:09:06 +00:00
return Status ( a . Status ) == StatusValid
2021-02-25 18:24:24 +00:00
}
2021-03-01 06:49:20 +00:00
// KeyToID converts a JWK to a thumbprint.
func KeyToID ( jwk * jose . JSONWebKey ) ( string , error ) {
kid , err := jwk . Thumbprint ( crypto . SHA256 )
if err != nil {
2021-03-05 07:10:46 +00:00
return "" , WrapErrorISE ( err , "error generating jwk thumbprint" )
2021-03-01 06:49:20 +00:00
}
return base64 . RawURLEncoding . EncodeToString ( kid ) , nil
}
2021-07-17 15:35:44 +00:00
2021-10-08 11:18:23 +00:00
// ExternalAccountKey is an ACME External Account Binding key.
2021-07-17 15:35:44 +00:00
type ExternalAccountKey struct {
2022-01-07 15:59:55 +00:00
ID string ` json:"id" `
ProvisionerID string ` json:"provisionerID" `
Reference string ` json:"reference" `
AccountID string ` json:"-" `
KeyBytes [ ] byte ` json:"-" `
CreatedAt time . Time ` json:"createdAt" `
BoundAt time . Time ` json:"boundAt,omitempty" `
2021-07-17 15:35:44 +00:00
}
2021-07-17 17:02:47 +00:00
2021-10-08 11:18:23 +00:00
// AlreadyBound returns whether this EAK is already bound to
// an ACME Account or not.
2021-07-22 21:48:41 +00:00
func ( eak * ExternalAccountKey ) AlreadyBound ( ) bool {
return ! eak . BoundAt . IsZero ( )
}
2021-10-08 11:18:23 +00:00
// BindTo binds the EAK to an Account.
// It returns an error if it's already bound.
func ( eak * ExternalAccountKey ) BindTo ( account * Account ) error {
if eak . AlreadyBound ( ) {
return NewError ( ErrorUnauthorizedType , "external account binding key with id '%s' was already bound to account '%s' on %s" , eak . ID , eak . AccountID , eak . BoundAt )
}
2021-07-17 17:02:47 +00:00
eak . AccountID = account . ID
eak . BoundAt = time . Now ( )
2021-07-22 21:48:41 +00:00
eak . KeyBytes = [ ] byte { } // clearing the key bytes; can only be used once
2021-10-08 11:18:23 +00:00
return nil
2021-07-17 17:02:47 +00:00
}