Skip to content

Commit

Permalink
refactor and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mohammed90 committed Sep 17, 2023
1 parent 37c6f1c commit ce51659
Show file tree
Hide file tree
Showing 4 changed files with 453 additions and 31 deletions.
36 changes: 6 additions & 30 deletions modules/caddypki/adminapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,35 +177,6 @@ func (a *adminAPI) handleCACerts(w http.ResponseWriter, r *http.Request) error {
return nil
}

type csrRequest struct {
// Custom name assigned to the CSR key. If empty, UUID is generated and assigned.
ID string `json:"id,omitempty"`

// Customization knobs of the generated/loaded key, if desired.
// If empty, sane defaults will be managed internally without exposing their details
// to the user. At the moment, the default parameters are:
// {
// "type": "EC",
// "curve": "P-256"
// }
Key *struct {
// The key type to be used for signing the CSR. The possible types are:
// EC, RSA, and OKP.
Type string `json:"type"`

// The curve to use with key types EC and OKP.
// If the Type is OKP, then acceptable curves are: Ed25519, or X25519
// If the Type is EC, then acceptable curves are: P-256, P-384, or P-521
Curve string `json:"curve,omitempty"`

// Only used with RSA keys and accepts minimum of 2048.
Size int `json:"size,omitempty"`
} `json:"key,omitempty"`

// SANs is a list of subject alternative names for the certificate.
SANs []string `json:"sans"`
}

func (a *adminAPI) handleCSRGeneration(w http.ResponseWriter, r *http.Request) error {
if r.Method != http.MethodPost {
return caddy.APIError{
Expand Down Expand Up @@ -234,7 +205,12 @@ func (a *adminAPI) handleCSRGeneration(w http.ResponseWriter, r *http.Request) e
if len(csrReq.ID) == 0 {
csrReq.ID = uuid.New().String()
}

if err := csrReq.validate(); err != nil {
return caddy.APIError{
HTTPStatus: http.StatusBadRequest,
Err: fmt.Errorf("invalid CSR request: %v", err),
}
}
// Generate the CSR
csr, err := ca.generateCSR(csrReq)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion modules/caddypki/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ func (ca CA) generateCSR(csrReq csrRequest) (csr *x509.CertificateRequest, err e
return nil, err
}
} else {
signer, err = keyutil.GenerateSigner(csrReq.Key.Type, csrReq.Key.Curve, csrReq.Key.Size)
signer, err = keyutil.GenerateSigner(csrReq.Key.Type.String(), csrReq.Key.Curve.String(), csrReq.Key.Size)
if err != nil {
return nil, err
}
Expand Down
154 changes: 154 additions & 0 deletions modules/caddypki/csr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package caddypki

import (
"encoding/json"
"fmt"
)

// The key type to be used for signing the CSR. The possible types are:
// EC, RSA, and OKP.
type keyType string

const (
keyTypeEC keyType = "EC"
keyTypeRSA keyType = "RSA"
keyTypeOKP keyType = "OKP"
)

var stringToKey = map[string]keyType{
"EC": keyTypeEC,
"RSA": keyTypeRSA,
"OKP": keyTypeOKP,
}

func (kt *keyType) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
switch s {
case string(keyTypeEC), string(keyTypeRSA), string(keyTypeOKP):
*kt = stringToKey[s]
default:
return fmt.Errorf("unknown key type: %s", s)
}
return nil
}

Check failure on line 36 in modules/caddypki/csr.go

View workflow job for this annotation

GitHub Actions / lint (ubuntu-latest)

File is not `gofumpt`-ed (gofumpt)
func (kt keyType) String() string {
return string(kt)
}

// The curve to use with key types EC and OKP.
// If the Type is OKP, then acceptable curves are: Ed25519, or X25519
// If the Type is EC, then acceptable curves are: P-256, P-384, or P-521
type curve string

const (
curveEd25519 curve = "Ed25519"
curveX25519 curve = "X25519"
curveP256 curve = "P-256"
curveP384 curve = "P-384"
curveP521 curve = "P-521"
)

var stringToCurve = map[string]curve{
"Ed25519": curveEd25519,
"X25519": curveX25519,
"P-256": curveP256,
"P-384": curveP384,
"P-521": curveP521,
}

func (c *curve) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
switch s {
case string(curveEd25519), string(curveX25519), string(curveP256), string(curveP384), string(curveP521):
*c = stringToCurve[s]
default:
return fmt.Errorf("unknown curve: %s", s)
}
return nil
}

Check failure on line 74 in modules/caddypki/csr.go

View workflow job for this annotation

GitHub Actions / lint (ubuntu-latest)

File is not `gofumpt`-ed (gofumpt)
func (c curve) String() string {
return string(c)
}

type keyParameters struct {
// The key type to be used for signing the CSR. The possible types are:
// EC, RSA, and OKP.
Type keyType `json:"type"`

// The curve to use with key types EC and OKP.
// If the Type is OKP, then acceptable curves are: Ed25519, or X25519
// If the Type is EC, then acceptable curves are: P-256, P-384, or P-521
Curve curve `json:"curve,omitempty"`

// Only used with RSA keys and accepts minimum of 2048.
Size int `json:"size,omitempty"`
}

func (kp *keyParameters) validate() error {
if kp == nil {
return nil
}

if kp.Type == keyTypeRSA {
if kp.Size < 2048 {
return fmt.Errorf("minimum RSA key size is 2048 bits: %v", kp.Size)
}
}
if kp.Type == keyTypeEC {
switch kp.Curve {
case curveP256, curveP384, curveP521:
return nil
default:
return fmt.Errorf("unrecognized EC curve: %v", kp.Curve)
}
}
if kp.Type == keyTypeOKP {
switch kp.Curve {
case curveEd25519, curveX25519:
return nil
default:
return fmt.Errorf("unrecognized OKP curve: %v", kp.Curve)
}
}
return nil
}

type csrRequest struct {
// Custom name assigned to the CSR key. If empty, UUID is generated and assigned.
ID string `json:"id,omitempty"`

// Customization knobs of the generated/loaded key, if desired. The format is:
// {
// // Valid values for type are: EC, RSA, and OKP.
// "type": "",
//
// // The curve to use with key types EC and OKP.
// // If the Type is OKP, then acceptable curves are: Ed25519, or X25519
// // If the Type is EC, then acceptable curves are: P-256, P-384, or P-521
// "curve": "",
//
// // Only used with RSA keys and accepts minimum of 2048.
// "size": 0
// }
//
// If empty, sane defaults will be managed internally without exposing their details
// to the user. At the moment, the default parameters are:
// {
// "type": "EC",
// "curve": "P-256"
// }
Key *keyParameters `json:"key,omitempty"`

// SANs is a list of subject alternative names for the certificate.
SANs []string `json:"sans"`
}

func (c csrRequest) validate() error {
return c.Key.validate()
}
Loading

0 comments on commit ce51659

Please sign in to comment.