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

Conversation

nyagamunene
Copy link
Contributor

@nyagamunene nyagamunene commented Nov 28, 2024

What type of PR is this?

This is a refactor because it changes the following functionality: it removes CSR repository.

What does this do?

It removes CSR repository.

Which issue(s) does this PR fix/relate to?

N/A

Have you included tests for your changes?

Yes

Did you document any new/modified features?

No

Notes

Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
@nyagamunene nyagamunene marked this pull request as ready for review December 2, 2024 08:31
Copy link

@SammyOina SammyOina left a comment

Choose a reason for hiding this comment

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

Method should be IssueFromCSR with csr as argument and the response should be the issued certificate

@nyagamunene nyagamunene self-assigned this Dec 2, 2024
@@ -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

Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
}

csr, err := svc.CreateCSR(ctx, req.Metadata, req.Metadata.EntityID, req.privKey)
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

Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
SammyOina
SammyOina previously approved these changes Dec 3, 2024
cli/certs.go Outdated
Comment on lines 392 to 397
case *rsa.PrivateKey:
signer = key
case *ecdsa.PrivateKey:
signer = key
case ed25519.PrivateKey:
signer = key
Copy link
Contributor

Choose a reason for hiding this comment

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

Group cases:

case *rsa.PrivateKey, *ecdsa.PrivateKey, *ed25519.PrivateKey:

cli/certs.go Outdated
}
return CreateCSR(metadata, parsedKey)
default:
return certs.CSR{}, errors.NewSDKError(errors.Wrap(ErrCreateEntity, errors.New("unsupported private key type")))
Copy link
Contributor

@dborovcanin dborovcanin Dec 6, 2024

Choose a reason for hiding this comment

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

Extract errors.New("unsupported...") to a variable.

cli/certs.go Outdated
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
case certs.ECPrivateKey:
privateKey, err = x509.ParseECPrivateKey(block.Bytes)
case certs.PrivateKey, "PKCS8 PRIVATE KEY":
Copy link
Contributor

Choose a reason for hiding this comment

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

Extract string literal to constant. Please double-check to see if there is no such constant somewhere in imported packages.

cli/certs.go Outdated
privateKey, err = x509.ParseECPrivateKey(block.Bytes)
case certs.PrivateKey, "PKCS8 PRIVATE KEY":
privateKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
case "ED25519 PRIVATE KEY":
Copy link
Contributor

Choose a reason for hiding this comment

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

Same.

cli/certs.go Outdated
case "ED25519 PRIVATE KEY":
privateKey, err = x509.ParsePKCS8PrivateKey(block.Bytes)
default:
err = errors.New("unsupported private key type")
Copy link
Contributor

Choose a reason for hiding this comment

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

Use error var.

cli/certs.go Outdated
err = errors.New("unsupported private key type")
}
if err != nil {
return nil, errors.New("failed to parse key")
Copy link
Contributor

Choose a reason for hiding this comment

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

Extract error to var.

Signed-off-by: nyagamunene <[email protected]>
service.go Outdated
// The certificate is then stored in the repository using the CreateCert method.
// If the root CA is not found, it returns an error.
func (s *service) IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, options SubjectOptions, key ...any) (Certificate, error) {
var privKey any
Copy link
Contributor

Choose a reason for hiding this comment

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

Use var privKey crypto.PrivateKey instead.

certs.go Outdated
@@ -217,7 +158,7 @@ type Service interface {
RetrieveCAToken(ctx context.Context) (string, error)

// IssueCert issues a certificate from the database.
IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions, privKey ...*rsa.PrivateKey) (Certificate, error)
IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions, privKey ...any) (Certificate, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Use privKey crypto.PrivateKey instead.

certs.go Outdated
@@ -217,7 +159,7 @@ type Service interface {
RetrieveCAToken(ctx context.Context) (string, error)

// IssueCert issues a certificate from the database.
IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions, privKey ...*rsa.PrivateKey) (Certificate, error)
IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions, privKey ...crypto.PrivateKey) (Certificate, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason for this to be a variadic function? Can we just use have

	IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions, privKey crypto.PrivateKey) (Certificate, error)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes there is a reason. It because its also been used by the issueCSR method to issue certificates since they user needs to provide their own private key

Signed-off-by: nyagamunene <[email protected]>
Signed-off-by: nyagamunene <[email protected]>
service.go Outdated
Comment on lines 96 to 100
// issueCert generates and issues a certificate for a given backendID.
// It uses the RSA algorithm to generate a private key, and then creates a certificate
// using the provided template and the generated private key.
// The certificate is then stored in the repository using the CreateCert method.
// If the root CA is not found, it returns an error.
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove duplicate comments.

service.go Outdated
// using the provided template and the generated private key.
// The certificate is then stored in the repository using the CreateCert method.
// If the root CA is not found, it returns an error.
func (s *service) IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, options SubjectOptions, key crypto.PrivateKey) (Certificate, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's extract issuing certs to unexported method:

 (s *service) issue(ctx context.Context, entityID, ttl string, ipAddrs []string, options SubjectOptions, pubKey crypto.PublicKey, privKey crypto.PrivateKey) (Certificate, error)

you can call from both IssuseCert and IssueFromCSR so that you can make the interface cleaner:

IssueCert(ctx context.Context, entityID, ttl string, ipAddrs []string, option SubjectOptions) (Certificate, error)

So we do not have any key params when issuing certs (so you don't have to use nil as the indicator you want to create a key pair).

service.go Outdated
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return Certificate{}, err
}

if s.intermediateCA.Certificate == nil || s.intermediateCA.PrivateKey == nil {
return Certificate{}, ErrIntermediateCANotFound
subject := s.getSubject(options)
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename to subjectFromOpts. Also, no need to make it a service method, it's just an unexported function: func subjectFromOpts(opts SubjectOptions) pkix.Name.

@dborovcanin dborovcanin merged commit 04dbd2c into absmach:main Dec 9, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

3 participants