2021-07-23 13:41:24 +00:00
package api
import (
2021-12-09 08:36:03 +00:00
"fmt"
2021-07-23 13:41:24 +00:00
"net/http"
2022-03-30 08:22:22 +00:00
"go.step.sm/linkedca"
2022-04-11 13:25:55 +00:00
"google.golang.org/protobuf/types/known/timestamppb"
2022-03-30 08:22:22 +00:00
2022-04-11 13:25:55 +00:00
"github.com/smallstep/certificates/acme"
2022-03-30 08:22:22 +00:00
"github.com/smallstep/certificates/api/render"
2021-07-23 13:41:24 +00:00
"github.com/smallstep/certificates/authority/admin"
2022-01-07 15:59:55 +00:00
)
2021-07-23 13:41:24 +00:00
// CreateExternalAccountKeyRequest is the type for POST /admin/acme/eab requests
type CreateExternalAccountKeyRequest struct {
2021-10-08 12:29:44 +00:00
Reference string ` json:"reference" `
2021-07-23 13:41:24 +00:00
}
2021-09-16 21:09:24 +00:00
// Validate validates a new ACME EAB Key request body.
2021-08-27 10:39:37 +00:00
func ( r * CreateExternalAccountKeyRequest ) Validate ( ) error {
2021-12-09 08:36:03 +00:00
if len ( r . Reference ) > 256 { // an arbitrary, but sensible (IMO), limit
return fmt . Errorf ( "reference length %d exceeds the maximum (256)" , len ( r . Reference ) )
}
2021-08-27 10:39:37 +00:00
return nil
2021-07-23 13:41:24 +00:00
}
// GetExternalAccountKeysResponse is the type for GET /admin/acme/eab responses
type GetExternalAccountKeysResponse struct {
2022-01-24 13:03:56 +00:00
EAKs [ ] * linkedca . EABKey ` json:"eaks" `
NextCursor string ` json:"nextCursor" `
2021-07-23 13:41:24 +00:00
}
2021-10-08 12:29:44 +00:00
// requireEABEnabled is a middleware that ensures ACME EAB is enabled
// before serving requests that act on ACME EAB credentials.
2022-05-06 20:21:41 +00:00
func requireEABEnabled ( next http . HandlerFunc ) http . HandlerFunc {
2021-10-08 12:29:44 +00:00
return func ( w http . ResponseWriter , r * http . Request ) {
2022-01-07 15:59:55 +00:00
ctx := r . Context ( )
2022-05-05 09:05:57 +00:00
prov := linkedca . MustProvisionerFromContext ( ctx )
2022-03-30 16:21:25 +00:00
2022-04-21 11:21:06 +00:00
acmeProvisioner := prov . GetDetails ( ) . GetACME ( )
2022-03-30 16:21:25 +00:00
if acmeProvisioner == nil {
render . Error ( w , admin . NewErrorISE ( "error getting ACME details for provisioner '%s'" , prov . GetName ( ) ) )
2021-10-08 12:29:44 +00:00
return
}
2021-09-16 21:09:24 +00:00
2022-03-30 16:21:25 +00:00
if ! acmeProvisioner . RequireEab {
render . Error ( w , admin . NewError ( admin . ErrorBadRequestType , "ACME EAB not enabled for provisioner '%s'" , prov . GetName ( ) ) )
2021-10-08 12:29:44 +00:00
return
}
2022-04-27 18:59:32 +00:00
2022-03-31 14:12:29 +00:00
next ( w , r )
2021-09-16 21:09:24 +00:00
}
2022-01-07 15:59:55 +00:00
}
2022-05-06 21:11:10 +00:00
// ACMEAdminResponder is responsible for writing ACME admin responses
type ACMEAdminResponder interface {
2022-02-08 12:26:30 +00:00
GetExternalAccountKeys ( w http . ResponseWriter , r * http . Request )
CreateExternalAccountKey ( w http . ResponseWriter , r * http . Request )
DeleteExternalAccountKey ( w http . ResponseWriter , r * http . Request )
2021-09-16 21:09:24 +00:00
}
2022-05-06 21:11:10 +00:00
// acmeAdminResponder implements ACMEAdminResponder.
type acmeAdminResponder struct { }
2021-07-23 13:41:24 +00:00
2022-02-08 12:26:30 +00:00
// NewACMEAdminResponder returns a new ACMEAdminResponder
2022-05-06 21:11:10 +00:00
func NewACMEAdminResponder ( ) ACMEAdminResponder {
return & acmeAdminResponder { }
2021-07-23 13:41:24 +00:00
}
2022-02-08 12:26:30 +00:00
// GetExternalAccountKeys writes the response for the EAB keys GET endpoint
2022-05-06 21:11:10 +00:00
func ( h * acmeAdminResponder ) GetExternalAccountKeys ( w http . ResponseWriter , r * http . Request ) {
2022-03-30 08:22:22 +00:00
render . Error ( w , admin . NewError ( admin . ErrorNotImplementedType , "this functionality is currently only available in Certificate Manager: https://u.step.sm/cm" ) )
2021-08-27 12:10:00 +00:00
}
2022-02-08 12:26:30 +00:00
// CreateExternalAccountKey writes the response for the EAB key POST endpoint
2022-05-06 21:11:10 +00:00
func ( h * acmeAdminResponder ) CreateExternalAccountKey ( w http . ResponseWriter , r * http . Request ) {
2022-03-30 08:22:22 +00:00
render . Error ( w , admin . NewError ( admin . ErrorNotImplementedType , "this functionality is currently only available in Certificate Manager: https://u.step.sm/cm" ) )
2022-02-08 12:26:30 +00:00
}
2021-08-27 14:58:04 +00:00
2022-02-08 12:26:30 +00:00
// DeleteExternalAccountKey writes the response for the EAB key DELETE endpoint
2022-05-06 21:11:10 +00:00
func ( h * acmeAdminResponder ) DeleteExternalAccountKey ( w http . ResponseWriter , r * http . Request ) {
2022-03-30 08:22:22 +00:00
render . Error ( w , admin . NewError ( admin . ErrorNotImplementedType , "this functionality is currently only available in Certificate Manager: https://u.step.sm/cm" ) )
2021-07-23 13:41:24 +00:00
}
2022-04-11 13:25:55 +00:00
func eakToLinked ( k * acme . ExternalAccountKey ) * linkedca . EABKey {
if k == nil {
return nil
}
eak := & linkedca . EABKey {
Id : k . ID ,
2022-04-26 08:15:17 +00:00
HmacKey : k . HmacKey ,
2022-04-11 13:25:55 +00:00
Provisioner : k . ProvisionerID ,
Reference : k . Reference ,
Account : k . AccountID ,
CreatedAt : timestamppb . New ( k . CreatedAt ) ,
BoundAt : timestamppb . New ( k . BoundAt ) ,
}
if k . Policy != nil {
eak . Policy = & linkedca . Policy {
X509 : & linkedca . X509Policy {
Allow : & linkedca . X509Names { } ,
Deny : & linkedca . X509Names { } ,
} ,
}
eak . Policy . X509 . Allow . Dns = k . Policy . X509 . Allowed . DNSNames
eak . Policy . X509 . Allow . Ips = k . Policy . X509 . Allowed . IPRanges
eak . Policy . X509 . Deny . Dns = k . Policy . X509 . Denied . DNSNames
eak . Policy . X509 . Deny . Ips = k . Policy . X509 . Denied . IPRanges
2022-04-29 13:08:19 +00:00
eak . Policy . X509 . AllowWildcardNames = k . Policy . X509 . AllowWildcardNames
2022-04-11 13:25:55 +00:00
}
return eak
}
func linkedEAKToCertificates ( k * linkedca . EABKey ) * acme . ExternalAccountKey {
if k == nil {
return nil
}
eak := & acme . ExternalAccountKey {
ID : k . Id ,
ProvisionerID : k . Provisioner ,
Reference : k . Reference ,
AccountID : k . Account ,
2022-04-26 08:15:17 +00:00
HmacKey : k . HmacKey ,
2022-04-11 13:25:55 +00:00
CreatedAt : k . CreatedAt . AsTime ( ) ,
BoundAt : k . BoundAt . AsTime ( ) ,
}
2022-04-21 14:18:55 +00:00
if policy := k . GetPolicy ( ) ; policy != nil {
eak . Policy = & acme . Policy { }
if x509 := policy . GetX509 ( ) ; x509 != nil {
eak . Policy . X509 = acme . X509Policy { }
if allow := x509 . GetAllow ( ) ; allow != nil {
eak . Policy . X509 . Allowed = acme . PolicyNames { }
eak . Policy . X509 . Allowed . DNSNames = allow . Dns
eak . Policy . X509 . Allowed . IPRanges = allow . Ips
}
if deny := x509 . GetDeny ( ) ; deny != nil {
eak . Policy . X509 . Denied = acme . PolicyNames { }
eak . Policy . X509 . Denied . DNSNames = deny . Dns
eak . Policy . X509 . Denied . IPRanges = deny . Ips
}
2022-04-29 13:08:19 +00:00
eak . Policy . X509 . AllowWildcardNames = x509 . AllowWildcardNames
2022-04-21 14:18:55 +00:00
}
2022-04-11 13:25:55 +00:00
}
return eak
}