Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NOISSUE - Refactor CSR generation #55

Merged
merged 22 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 15 additions & 48 deletions api/http/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,71 +314,38 @@ func createCSREndpoint(svc certs.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(createCSRReq)
if err := req.validate(); err != nil {
return createCSRRes{created: false}, err

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of create csr endpoint, users can create csrs using openssl

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its an alternative if the user doesn't want to use openssl. The idea is to make certs more generic.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move to cli tool, no need to call an online api to create a CSR

return createCSRRes{}, err
}

csr, err := svc.CreateCSR(ctx, req.Metadata, req.Metadata.EntityID, req.privKey)
csr, err := svc.CreateCSR(ctx, req.Metadata, req.privKey)
if err != nil {
return createCSRRes{created: false}, err
return createCSRRes{}, err
}

return createCSRRes{
created: true,
CSR: csr,
CSR: string(csr.CSR),
}, nil
}
}

func signCSREndpoint(svc certs.Service) endpoint.Endpoint {
func issueFromCSREndpoint(svc certs.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(SignCSRReq)
req := request.(IssueFromCSRReq)
if err := req.validate(); err != nil {
return signCSRRes{signed: false}, err
return issueFromCSRRes{}, err
}

err = svc.SignCSR(ctx, req.csrID, req.approve)
cert, err := svc.IssueFromCSR(ctx, req.entityID, req.ttl, certs.CSR{CSR: []byte(req.CSR), PrivateKey: []byte(req.PrivateKey)})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the private key uploaded,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need the private key when signing the certificate, you only need the public key. the point of this endpoint is for users who want to keep their private keys secure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me make that change

if err != nil {
return signCSRRes{signed: false}, err
return issueFromCSRRes{}, err
}

return signCSRRes{
signed: true,
}, nil
}
}

func retrieveCSREndpoint(svc certs.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(retrieveCSRReq)
if err := req.validate(); err != nil {
return retrieveCSRRes{}, err
}

csr, err := svc.RetrieveCSR(ctx, req.csrID)
if err != nil {
return retrieveCSRRes{}, err
}

return retrieveCSRRes{
CSR: csr,
}, nil
}
}

func listCSRsEndpoint(svc certs.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(listCSRsReq)
if err := req.validate(); err != nil {
return listCSRsRes{}, err
}

cp, err := svc.ListCSRs(ctx, req.pm)
if err != nil {
return listCSRsRes{}, err
}

return listCSRsRes{
cp,
return issueFromCSRRes{
SerialNumber: cert.SerialNumber,
Certificate: string(cert.Certificate),
Revoked: cert.Revoked,
ExpiryTime: cert.ExpiryTime,
EntityID: cert.EntityID,
}, nil
}
}
7 changes: 5 additions & 2 deletions api/http/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ var (
// ErrMissingCN indicates missing common name.
ErrMissingCN = errors.New("missing common name")

// ErrMissingStatus indicates missing status.
ErrMissingStatus = errors.New("missing status")
// ErrMissingCSR indicates missing csr.
ErrMissingCSR = errors.New("missing CSR")

// ErrMissingPrivKey indicates missing csr.
ErrMissingPrivKey = errors.New("missing private key")
)
49 changes: 17 additions & 32 deletions api/http/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
package http

import (
"crypto/rsa"

"github.com/absmach/certs"
"github.com/absmach/certs/errors"
"golang.org/x/crypto/ocsp"
Expand Down Expand Up @@ -92,48 +90,35 @@ func (req ocspReq) validate() error {

type createCSRReq struct {
Metadata certs.CSRMetadata `json:"metadata"`
PrivateKey []byte `json:"private_Key"`
privKey *rsa.PrivateKey
PrivateKey string `json:"private_key"`
privKey any
}

func (req createCSRReq) validate() error {
if req.Metadata.EntityID == "" {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingEntityID)
}
return nil
}

type SignCSRReq struct {
csrID string
approve bool
}

func (req SignCSRReq) validate() error {
if req.csrID == "" {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingEntityID)
if req.Metadata.CommonName == "" {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingCN)
}

return nil
}

type listCSRsReq struct {
pm certs.PageMetadata
}

func (req listCSRsReq) validate() error {
if req.pm.Status.String() == "" {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingStatus)
if len(req.PrivateKey) == 0 {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingPrivKey)
}
return nil
}

type retrieveCSRReq struct {
csrID string
type IssueFromCSRReq struct {
entityID string
ttl string
CSR string `json:"csr"`
PrivateKey string `json:"private_key"`
}

func (req retrieveCSRReq) validate() error {
if req.csrID == "" {
func (req IssueFromCSRReq) validate() error {
if req.entityID == "" {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingEntityID)
}
if len(req.CSR) == 0 {
return errors.Wrap(certs.ErrMalformedEntity, ErrMissingCSR)
}

return nil
}
56 changes: 11 additions & 45 deletions api/http/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http"
"time"

"github.com/absmach/certs"
"golang.org/x/crypto/ocsp"
)

Expand Down Expand Up @@ -204,16 +203,11 @@ type fileDownloadRes struct {
}

type createCSRRes struct {
certs.CSR
created bool
CSR string `json:"csr"`
}

func (res createCSRRes) Code() int {
if res.created {
return http.StatusCreated
}

return http.StatusNoContent
return http.StatusCreated
}

func (res createCSRRes) Headers() map[string]string {
Expand All @@ -224,50 +218,22 @@ func (res createCSRRes) Empty() bool {
return false
}

type signCSRRes struct {
signed bool
}

func (res signCSRRes) Code() int {
return http.StatusOK
}

func (res signCSRRes) Headers() map[string]string {
return map[string]string{}
}

func (res signCSRRes) Empty() bool {
return true
}

type listCSRsRes struct {
certs.CSRPage
}

func (res listCSRsRes) Code() int {
return http.StatusOK
}

func (res listCSRsRes) Headers() map[string]string {
return map[string]string{}
}

func (res listCSRsRes) Empty() bool {
return false
}

type retrieveCSRRes struct {
certs.CSR
type issueFromCSRRes struct {
SerialNumber string `json:"serial_number"`
Certificate string `json:"certificate,omitempty"`
Revoked bool `json:"revoked"`
ExpiryTime time.Time `json:"expiry_time"`
EntityID string `json:"entity_id"`
}

func (res retrieveCSRRes) Code() int {
func (res issueFromCSRRes) Code() int {
return http.StatusOK
}

func (res retrieveCSRRes) Headers() map[string]string {
func (res issueFromCSRRes) Headers() map[string]string {
return map[string]string{}
}

func (res retrieveCSRRes) Empty() bool {
func (res issueFromCSRRes) Empty() bool {
return false
}
Loading
Loading