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

Implement Certificate Revocation List (1) #1383

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Danielius1922
Copy link
Member

No description provided.

Copy link
Contributor

coderabbitai bot commented Oct 27, 2024

Important

Review skipped

More than 25% of the files skipped due to max files limit. The review is being skipped to prevent a low-quality review.

37 files out of 119 files are above the max files limit of 75. Please upgrade to Pro plan to get higher limits.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes in this pull request include significant updates across various files related to the certificate authority service. Key modifications involve enhancements to Nginx configuration for improved routing and SSL handling, updates to protocol documentation, and the introduction of new fields in data structures for better tracking of certificate statuses. Additionally, several new methods and validation checks have been implemented, particularly for handling revocation lists and signing records. The overall structure and functionality of the service have been refined to support these enhancements effectively.

Changes

File Path Change Summary
bundle/nginx/nginx.conf.template Updated location block to include /certificate-authority alongside /api/v1/sign.
certificate-authority/pb/README.md Expanded method descriptions and added new fields in CredentialStatus.
certificate-authority/pb/doc.html Updated HTML documentation for new fields and method descriptions.
certificate-authority/pb/service.proto Added additional_bindings for HTTP options with new endpoint paths.
certificate-authority/pb/signingRecords.go Introduced Validate method for CredentialStatus and updated validation in SigningRecord.
certificate-authority/pb/signingRecords.proto Added fields serial and issuer_id to CredentialStatus and introduced DeletedSigningRecords.
certificate-authority/pb/signingRecords_test.go Added unit tests for validation logic of CredentialStatus and SigningRecord.
certificate-authority/service/config.go Added ExternalAddress field to HTTPConfig struct and updated validation logic.
certificate-authority/service/config_test.go Introduced TestHTTPConfigValidate for validating HTTPConfig.
certificate-authority/service/grpc/config.go Added CRLConfig type and integrated it into SignerConfig.
certificate-authority/service/grpc/config_test.go Added unit tests for CRLConfig and SignerConfig.
certificate-authority/service/grpc/deleteSigningRecords.go Introduced errDeleteSigningRecords for error handling in deletion logic.
certificate-authority/service/grpc/getSigningRecords.go Simplified GetSigningRecords method to send records without an iterator.
certificate-authority/service/grpc/server.go Added crlServerAddress field to CertificateAuthorityServer.
certificate-authority/service/http/requestHandler.go Enhanced RequestHandler to manage revocation lists based on configuration.
certificate-authority/service/http/revocationList.go Implemented CRL management functionality.
certificate-authority/service/http/revocationList_test.go Added unit tests for revocation list functionality.
certificate-authority/store/cqldb/revocationList.go Implemented revocation list management methods.
certificate-authority/store/mongodb/revocationList.go Added revocation list management methods for MongoDB.
charts/plgd-hub/README.md Enhanced configuration documentation for various services.
device-provisioning-service/pb/service.proto Updated HTTP options for several RPC methods to include body fields.
http-gateway/test/http.go Added AddIssuerID method to RequestBuilder.
pkg/security/certificateSigner/certificateSigner.go Enhanced SignerConfig with CRLDistributionPoints field.
pkg/security/certificateSigner/certificateSigner_test.go Added tests for certificate signing scenarios.

Poem

In the burrow deep, where the code does flow,
Changes abound, like flowers that grow.
With paths now clearer, and records in line,
The rabbit hops proud, for all will be fine!
SSL and routes, all snug in their place,
A joyful leap forward, in this coding race! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

certificate-authority/store/mongodb/revocationList.go Dismissed Show dismissed Hide dismissed
certificate-authority/store/mongodb/revocationList.go Dismissed Show dismissed Hide dismissed
certificate-authority/store/mongodb/revocationList.go Dismissed Show dismissed Hide dismissed
@Danielius1922 Danielius1922 force-pushed the adam/feature/crl-1 branch 2 times, most recently from d3acc56 to 36e6847 Compare October 28, 2024 14:24
@Danielius1922 Danielius1922 marked this pull request as ready for review October 28, 2024 14:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 41

🧹 Outside diff range and nitpick comments (52)
certificate-authority/service/http/config.go (1)

16-16: Consider adding documentation for the CRLEnabled field.

While the field name is self-explanatory, adding a comment would help future maintainers understand its purpose, especially since it's an internal configuration that affects runtime behavior.

+	// CRLEnabled controls whether Certificate Revocation List (CRL) functionality is enabled.
+	// This field is set programmatically and excluded from serialization.
 	CRLEnabled bool `yaml:"-" json:"-"`
certificate-authority/service/grpc/deleteSigningRecords.go (1)

14-27: Enhance security measures for certificate revocation.

Certificate revocation is a security-critical operation. Consider implementing these security enhancements:

  1. Add revocation reason to the request parameters
  2. Implement detailed audit logging
  3. Add specific access control checks for revocation operations

Example enhancements:

type DeleteSigningRecordsRequest struct {
+    reason RevocationReason
+    comment string  // Optional explanation
     // ... existing fields
}

func (s *CertificateAuthorityServer) DeleteSigningRecords(ctx context.Context, req *pb.DeleteSigningRecordsRequest) (*pb.DeletedSigningRecords, error) {
     owner, err := ownerToUUID(ctx, s.ownerClaim)
     if err != nil {
         return nil, s.logger.LogAndReturnError(errDeleteSigningRecords(err))
     }
+    // Log revocation attempt
+    s.logger.Info("Certificate revocation requested",
+        "owner", owner,
+        "reason", req.reason,
+        "comment", req.comment)
     
     count, err := s.store.RevokeSigningRecords(ctx, owner, req)
     if err != nil {
         return nil, s.logger.LogAndReturnError(errDeleteSigningRecords(err))
     }
+    // Log successful revocation
+    s.logger.Info("Certificates revoked successfully",
+        "owner", owner,
+        "count", count)
     
     return &pb.DeletedSigningRecords{
         Count: count,
     }, nil
}
certificate-authority/service/http/signIdentityCertificate_test.go (1)

36-36: Consider adding test cases for certificate revocation scenarios.

While the URI constant is correctly used, since this PR implements Certificate Revocation List functionality, consider adding test cases that verify:

  1. Signing requests for previously revoked certificates
  2. Signing requests with revocation status checks

Would you like me to help draft additional test cases for these scenarios?

certificate-authority/service/http/requestHandler.go (1)

22-24: Consider adding field documentation.

While the field types are appropriate, adding documentation comments for the new fields would improve code maintainability:

 type RequestHandler struct {
 	config *Config
 	mux    *runtime.ServeMux
 
+	// cas handles certificate authority operations via gRPC
 	cas   *grpcService.CertificateAuthorityServer
+	// store provides persistence for certificate-related data
 	store store.Store
 }
certificate-authority/test/revocationList.go (2)

1-16: Add package documentation.

Consider adding a package comment that describes the purpose and usage of these test utilities. This will help other developers understand how to use these helpers effectively in their tests.

+// Package test provides utilities for testing Certificate Revocation List (CRL) functionality.
+// It includes helpers for generating test data, managing certificate serials, and validating
+// revocation list operations.
 package test

23-42: Add documentation and input validation.

The helper functions would benefit from proper documentation and input validation to improve usability and robustness.

Consider these improvements:

+// GetIssuerID generates a formatted issuer ID using a zero-padded 12-digit suffix.
+// The format follows: "49000000-0000-0000-0000-XXXXXXXXXXXX"
 func GetIssuerID(i int) string {
+	if i < 0 {
+		i = 0
+	}
 	return fmt.Sprintf("49000000-0000-0000-0000-%012d", i)
 }

+// GetCertificateSerial generates or retrieves a unique certificate serial number
+// for the given index. The serial numbers are cached to ensure consistency.
 func GetCertificateSerial(i int) string {
 	// ... existing code ...
 }

+// GetCertificate creates a test RevocationListCertificate with the specified
+// certificate index, revocation time, and expiration time.
 func GetCertificate(c int, rev, exp time.Time) *store.RevocationListCertificate {
+	if rev.After(exp) {
+		rev = exp
+	}
 	return &store.RevocationListCertificate{
 		Serial:     GetCertificateSerial(c),
 		ValidUntil: pkgTime.UnixNano(exp),
 		Revocation: pkgTime.UnixNano(rev),
 	}
 }
certificate-authority/pb/service.proto (2)

41-44: LGTM! Consider documenting the dual endpoints.

The additional binding provides a more service-oriented path while maintaining backward compatibility.

Consider adding a comment explaining the purpose of dual endpoints and any future deprecation plans for the legacy endpoint.


Line range hint 1-91: Document CRL implementation details.

As this is part 1 of the Certificate Revocation List implementation, consider:

  1. Adding OpenAPI documentation for CRL-specific endpoints
  2. Documenting the CRL check process in the service documentation
  3. Specifying the CRL distribution point format and update frequency
  4. Describing how to handle certificate validation against the CRL

Consider implementing:

  • CRL caching mechanism
  • Periodic CRL updates
  • Metrics for revocation operations
  • Integration with OCSP if needed
device-provisioning-service/Makefile (1)

57-59: Consider documenting the proto output path changes.

Since this changes where the generated files are placed, it would be helpful to update the project documentation to reflect this change. This ensures other developers are aware of the new file locations.

Would you like me to help draft documentation updates for the README or contributing guidelines?

Also applies to: 60-63

certificate-authority/service/grpc/deleteSigningRecords_test.go (3)

25-28: Consider defining ownerClaim as a package constant

The "sub" string appears to be a standard claim identifier. Consider defining it as a package-level constant for better maintainability and reusability.

+const defaultOwnerClaim = "sub"

 func TestCertificateAuthorityServerDeleteSigningRecords(t *testing.T) {
 	owner := events.OwnerToUUID("owner")
-	const ownerClaim = "sub"
+	ownerClaim := defaultOwnerClaim

53-62: Enhance error assertion in the missing token test

While testing for missing token is crucial, consider making the error assertion more specific to verify the exact error type or message.

 {
 	name: "missing token with ownerClaim in ctx",
 	args: args{
 		req: &pb.DeleteSigningRecordsRequest{
 			IdFilter: []string{r.GetId()},
 		},
 		ctx: context.Background(),
 	},
 	wantErr: true,
+	wantErrMsg: "missing token in context",
 },

100-100: Consider more robust HTTP host URL construction

The URL construction with string concatenation could be improved using url.Parse or similar utilities to ensure proper URL formatting and escaping.

-"https://"+config.CERTIFICATE_AUTHORITY_HTTP_HOST
+url.Parse(fmt.Sprintf("https://%s", config.CERTIFICATE_AUTHORITY_HTTP_HOST))
certificate-authority/service/grpc/server_test.go (1)

86-86: LGTM! Consider adding CRL-specific test cases.

The addition of the HTTP host parameter is correct and aligns with the implementation of Certificate Revocation List functionality. However, since this is part of CRL implementation, consider adding test cases that verify:

  • The CRL endpoint is properly configured with the provided HTTP host
  • The server correctly serves the CRL at the expected URL
  • The CRL is accessible and properly formatted as per RFC 5280

Would you like me to help generate additional test cases for the CRL functionality?

certificate-authority/service/cleanDatabase_test.go (1)

Line range hint 81-93: Consider enhancing test assertions for new fields.

While the test verifies basic record cleanup, consider adding explicit assertions to verify the Serial and IssuerId fields in the retrieved records before cleanup.

 		require.NoError(t, errR)
 		got = append(got, r)
 	}
 	require.Len(t, got, 1)
+	require.Equal(t, big.NewInt(42).String(), got[0].GetCredential().GetSerial())
+	require.Equal(t, "42424242-4242-4242-4242-424242424242", got[0].GetCredential().GetIssuerId())
 	time.Sleep(4 * time.Second)
certificate-authority/service/grpc/getSigningRecords_test.go (1)

Line range hint 52-89: Consider adding more test cases for CRL scenarios.

The current test structure is good, but consider adding test cases for:

  1. Revoked certificates
  2. Expired certificates
  3. Multiple serial numbers
  4. Invalid issuer IDs

Would you like me to help generate additional test cases for these scenarios?

certificate-authority/service/grpc/server.go (1)

31-39: Consider validating the CRL server address format.

For enhanced security and reliability, consider adding validation for the CRL server address format before using it. This could prevent runtime issues with malformed addresses.

Suggested validations:

  1. Check for empty string
  2. Validate URL/address format
  3. Consider adding TLS verification settings if HTTPS is used

Also applies to: 105-105

certificate-authority/service/http/signCertificate_test.go (1)

Line range hint 84-104: Consider enhancing error handling test coverage.

The httpDoSign function handles errors well, but consider adding test cases for:

  1. Network failures
  2. Invalid token scenarios
  3. Malformed response handling
  4. Timeout scenarios

This would make the test suite more robust for the Certificate Revocation List implementation.

Example test enhancement:

func TestCertificateAuthorityServerSignCSRErrors(t *testing.T) {
    tests := []struct {
        name    string
        setup   func(*http.Request)
        wantErr error
    }{
        {
            name: "network timeout",
            setup: func(r *http.Request) {
                // Setup timeout scenario
            },
            wantErr: context.DeadlineExceeded,
        },
        // Add more error scenarios
    }
    // Test implementation
}
certificate-authority/store/revocationList_test.go (2)

12-54: Consider adding more edge cases to strengthen test coverage.

While the current test cases cover basic validation scenarios, consider adding these additional cases to improve robustness:

  • Invalid serial number format (e.g., special characters)
  • Future revocation time
  • Negative revocation time

Example addition:

 func TestRevocationListCertificateValidate(t *testing.T) {
     tests := []struct {
         name    string
         input   store.RevocationListCertificate
         wantErr bool
     }{
         // ... existing tests ...
+        {
+            name: "Future revocation time",
+            input: store.RevocationListCertificate{
+                Serial:     "12345",
+                Revocation: time.Now().Add(24 * time.Hour).UnixNano(),
+            },
+            wantErr: true,
+        },
+        {
+            name: "Invalid serial format",
+            input: store.RevocationListCertificate{
+                Serial:     "12345#$%",
+                Revocation: time.Now().UnixNano(),
+            },
+            wantErr: true,
+        },
     }

44-53: Consider verifying specific error messages.

The test loops currently only check for error presence/absence. Consider enhancing them to verify the specific error messages returned by the validation functions. This would ensure that appropriate error messages are provided to users and help with debugging.

Example enhancement:

     for _, tt := range tests {
         t.Run(tt.name, func(t *testing.T) {
             err := tt.input.Validate()
             if tt.wantErr {
-                require.Error(t, err)
+                require.ErrorContains(t, err, tt.expectedErrMsg)
                 return
             }
             require.NoError(t, err)
         })
     }

Also applies to: 135-144

certificate-authority/service/config.go (2)

69-71: Consider reordering fields for better readability.

Consider ordering the fields more logically, with the primary address field first:

 type HTTPConfig struct {
-	ExternalAddress string            `yaml:"externalAddress" json:"externalAddress"`
 	Addr            string            `yaml:"address" json:"address"`
+	ExternalAddress string            `yaml:"externalAddress" json:"externalAddress"`
 	Server          httpServer.Config `yaml:",inline" json:",inline"`
 }

69-69: Document ExternalAddress usage for CRL.

Since this is part of the CRL implementation, please add a comment explaining:

  1. The purpose of ExternalAddress in the context of CRL
  2. The expected format (e.g., https://example.com)
  3. How it will be used in CRL distribution points
 type HTTPConfig struct {
+	// ExternalAddress is the publicly accessible URL of the service.
+	// It must be an HTTPS URL (e.g., https://ca.example.com) and will be used
+	// as the base URL for CRL distribution points.
 	ExternalAddress string            `yaml:"externalAddress" json:"externalAddress"`
certificate-authority/service/grpc/config_test.go (2)

12-50: Consider adding more test cases for comprehensive coverage.

While the current test cases cover basic scenarios, consider adding:

  1. Test case for exactly 1-minute expiration (edge case)
  2. Test case for negative ExpiresIn value
  3. Test case for maximum allowed expiration time
  4. Test case for empty ExternalAddress when enabled

This will ensure more robust validation of the CRL configuration.

Would you like me to provide the additional test cases?


52-82: Consider using a more realistic invalid CAPool test case.

The current test uses an integer (42) for invalid CAPool type. Consider using a more realistic invalid value like a single string instead of a slice, which better represents potential real-world misconfiguration.

-				CAPool:    42,
+				CAPool:    "ca1.pem", // single string instead of []string
certificate-authority/test/service.go (1)

25-43: Consider adding test cases for CRL edge cases.

Since this is a test configuration file, consider adding test cases for:

  1. CRL expiration and renewal
  2. Database failover scenarios
  3. Invalid CRL configurations
  4. Different time zones handling for expiration

This will ensure robust testing of the CRL implementation.

Would you like me to help create additional test cases for these scenarios?

device-provisioning-service/pb/service.proto (1)

Line range hint 75-144: Consider documenting the API changes in OpenAPI specification.

The HTTP binding changes look good, but since these endpoints are part of the Certificate Revocation List implementation:

  1. Consider updating the OpenAPI/Swagger documentation to reflect these changes
  2. Ensure that the error responses are properly documented for certificate-related failures
  3. Consider adding examples in the OpenAPI specification for the request/response bodies

This will help maintain API consistency and improve developer experience.

certificate-authority/pb/signingRecords_test.go (2)

11-95: Add test cases for temporal validation and enhance test data.

The test structure is well-organized with good coverage of basic validation cases. Consider these improvements:

  1. Add test case for expired certificate (ValidUntilDate < Date)
  2. Add test case for future Date
  3. Consider using constants for test timestamps and certificate data

Example additional test case:

{
    name: "Expired certificate",
    input: &pb.CredentialStatus{
        Date:           1669462400000000000, // Later date
        ValidUntilDate: 1659462400000000000, // Earlier date
        CertificatePem: "valid-cert",
        Serial:         "1234567890",
        IssuerId:       uuid.New().String(),
    },
    wantErr: true,
},

97-189: Enhance SigningRecord validation test coverage.

The test structure is well-organized with good basic validation coverage. Consider these improvements:

  1. Add test case for nil Credential field
  2. Add test cases for string field length boundaries
  3. Add test case for special characters in CommonName and Owner fields

Example additional test cases:

{
    name: "Nil credential",
    input: &pb.SigningRecord{
        Id:         uuid.New().String(),
        Owner:      "owner",
        CommonName: "common_name",
        DeviceId:   uuid.New().String(),
        Credential: nil,
    },
    wantErr: true,
},
{
    name: "Very long common name",
    input: &pb.SigningRecord{
        Id:         uuid.New().String(),
        Owner:      "owner",
        CommonName: strings.Repeat("a", 256), // Assuming there's a reasonable max length
        DeviceId:   uuid.New().String(),
        Credential: validCredential,
    },
    wantErr: true,
},
certificate-authority/service/config_test.go (1)

158-187: Consider adding more test cases for comprehensive validation.

Given this is part of a certificate authority service, consider adding these test cases:

  • Empty strings for both fields
  • Malformed URLs (e.g., "http://[::1]:invalid")
  • Both fields invalid simultaneously
  • URLs with invalid schemes

Example addition:

 		{
 			name: "invalid address",
 			args: args{
 				cfg: func() service.HTTPConfig {
 					cfg := test.MakeHTTPConfig()
 					cfg.Addr = "invalid"
 					return cfg
 				}(),
 			},
 			wantErr: true,
 		},
+		{
+			name: "both fields invalid",
+			args: args{
+				cfg: func() service.HTTPConfig {
+					cfg := test.MakeHTTPConfig()
+					cfg.Addr = "invalid"
+					cfg.ExternalAddress = "invalid"
+					return cfg
+				}(),
+			},
+			wantErr: true,
+		},
+		{
+			name: "empty fields",
+			args: args{
+				cfg: func() service.HTTPConfig {
+					cfg := test.MakeHTTPConfig()
+					cfg.Addr = ""
+					cfg.ExternalAddress = ""
+					return cfg
+				}(),
+			},
+			wantErr: true,
+		},
certificate-authority/service/service.go (1)

Line range hint 103-123: Add integration tests for CRL functionality.

The CRL implementation involves multiple components working together. Consider:

  1. Adding integration tests that verify the complete CRL workflow
  2. Testing different configuration scenarios (enabled/disabled)
  3. Security testing for the CRL distribution endpoint
  4. Performance testing for CRL generation and distribution

Consider implementing:

  • Caching for CRL to improve performance
  • Monitoring metrics for CRL operations
  • Health checks for the CRL endpoint

Would you like me to help create integration tests or monitoring metrics for the CRL functionality?

certificate-authority/service/http/revocationList_test.go (5)

34-34: Simplify time conversion logic.

The double Unix timestamp conversion pkgTime.Unix(pkgTime.Unix(0, cert.Revocation).Unix(), 0) seems unnecessarily complex and could be simplified.

Consider this simpler alternative:

-RevocationTime: pkgTime.Unix(pkgTime.Unix(0, cert.Revocation).Unix(), 0).UTC(),
+RevocationTime: time.Unix(0, cert.Revocation).UTC(),

56-59: Fix loop variable scope and magic number.

Two issues to address:

  1. The loop variable i in range loops should be properly scoped to prevent potential issues in concurrent operations
  2. The magic number 10 should be defined as a constant with a meaningful name

Consider these improvements:

+const defaultTestCertificateCount = 10

-for i := range 10 {
+for i := range defaultTestCertificateCount {
+    i := i  // proper scope for loop variable
     rlc := test.GetCertificate(i, now, now.Add(time.Hour))
     rl1.Certificates = append(rl1.Certificates, rlc)
 }

Also applies to: 68-70


102-107: Enhance test coverage and validation.

Consider adding these improvements to the test cases:

  1. Add a test case for expired CRL scenario
  2. Validate specific error types/messages
  3. Verify HTTP response status codes

Example additions:

 type args struct {
     issuer string
 }
 tests := []struct {
     name      string
     args      args
     verifyCRL func(crl *x509.RevocationList)
     wantErr   bool
+    wantStatus int
+    wantErrMsg string
 }
 // ... existing test cases ...
+{
+    name: "expired",
+    args: args{
+        issuer: test.GetIssuerID(2),
+    },
+    wantStatus: http.StatusGone,
+    wantErr:    true,
+    wantErrMsg: "revocation list has expired",
+},

Also applies to: 147-147


152-157: Verify HTTP response status code.

The test should validate the HTTP response status code before attempting to parse the response body.

Add status code verification:

 httpResp := httpgwTest.HTTPDo(t, request)
+require.Equal(t, tt.wantStatus, httpResp.StatusCode)
 respBody, err := io.ReadAll(httpResp.Body)

102-147: Add security-focused test cases.

Consider adding test cases for security-critical scenarios:

  1. Malformed issuer IDs
  2. Very large certificate lists
  3. Invalid signature verification
  4. Tampered revocation times

These additional test cases would help ensure the robustness of the CRL implementation against potential security issues.

certificate-authority/service/grpc/signCertificate_test.go (1)

153-197: Add documentation for security implications.

While the test case correctly validates that a device cannot obtain a new certificate with a different private key, it would be helpful to add comments explaining:

  1. The security implications of this test
  2. Why allowing different keys for the same device ID would be a security risk

Additionally, consider using a more specific error check on line 197:

-	require.Error(t, err)
+	require.ErrorContains(t, err, "expected error message about invalid key")
certificate-authority/store/mongodb/revocationList_test.go (4)

241-241: Use count variable instead of magic number for WaitGroup.

The WaitGroup is initialized with a hardcoded value of 10, which should match the count variable for consistency and maintainability.

-	wg.Add(10)
+	wg.Add(count)

249-249: Define retry count as a constant.

The retry count of 100 should be defined as a constant at package level for better maintainability and clarity.

+const maxRetries = 100
 
-			for range 100 {
+			for range maxRetries {

278-278: Consider inline test data setup for better readability.

The test relies on external helper test.AddRevocationListToStore which makes it harder to understand the test data without context. Consider setting up test data inline or documenting the expected structure returned by the helper function.


1-341: Consider adding benchmark tests.

Given the concurrent nature of the operations and the importance of performance in certificate revocation list handling, consider adding benchmark tests to measure and track the performance of these operations, especially for parallel updates.

Would you like me to help create benchmark tests for these operations?

certificate-authority/store/mongodb/signingRecords_test.go (1)

44-45: Enhance test coverage for new credential fields.

The new Serial and IssuerId fields are using hardcoded values across all test cases. Consider:

  1. Testing different serial number formats and lengths
  2. Testing invalid UUID formats for IssuerId
  3. Adding edge cases (empty strings, very large numbers)

Example improvement for better test coverage:

-Serial:         big.NewInt(42).String(),
-IssuerId:       "42424242-4242-4242-4242-424242424242",
+Serial:         fmt.Sprintf("%x", big.NewInt(test.GetTestCaseIdx()).Exp(big.NewInt(2), big.NewInt(64), nil)),
+IssuerId:       uuid.New().String(),

Also applies to: 64-65, 83-84, 217-218, 283-284, 326-327, 341-342, 356-357, 371-372

certificate-authority/store/cqldb/signingRecords_test.go (1)

35-36: LGTM: Consistent implementation of CRL-related fields

The new Serial and IssuerId fields are consistently implemented across all test cases with appropriate test data.

Consider adding these test cases to improve coverage:

  1. Validation for invalid serial numbers
  2. Explicit assertions to verify the new fields in test results

Example test case for invalid serial:

{
    name: "invalid serial number",
    args: args{
        sub: &store.SigningRecord{
            Id:         id1,
            Owner:      "owner",
            CommonName: "commonName",
            Credential: &pb.CredentialStatus{
                Serial:   "invalid",  // Invalid serial number
                IssuerId: "42424242-4242-4242-4242-424242424242",
            },
        },
    },
    wantErr: true,
},

Also applies to: 55-56, 110-111, 130-131, 150-151, 169-170, 294-295, 310-311, 326-327, 363-364, 408-409, 423-424, 438-439, 574-575

certificate-authority/pb/doc.html (2)

349-349: Fix typo in DeleteSigningRecords description

There's a typo in "certficate" that should be "certificate".

-                <td><p>Revoke signed certficate or delete expired signed certificate records.</p></td>
+                <td><p>Revoke signed certificate or delete expired signed certificate records.</p></td>

Also applies to: 356-356


551-551: Enhance DeletedSigningRecords description

The description "Revoke or delete certificates" is concise but could be more informative about the difference between revocation and deletion.

Consider expanding the description to clarify:

-        <p>Revoke or delete certificates</p>
+        <p>Response for certificate revocation or deletion operations. Revocation marks certificates as invalid while deletion removes expired certificate records.</p>
certificate-authority/store/mongodb/store.go (1)

20-20: Ensure logger is utilized within the Store methods

The logger field has been added to the Store struct but is not currently used within the provided methods. To make effective use of the logging capabilities, consider integrating logger into Store methods where appropriate to log important events and errors.

Also applies to: 91-92

certificate-authority/store/store.go (2)

47-47: Maintain Consistent Method Comment Style

For consistency, consider rephrasing the comment for SupportsRevocationList to start with a verb in the third-person singular form, matching the style of other method comments.

Apply this diff to adjust the comment:

-// Check if the implementation supports the RevocationList feature
+// SupportsRevocationList checks if the implementation supports the RevocationList feature.

51-51: Enhance Clarity in UpdateRevocationList Method Comment

The current comment can be made clearer for better understanding. Rewriting it will help convey its functionality more effectively.

Apply this diff to improve the comment:

-// UpdateRevocationList updates revocation list number and validity and adds certificates to revocation list. Returns the updated revocation list.
+// UpdateRevocationList updates the revocation list number and validity, adds certificates to the revocation list, and returns the updated revocation list.
certificate-authority/service/http/revocationList.go (1)

67-69: Validate issuer ID and handle parsing errors appropriately

The parsing of issuerID using uuid.Parse is correct. Returning the error directly is acceptable, but consider wrapping the error with additional context for better error tracing.

Apply this diff to provide more context in the error:

 	if _, err := uuid.Parse(issuerID); err != nil {
-		return err
+		return fmt.Errorf("invalid issuer ID '%s': %w", issuerID, err)
 	}
certificate-authority/store/revocationList.go (1)

62-65: Address the TODO regarding expiration check in IsExpired method

There's a TODO comment indicating the need to consider a delta when checking expiration. This could be important to handle network delays or clock skew between systems.

Would you like assistance in implementing an expiration check that accounts for a tolerance delta? For example:

const expirationDelta = 5 * time.Minute

func (rl *RevocationList) IsExpired() bool {
    return rl.ValidUntil <= time.Now().Add(expirationDelta).UnixNano()
}
pkg/security/certificateSigner/certificateSigner.go (1)

Line range hint 66-82: Consider providing more descriptive error messages

In the parseCertificateRequest function, the error message "pem not found" might be unclear. Consider changing it to "failed to decode CSR PEM block" to provide more context and aid in debugging.

certificate-authority/store/mongodb/signingRecords.go (1)

181-186: Remove unnecessary error check for mongo.ErrNilDocument

The Find method does not return mongo.ErrNilDocument when no documents are found; instead, it returns a cursor with no results. The check for mongo.ErrNilDocument after Find is unnecessary and can be removed to simplify the code.

Apply this diff to remove the unnecessary error check:

 	if err != nil {
-		if errors.Is(err, mongo.ErrNilDocument) {
-			return nil
-		}
 		return err
 	}
certificate-authority/service/grpc/signCertificate.go (1)

162-164: Improve the clarity of the error message when credential is nil.

The error message "cannot create signing record" may not clearly indicate that credential is nil. Providing more specific information can aid in debugging.

Update the error message for clarity:

- return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("cannot create signing record")))
+ return nil, logger.LogAndReturnError(status.Errorf(codes.Internal, fmtError, errors.New("credential is nil; failed to create signing record")))
certificate-authority/store/mongodb/revocationList.go (1)

225-226: Ensure time synchronization and correct expiration checks

The condition !rl.IsExpired() depends on the system's current time. To prevent issues caused by time discrepancies between systems, ensure that the time used for expiration checks is consistent and consider time skew.

Recommendation:

  • Use a time source that is consistent across your systems.
  • If possible, include leeway in expiration checks to account for minimal time differences.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 11ac65b and 36e6847.

⛔ Files ignored due to path filters (10)
  • certificate-authority/config.yaml is excluded by !**/*.yaml
  • certificate-authority/pb/service.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • certificate-authority/pb/service.swagger.json is excluded by !**/*.json
  • certificate-authority/pb/service_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/signingRecords.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • charts/plgd-hub/templates/certificate-authority/config.yaml is excluded by !**/*.yaml
  • charts/plgd-hub/values.yaml is excluded by !**/*.yaml
  • device-provisioning-service/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • device-provisioning-service/pb/service.swagger.json is excluded by !**/*.json
📒 Files selected for processing (55)
  • bundle/nginx/nginx.conf.template (1 hunks)
  • certificate-authority/pb/README.md (3 hunks)
  • certificate-authority/pb/doc.html (7 hunks)
  • certificate-authority/pb/service.proto (2 hunks)
  • certificate-authority/pb/signingRecords.go (3 hunks)
  • certificate-authority/pb/signingRecords.proto (2 hunks)
  • certificate-authority/pb/signingRecords_test.go (1 hunks)
  • certificate-authority/service/cleanDatabase_test.go (5 hunks)
  • certificate-authority/service/config.go (3 hunks)
  • certificate-authority/service/config_test.go (1 hunks)
  • certificate-authority/service/grpc/config.go (2 hunks)
  • certificate-authority/service/grpc/config_test.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords_test.go (4 hunks)
  • certificate-authority/service/grpc/getSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/getSigningRecords_test.go (5 hunks)
  • certificate-authority/service/grpc/server.go (2 hunks)
  • certificate-authority/service/grpc/server_test.go (1 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signCertificate_test.go (4 hunks)
  • certificate-authority/service/grpc/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/grpc/signer_internal_test.go (1 hunks)
  • certificate-authority/service/http/config.go (1 hunks)
  • certificate-authority/service/http/requestHandler.go (1 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/service/http/service.go (2 hunks)
  • certificate-authority/service/http/signCertificate_test.go (6 hunks)
  • certificate-authority/service/http/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/service.go (2 hunks)
  • certificate-authority/service/uri/uri.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords_test.go (18 hunks)
  • certificate-authority/store/mongodb/bulkWriter.go (0 hunks)
  • certificate-authority/store/mongodb/config.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList_test.go (1 hunks)
  • certificate-authority/store/mongodb/signingRecords.go (3 hunks)
  • certificate-authority/store/mongodb/signingRecords_test.go (13 hunks)
  • certificate-authority/store/mongodb/store.go (3 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList_test.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • certificate-authority/test/revocationList.go (1 hunks)
  • certificate-authority/test/service.go (2 hunks)
  • charts/plgd-hub/README.md (0 hunks)
  • device-provisioning-service/Makefile (1 hunks)
  • device-provisioning-service/pb/service.proto (4 hunks)
  • http-gateway/test/http.go (1 hunks)
  • http-gateway/uri/uri.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (0 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (0 hunks)
💤 Files with no reviewable changes (4)
  • certificate-authority/store/mongodb/bulkWriter.go
  • charts/plgd-hub/README.md
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
✅ Files skipped from review due to trivial changes (2)
  • certificate-authority/service/uri/uri.go
  • certificate-authority/store/cqldb/revocationList.go
🧰 Additional context used
🪛 GitHub Check: CodeQL
certificate-authority/store/mongodb/revocationList.go

[failure] 75-75: Database query built from user-controlled sources
This query depends on a user-provided value.


[failure] 169-169: Database query built from user-controlled sources
This query depends on a user-provided value.


[failure] 209-209: Database query built from user-controlled sources
This query depends on a user-provided value.

🔇 Additional comments (110)
certificate-authority/store/mongodb/config.go (2)

11-13: LGTM!

The simplified Validate method correctly delegates to the underlying Mongo configuration validation.


8-8: Verify the removal of bulk write configuration.

The removal of BulkWrite configuration field is a breaking change. Please ensure that bulk operations are not required for certificate operations, especially for the new Certificate Revocation List implementation.

certificate-authority/service/http/config.go (1)

15-15: LGTM! Good formatting.

The empty line improves readability by separating the configuration groups.

certificate-authority/service/grpc/getSigningRecords.go (1)

14-18: Clean and efficient implementation of the signing records callback!

The refactored implementation is well-structured with several positive aspects:

  • Simplified logic using a callback approach instead of iterator
  • Clear error propagation
  • Proper context handling
  • Maintains security through owner validation
certificate-authority/service/grpc/deleteSigningRecords.go (1)

20-22: Method behavior changed from Delete to Revoke without API version change.

The method still uses DeleteSigningRecords name but now calls RevokeSigningRecords internally. This change in behavior without a corresponding API version change could break existing clients who expect deletion rather than revocation.

Let's check if this change is properly documented in the proto files:

Consider one of these approaches:

  1. Create a new RevokeSigningRecords method and deprecate this one
  2. Version the API (e.g., v2) to signal breaking changes
  3. Document the behavior change clearly in API documentation if revocation was the intended behavior all along
certificate-authority/service/http/signIdentityCertificate_test.go (2)

12-12: LGTM! Good practice using centralized URI constants.

The change to import URI constants from a dedicated package improves maintainability by centralizing URI definitions.


25-25: LGTM! Verify consistent URI usage across the codebase.

The URI constant is correctly used in the test case.

✅ Verification successful

Let me check the content of the .pb.gw.go file to understand if it's an auto-generated file and verify the usage context.


URI constant usage is correctly implemented

The hardcoded URI path /certificate-authority/api/v1/sign/identity-csr only appears in the auto-generated gRPC gateway code (service.pb.gw.go), which is expected. All other occurrences in the codebase properly use the certAuthURI.SignIdentityCertificate constant. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent usage of SignIdentityCertificate URI constant
# across the codebase to ensure all hardcoded instances are replaced.

echo "Checking for any remaining hardcoded sign identity certificate URIs..."
rg -l "/certificate-authority/api/v1/sign/identity-csr" --type go

echo "Checking current usage of the URI constant..."
rg "certAuthURI.SignIdentityCertificate" --type go

Length of output: 712


Script:

#!/bin/bash
# Check if the file is auto-generated
head -n 5 certificate-authority/pb/service.pb.gw.go

# Check the specific usage context
rg -A 5 -B 5 "/certificate-authority/api/v1/sign/identity-csr" certificate-authority/pb/service.pb.gw.go

Length of output: 1657

certificate-authority/service/http/requestHandler.go (2)

6-6: LGTM: Import statements are appropriate.

The new imports are necessary for HTTP handling, route management, and data persistence.

Also applies to: 13-14


41-41: LGTM: Proper gRPC service registration.

The gRPC service registration is correctly implemented with appropriate error handling.

certificate-authority/pb/signingRecords.go (2)

6-6: LGTM!

The addition of math/big is appropriate for handling certificate serial numbers.


67-68: Verify the impact of validation changes.

The refactoring to use credential.Validate() improves code organization. However, let's verify that all existing code paths are prepared for the potentially new validation errors.

✅ Verification successful

Let me analyze the validation changes and their impact based on the search results.

Validation changes are properly handled

The codebase shows consistent error handling patterns around Validate() calls:

  1. The SigningRecord.Validate() method is called with proper nil checks in multiple places:
  • certificate-authority/store/mongodb/signingRecords.go
  • certificate-authority/store/cqldb/signingRecords.go
  1. All callers properly handle validation errors through:
  • Returning errors wrapped with additional context
  • Proper error propagation up the call chain
  • Consistent error handling patterns across the codebase
  1. The credential.Validate() method is part of a well-established validation pattern where:
  • Parent objects validate their child objects
  • Nil checks are performed before validation
  • Validation errors are properly propagated

The refactoring to use credential.Validate() maintains consistency with the existing validation patterns in the codebase and all error cases are properly handled by the callers.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all places where SigningRecord.Validate() is called to ensure proper error handling

echo "Searching for direct Validate() calls:"
rg -A 3 "Validate\(\)" --type go

echo "Searching for error handling patterns around Validate():"
ast-grep --pattern 'if err := $_.Validate(); err != nil {
  $$$
}'

Length of output: 168007

certificate-authority/service/http/service.go (5)

5-14: LGTM: Import changes are well-organized and necessary.

The new imports support the CRL functionality and follow Go's import organization conventions.


37-46: LGTM: Service configuration is well-structured.

The configuration properly integrates CRL support while maintaining existing functionality. The use of package-specific constants enhances maintainability.


52-52: LGTM: RequestHandler properly initialized with store.

The store parameter is correctly passed to the RequestHandler, maintaining proper error handling.


28-34: LGTM: Secure implementation of CRL endpoint whitelist.

The implementation correctly:

  • Uses QuoteMeta for safe regex pattern
  • Restricts to GET method only
  • Guards the feature with CRLEnabled flag
✅ Verification successful

Based on the search results, I can generate the final response as I have sufficient information to verify the concern. The results show all usages of SigningRevocationList in the codebase:

Verified: CRL endpoint is securely implemented with proper access controls

The implementation is secure because:

  • The CRL endpoint is only registered when CRLEnabled is true in both the whitelist and route handler
  • The endpoint is consistently restricted to GET method only
  • The endpoint path is only used for CRL distribution in the certificate signer configuration
  • No other potentially unsafe access patterns were found
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify no other endpoints expose CRL data
rg -g '*.go' "SigningRevocationList" -C 5

Length of output: 4907


27-27: Verify all callers are updated with the new store parameter.

The function signature change is breaking and requires updates to all callers.

certificate-authority/service/grpc/config.go (3)

16-22: Technical debt alert: Review CRL implementation for cqldb

The comment indicates temporary test-related implementation for cqldb. This should be properly tracked and addressed.

Would you like me to create a GitHub issue to track the implementation of CRL support in cqldb?

Consider exposing the Enabled flag in configuration

The Enabled field is currently hidden from YAML/JSON serialization. This makes it impossible to enable/disable CRL through configuration files, which might limit operational flexibility.


40-40: LGTM!

The CRL field is properly integrated into the SignerConfig struct with appropriate serialization tags.


58-65: LGTM!

The validation changes are well-implemented:

  • Error messages are more specific and consistent
  • CRL validation is properly integrated
  • Error wrapping follows Go best practices
certificate-authority/pb/signingRecords.proto (1)

23-26: Consider making new fields optional for backward compatibility.

The new fields enhance certificate tracking capabilities and are well-documented. However, since these fields are added to an existing message type, consider the following:

  1. Verify that these fields are properly utilized in the CRL implementation
  2. Consider marking these fields as optional (though all proto3 fields are technically optional) to explicitly indicate that they might be absent in existing records
✅ Verification successful

Based on the extensive search results, I can now provide a definitive response about the new fields in the protobuf file:

The new fields are properly integrated into the CRL implementation

The codebase shows comprehensive integration of these fields:

  • The serial and issuer_id fields are actively used in the CRL (Certificate Revocation List) implementation:
    • serial is used to identify certificates in revocation entries (RevocationListCertificate.Serial)
    • issuer_id is used to track and manage CRLs per issuer (RevocationList.Id)
  • The fields are properly handled in MongoDB storage implementation with corresponding BSON tags
  • The CRL functionality is fully implemented with proper validation, HTTP endpoints, and tests
  • Making the fields optional is not necessary as they are already effectively optional in proto3 (zero values are used when not set)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of new fields in CRL implementation

# Test 1: Check if serial field is used in CRL-related code
echo "Checking usage of serial field in CRL implementation..."
rg -l "serial.*revocation" --type go

# Test 2: Check if issuer_id is used for certificate chain validation
echo "Checking usage of issuer_id in certificate validation..."
rg -l "issuer_id.*validate" --type go

Length of output: 322


Script:

#!/bin/bash
# Let's try a broader search to understand the usage of these fields

# Check for any usage of 'serial' field in go files
echo "Checking usage of serial field..."
rg -A 3 -B 3 "\.serial" --type go

# Check for any usage of 'issuer_id' or 'issuerId' in go files
echo "Checking usage of issuer_id field..."
rg -A 3 -B 3 "(issuer_id|issuerId)" --type go

# Check for any CRL related implementations
echo "Checking CRL related implementations..."
rg -A 3 -B 3 "CRL|RevocationList" --type go

# Check the proto file implementation in more detail
echo "Checking proto file implementation..."
cat certificate-authority/pb/signingRecords.proto

Length of output: 94808

certificate-authority/pb/service.proto (2)

57-60: LGTM! Consistent with SignIdentityCertificate implementation.

The changes maintain a consistent API design pattern across the service.


80-86: ⚠️ Potential issue

Consider separating revocation and cleanup responsibilities.

Issues found:

  1. Typo in comment: "certficate" should be "certificate"
  2. The method serves dual purposes (revocation and cleanup), which might be better separated for clarity and maintainability.

Consider splitting into two distinct endpoints:

  • RevokeCertificate for certificate revocation
  • DeleteExpiredRecords for cleanup operations

This separation would:

  • Make the API more intuitive
  • Allow different authorization levels
  • Enable separate rate limiting if needed
  • Improve monitoring and logging clarity
device-provisioning-service/Makefile (1)

57-59: LGTM! The output path changes align with modern Go practices.

The change from $(GOPATH)/src to $(REPOSITORY_DIRECTORY) for both OpenAPI and gRPC gateway outputs is a good improvement. This makes the build more predictable and module-aware.

Let's verify the proto generation paths are consistently updated:

Also applies to: 60-63

certificate-authority/service/grpc/deleteSigningRecords_test.go (4)

5-5: LGTM: Import additions are appropriate

The new imports support certificate serial number handling and token context management.

Also applies to: 17-17


69-69: LGTM: Explicit context handling improves test clarity

The explicit context passing through test args is a good practice that makes the test cases more maintainable and flexible.

Also applies to: 78-78


109-113: LGTM: Clear error handling in test execution

The explicit error handling with early return improves test clarity and maintainability.


39-40: LGTM: Certificate fields align with X.509 standards

The addition of Serial and IssuerId fields properly supports certificate tracking and revocation. Consider adding validation tests for these new fields.

certificate-authority/service/cleanDatabase_test.go (4)

8-8: LGTM: Import changes align with new requirements.

The addition of "math/big" supports the new Serial field, and the import alias change maintains consistency.

Also applies to: 21-21


79-79: LGTM: Context creation update is consistent.

The change to use pkgGrpc maintains the same functionality while aligning with the updated import convention.


70-70: Verify HTTPS configuration in test environment.

While enforcing HTTPS is correct for security, please ensure that the test environment properly handles HTTPS connections.

✅ Verification successful

Based on the search results, I can see that the test environment properly handles HTTPS/TLS connections. Specifically:

  1. The test configuration in certificate-authority/test/service.go shows proper TLS setup:
cfg.APIs.GRPC.TLS.ClientCertificateRequired = false
TLS: config.MakeTLSClientConfig()
  1. The test helper functions in test/config/config.go provide both client and server TLS configurations:
func MakeTLSClientConfig() client.Config
func MakeTLSServerConfig() server.Config
  1. The HTTPS prefix addition is consistent with the test environment setup where TLS/HTTPS is properly configured and handled.

HTTPS configuration is properly set up in test environment

The change to enforce HTTPS is safe as the test infrastructure already supports and handles HTTPS connections appropriately through the existing TLS configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify HTTPS configuration in test environment

# Check for TLS/HTTPS configuration in test setup
echo "Checking test TLS configuration..."
rg -A 5 "TLS|Certificate" "certificate-authority/test"

# Check for any test skip conditions related to HTTPS
echo "Checking for HTTPS-related test conditions..."
rg "Skip.*[\"']https|TLS" --type go

Length of output: 63355


52-53: Verify consistent field usage across the codebase.

The new Serial and IssuerId fields are well-structured for certificate tracking and revocation. The Serial field appropriately uses big.Int for certificate serial numbers, and IssuerId follows UUID format.

✅ Verification successful

Let me gather more specific information about the Serial and IssuerId fields in the codebase.


Let me check one more aspect to verify the consistency of these fields across the codebase.


Based on the gathered information, I can now generate the final response:

The Serial and IssuerId fields are consistently implemented across the codebase

The fields are properly defined and used consistently:

  • Serial field is correctly stored as a string in both proto definitions and database models
  • IssuerId is consistently used with UUID format and properly documented as derived from the issuer's public certificate
  • Both fields are properly integrated into the certificate signing and storage workflow
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent implementation of Serial and IssuerId fields
# across the codebase

# Check for consistent field definitions in proto files and structs
echo "Checking field definitions..."
rg -A 2 "Serial.*string|IssuerId.*string" --type go --type proto

# Check for proper UUID format usage for IssuerId
echo "Checking IssuerId UUID format usage..."
rg -A 2 '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' --type go

Length of output: 28122


Script:

#!/bin/bash
# Search for Serial and IssuerId field definitions in proto files and Go structs
echo "Checking field definitions in proto and Go files..."
rg -A 2 'Serial.*string|IssuerId.*string|Serial.*big\.Int' --type-add 'proto:*.proto' --type go --type proto

# Search for usage patterns of these fields
echo "Checking usage patterns..."
ast-grep --pattern 'type $_ struct {
  $$$
  Serial $_
  $$$
}'

echo "Checking IssuerId usage..."
ast-grep --pattern 'type $_ struct {
  $$$
  IssuerId $_
  $$$
}'

Length of output: 2992


Script:

#!/bin/bash
# Check for proto definitions and field usage in signing records
echo "Checking proto definitions..."
rg -p "message (SigningRecord|CredentialStatus)" --type proto -A 10

# Check for any other implementations or usages
echo "Checking implementations..."
rg -p "func.*Sign.*Certificate" --type go -A 5

Length of output: 21241

certificate-authority/service/grpc/getSigningRecords_test.go (4)

7-7: LGTM! Import changes are appropriate.

The addition of math/big is suitable for handling certificate serial numbers, and the package alias update maintains consistency.

Also applies to: 20-20


43-44: Consider adding Serial number validation in tests.

The addition of Serial and IssuerId fields is appropriate for CRL implementation. However, consider adding test cases that verify:

  1. Serial number parsing back to big.Int
  2. Different serial number sizes
  3. Invalid serial number formats

Let's check if there are any validation tests for these fields:


101-101: LGTM! Package refactoring maintains token handling.

The context creation update correctly maintains the token handling functionality while using the updated package.

Let's verify the token handling implementation:

✅ Verification successful

Token handling implementation verified and consistent

The change from kitNetGrpc to pkgGrpc is correct and maintains the same token handling functionality. The CtxWithToken function in pkg/net/grpc/auth.go properly sets the authorization token in the gRPC metadata context, which is the expected behavior for gRPC authentication.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check token context handling in the new package
ast-grep --pattern 'func CtxWithToken($ctx, $token) $ret {
  $$$
}'

Length of output: 69


Script:

#!/bin/bash
# Let's try to find the CtxWithToken function using ripgrep for better coverage
rg -A 5 "func CtxWithToken" 

# Also search for the import statement to verify the package
rg "pkgGrpc" certificate-authority/service/grpc/getSigningRecords_test.go

Length of output: 957


92-92: Verify HTTPS URL construction safety.

The server initialization now uses a constructed HTTPS URL. Please ensure:

  1. The URL is properly sanitized
  2. The host value is validated
  3. There's proper error handling for malformed URLs

Let's check URL handling across the codebase:

✅ Verification successful

Let's analyze how URLs are constructed and validated in the codebase. The previous search might have been too specific, so I've broadened it to catch more URL-related patterns.


Based on the search results, I can now generate a final response:

URL construction is properly handled and validated.

The URL construction pattern "https://" + config.CERTIFICATE_AUTHORITY_HTTP_HOST is consistently used across the codebase and the HTTPConfig struct includes proper validation:

  • The ExternalAddress is validated using url.ParseRequestURI() in certificate-authority/service/config.go
  • The host configuration is used consistently across test and production code
  • The URL construction is part of a validated configuration structure rather than ad-hoc string concatenation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for URL validation and sanitization
rg "https://" --type go -B 2 -A 2

Length of output: 69


Script:

#!/bin/bash
# Let's try a more comprehensive search for URL handling patterns
rg "config\.CERTIFICATE_AUTHORITY_HTTP_HOST" --type go -B 2 -A 2

# Also search for URL validation/sanitization patterns
rg "url\.(Parse|URL|QueryEscape)" --type go -B 2 -A 2

# Look for any HTTP/HTTPS related configuration
ast-grep --pattern 'config.CERTIFICATE_AUTHORITY_HTTP_HOST'

# Search for any URL construction patterns
ast-grep --pattern '$var := "https://" + $host'

Length of output: 14219

certificate-authority/service/grpc/signIdentityCertificate_test.go (3)

15-15: LGTM: Package rename from kitNetGrpc to pkgGrpc

The package rename maintains the same functionality while using a more standardized naming convention.


Line range hint 1-106: Verify test coverage for certificate revocation

Given that this PR implements Certificate Revocation List functionality, consider adding test cases to verify:

  1. Signing certificates for already revoked identities
  2. Handling of revocation status during signing

Let's check if these scenarios are covered elsewhere:

#!/bin/bash
# Description: Look for revocation-related test cases
# Test: Search for test files containing revocation tests
rg -t go "Test.*Revocation" --glob "*_test.go"

52-52: LGTM: Updated context creation with token using renamed package

The context creation with token has been correctly updated to use the renamed package pkgGrpc. The functionality remains unchanged.

Let's verify that all occurrences of the old package have been updated:

Also applies to: 80-80

certificate-authority/service/grpc/server.go (3)

26-26: LGTM! Field addition follows Go conventions.

The new crlServerAddress field is appropriately typed and named for storing the CRL server address.


31-39: Verify the impact of constructor signature change.

The constructor has been updated correctly to include the CRL server address. However, this is a breaking change that requires verification of all existing callers.

✅ Verification successful

Constructor signature change has been properly propagated

All existing callers of NewCertificateAuthorityServer have been updated to include the new crlServerAddress parameter:

  • Main service initialization in certificate-authority/service/service.go uses config.APIs.HTTP.ExternalAddress
  • Test files consistently use "https://"+config.CERTIFICATE_AUTHORITY_HTTP_HOST
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all existing calls to NewCertificateAuthorityServer to ensure they've been updated
rg "NewCertificateAuthorityServer\(" --type go -B 2 -A 2

Length of output: 94


Script:

#!/bin/bash
# Search for NewCertificateAuthorityServer calls with case-insensitive and word boundary matches
rg -w -i "NewCertificateAuthorityServer" --type go

# Also check for test files that might use this constructor
rg -w -i "NewCertificateAuthorityServer" --type go --glob "*_test.go"

# Look for files that might contain the constructor implementation
fd -e go | xargs grep -l "CertificateAuthorityServer"

Length of output: 3592


105-105: Verify the NewSigner implementation handles the CRL address correctly.

The crlServerAddress is now passed to the signer, but we should verify its implementation in the signer code.

✅ Verification successful

CRL server address is properly handled in the signer implementation

The verification shows that:

  • The crlServerAddress parameter is correctly passed through NewSigner to newSigner
  • The address is properly stored in the Signer struct's crl.serverAddress field
  • It's only set when CRL is enabled (if signerConfig.CRL.Enabled)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check the NewSigner implementation to ensure proper handling of crlServerAddress
ast-grep --pattern 'func NewSigner($_, $_, $crlServerAddress string, $_) ($_, $_) {
  $$$
}'

Length of output: 94


Script:

#!/bin/bash
# Let's try to find the NewSigner function implementation with a broader pattern
ast-grep --pattern 'func NewSigner($$$) {
  $$$
}'

# Also search for the file content directly
rg "func NewSigner" -A 10

Length of output: 902


Script:

#!/bin/bash
# Let's check how crlServerAddress is used within the signer implementation
rg "crlServerAddress" certificate-authority/service/grpc/signer.go -B 2 -A 10

# Also check the Signer struct definition to see how the address is stored
ast-grep --pattern 'type Signer struct {
  $$$
}'

Length of output: 2858

certificate-authority/service/http/signCertificate_test.go (4)

16-16: LGTM! Good refactoring of imports.

The addition of centralized URI management through certAuthURI and token handling through pkgGrpc improves code organization and maintainability.

Also applies to: 18-18


70-70: LGTM! Consistent token management.

Good update to use the standardized pkgGrpc package for token context management.


116-116: LGTM! Consistent use of centralized URIs.

Good update to use the centralized URI definitions from certAuthURI package, which improves maintainability and consistency.

Also applies to: 128-128


55-61: 🛠️ Refactor suggestion

Consider expanding test coverage for revocation scenarios.

While testing multiple certificate requests with the same CSR is good, consider adding test cases that explicitly verify:

  1. Certificate revocation status tracking
  2. Handling of signing requests for previously revoked certificates
  3. Edge cases around certificate lifecycle management

Example test case structure:

{
    name: "previously revoked certificate",
    args: args{
        req: &pb.SignCertificateRequest{
            CertificateSigningRequest: csr,
            // Add relevant fields for revocation testing
        },
    },
    wantErr: true,
}
certificate-authority/store/revocationList_test.go (1)

1-10: LGTM! Well-structured test package setup.

The black-box testing approach using store_test package is appropriate for testing the public API. Import declarations are clean and follow Go conventions.

certificate-authority/service/config.go (2)

6-6: LGTM: Required import for URL validation.

The addition of the net/url package is necessary for validating the new ExternalAddress field.


44-44: Verify all NewSigner usages are updated.

The signature change of NewSigner to include ExternalAddress is a breaking change. Let's verify all callers are updated.

✅ Verification successful

Let me verify the NewSigner function definition to ensure we have a complete picture.


All NewSigner usages are correctly updated

The verification shows that all calls to NewSigner are consistent with its signature that includes the crlServerAddress parameter:

  • In certificate-authority/service/config.go: Uses c.APIs.HTTP.ExternalAddress
  • In certificate-authority/service/grpc/server.go: Uses s.crlServerAddress
  • In certificate-authority/service/grpc/signer_internal_test.go: Uses empty string "" for testing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all NewSigner calls to ensure they include the new parameter
ast-grep --pattern 'NewSigner($$$)'

Length of output: 308


Script:

#!/bin/bash
# Search for NewSigner function definition
ast-grep --pattern 'func NewSigner($$$)'

Length of output: 3651

certificate-authority/service/grpc/signer_internal_test.go (1)

Line range hint 119-126: Verify error handling for CRL server connectivity.

The test doesn't verify how NewSigner handles CRL server connectivity issues. This is important for the Certificate Revocation List implementation.

Let's check if there's error handling for CRL server issues in the implementation:

certificate-authority/service/grpc/config_test.go (2)

1-10: LGTM! Clean package structure and imports.

The package name and imports follow Go conventions and contain only necessary dependencies.


53-56: Verify CRL configuration aligns with RFC 5280 requirements.

The test uses a 1-hour expiration for CRL. Please verify this aligns with your CA's CRL update frequency requirements. According to RFC 5280, the CRL validity period should be aligned with:

  1. The CA's CRL issuance frequency
  2. The risk of key compromise
  3. Revocation checking requirements of relying parties
✅ Verification successful

Based on the search results, I can now provide a final response since I have sufficient information about the CRL implementation:

CRL configuration duration of 1 hour is appropriate and aligns with implementation

The test configuration using a 1-hour expiration for CRL is valid because:

  1. The codebase enforces a minimum CRL validity period of 1 minute through validation in service/grpc/config.go
  2. The production code in certificate-authority/test/service.go also uses the same 1-hour duration as the default configuration
  3. The implementation supports dynamic CRL updates through UpdateRevocationListQuery with UpdateIfExpired flag in the store
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CRL-related constants or documentation that might define these requirements
rg -g '!*.test.go' -g '!*_test.go' "CRL" -A 5 -B 5

Length of output: 20511

certificate-authority/test/service.go (4)

10-10: LGTM: Import added for CRL configuration.

The grpc import is correctly added to support the new CRL configuration functionality.


53-53: LGTM: Clean integration of new configuration.

The new HTTP and CRL configurations are properly integrated into the main config setup, maintaining the existing validation flow.

Also applies to: 59-59


33-43: Consider making CRL configuration more flexible.

A few concerns about the current implementation:

  1. The expiration time is hard-coded to 1 hour. Consider making this configurable through environment variables or configuration files for different environments.
  2. CRL is only enabled for MongoDB. The reason for this limitation isn't clear and might need documentation.

25-31: Verify the security of HTTP/HTTPS configuration.

The external address uses HTTPS while the internal address appears to use HTTP. Please verify if this is intentional and secure for your deployment environment.

device-provisioning-service/pb/service.proto (4)

75-75: Verify request validation for enrollment group creation.

While using body: "*" is common for POST endpoints, ensure that proper validation is implemented in the service layer, especially for certificate-related operations. This is crucial for maintaining security in the provisioning process.

Also applies to: 78-78


89-89: LGTM! Well-structured update endpoint.

The explicit body: "enrollment_group" specification follows best practices by clearly defining the expected request body structure.

Also applies to: 92-92


127-127: Ensure consistent validation across creation endpoints.

Similar to the enrollment group creation, verify that proper validation is implemented for hub creation requests, maintaining consistency in security measures across the service.

Also applies to: 130-130


141-141: LGTM! Consistent with update endpoint patterns.

The body: "hub" specification maintains consistency with the enrollment group update pattern and follows RESTful best practices.

Also applies to: 144-144

certificate-authority/pb/signingRecords_test.go (2)

1-9: LGTM! Package and imports are well-structured.

The package name and imports follow Go best practices for external test packages.


1-189: Enhance security validation test coverage.

Given that this code handles certificate management, consider adding security-focused test cases:

  1. Test invalid certificate PEM formats
  2. Test certificate PEM with potential injection patterns
  3. Test malformed serial numbers that might bypass validation

Let's verify the validation implementation:

✅ Verification successful

Let me search for the validation implementation to better understand how certificates are validated:


Let me try a different search pattern to find the validation implementation:


Let me search for the actual certificate validation implementation:


Based on the code review and verification results, I can now provide a final response:

Test coverage for certificate validation is adequate

The current test coverage appropriately validates certificates through multiple layers:

  1. The test cases verify empty/invalid certificate PEM content
  2. The serial number validation ensures proper decimal format using big.Int.SetString
  3. The implementation uses proper X509 parsing via security package's ParseX509FromPEM
  4. The test cases cover all validation scenarios including missing fields and invalid formats

The original review comment's concerns are already addressed by the existing implementation and test coverage.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for certificate validation logic
ast-grep --pattern 'func (c *CredentialStatus) Validate() error {
  $$$
}'

# Look for any existing security-related tests
rg -i 'security|injection|malicious|invalid.*certificate' --type go

Length of output: 29555


Script:

#!/bin/bash
# Search for CredentialStatus validation implementation
ast-grep --pattern 'func (c *CredentialStatus) Validate() error {
  $$$
}'

# Search for certificate validation in the codebase
rg -A 10 'func.*Validate.*Certificate' --type go

Length of output: 127


Script:

#!/bin/bash
# Search for the validation implementation in the proto/pb files
rg -A 15 'func \(.*\) Validate\(\)' --type go certificate-authority/pb/

# Look for certificate validation patterns
rg -A 10 'CertificatePem|Serial.*validate' --type go certificate-authority/

Length of output: 39119


Script:

#!/bin/bash
# Search for certificate validation in x509 package
rg -A 10 'func.*Validate' --type go pkg/security/x509/

# Search for PEM validation
rg -A 10 'ParseX509FromPEM|LoadX509' --type go

Length of output: 6391

certificate-authority/service/config_test.go (2)

150-199: LGTM! Well-structured test implementation.

The test follows good practices with table-driven tests and is consistent with the existing test patterns in the file.


162-163: Verify the test helper function implementation.

Let's verify that test.MakeHTTPConfig() sets secure defaults for the HTTP configuration.

✅ Verification successful

Let's verify the security settings by checking the implementation of config.MakeHttpServerConfig() which is used by all the test helper functions.


Test helper function MakeHTTPConfig() provides reasonable defaults for testing

The implementation shows that:

  • The HTTP server configuration sets appropriate timeouts:
    • Read timeout: 8 seconds
    • Read header timeout: 4 seconds
    • Write timeout: 16 seconds
    • Idle timeout: 30 seconds
  • The certificate authority implementation properly sets HTTPS external address
  • The device provisioning service includes authorization configuration
  • All implementations use the common MakeHttpServerConfig() with consistent timeout settings

These settings are reasonable for testing purposes and don't expose any security concerns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of test.MakeHTTPConfig()
# to ensure it sets secure defaults for HTTP configuration

# Look for the helper function implementation
ast-grep --pattern 'func MakeHTTPConfig() $_ {
  $$$
}'

# Also check for any constants or variables used in the implementation
rg -A 5 'MakeHTTPConfig'

Length of output: 6433


Script:

#!/bin/bash
# Check the implementation of MakeHttpServerConfig
ast-grep --pattern 'func MakeHttpServerConfig() $_ {
  $$$
}'

# Also look for any TLS or security related configurations
rg -A 5 'MakeHttpServerConfig'

Length of output: 5288

certificate-authority/service/service.go (2)

103-103: Verify external address configuration for CRL distribution point.

The external address will be used as the CRL distribution point in certificates. Ensure that:

  1. The address is properly validated in the config
  2. It's accessible from external networks
  3. It matches the CRL endpoint path
✅ Verification successful

External address validation is properly implemented for CRL distribution point

The external address configuration is properly validated:

  • The HTTPConfig.Validate() function validates the external address using url.ParseRequestURI
  • The address is correctly passed to NewCertificateAuthorityServer as crlServerAddress
  • Test cases cover validation of invalid addresses
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the external address validation in config

# Test: Check if the external address is validated in config
rg -A 5 "ExternalAddress.*Validate" certificate-authority/service/config/

# Test: Check if the address is used in CRL-related code
rg -A 5 "CRLDistributionPoints|crlDistributionPoints" certificate-authority/

Length of output: 162


Script:

#!/bin/bash
# Let's try different approaches to verify the external address usage and validation

# Check config validation patterns
rg -A 10 "type HTTP struct" certificate-authority/service/config/
rg "func.*Validate" certificate-authority/service/config/

# Check how external address is used in the codebase
rg -A 5 "ExternalAddress" certificate-authority/service/

# Look for CRL distribution point implementation
ast-grep --pattern 'func NewCertificateAuthorityServer($$$) ($_, error) {
  $$$
}'

# Check for URL/address validation patterns
rg -A 5 "(url|addr|address).*(Valid|Parse)" certificate-authority/service/

Length of output: 7982


122-123: Verify CRL implementation details.

The CRL feature can be toggled via configuration. Please ensure:

  1. Proper error handling when CRL is enabled but the database doesn't support required operations
  2. Clear documentation of CRL-related configuration options
  3. Appropriate logging when CRL operations are performed
✅ Verification successful

Based on the search results, I can now provide a comprehensive verification of the CRL implementation. Here's the final response:

CRL implementation has proper error handling and configuration validation

The CRL feature is well-implemented with:

  • Proper configuration validation in CRLConfig.Validate() ensuring ExpiresIn is > 1 minute
  • Error handling in MongoDB storage for CRL number sequence
  • Conditional CRL distribution points in certificate signing
  • Proper HTTP endpoint protection with JWT validation
  • Database-specific CRL support (currently MongoDB only)

Implementation details to note:

  • CRL is properly toggled via config.Signer.CRL.Enabled
  • CRL validity period is configurable via config.Signer.CRL.ExpiresIn
  • CRL distribution points are automatically configured when enabled
  • HTTP endpoints for CRL are conditionally registered
  • MongoDB implementation handles CRL number sequence starting from 1
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CRL implementation details

# Test: Check error handling in CRL-related code
ast-grep --pattern 'if $err != nil {
  $$$
  return $_, fmt.Errorf("CRL: %w", $err)
}'

# Test: Check for CRL-related logging
rg "log\.(Debug|Info|Error).*CRL" 

# Test: Check for CRL documentation
fd -e md -e txt . | xargs rg -l "CRL"

Length of output: 162


Script:

#!/bin/bash
# Let's try a different approach to verify CRL implementation

# Check for CRL-related error handling with broader pattern
ast-grep --pattern 'if err := $$.CRL$$; err != nil {
  $$$
}'

# Look for CRL-related function implementations
ast-grep --pattern 'func $_($$$) {
  $$$
  CRL
  $$$
}'

# Search for CRL-related code with context
rg -A 3 -B 3 "CRL" --type go

# Check configuration structure for CRL
rg "type.*Config.*struct" -A 15 --type go | rg -B 15 -A 15 "CRL"

# Look for CRL in comments and documentation
rg "(?m)^//.*CRL" --type go

Length of output: 30273

http-gateway/test/http.go (2)

196-199: LGTM! Implementation follows established patterns.

The AddIssuerID method is well-implemented and consistent with other builder methods in the file, following the same patterns for parameter handling and method chaining.


196-199: Add test coverage for the new method.

Since this is a test utility that will be used for testing CRL endpoints, it's important to ensure the method works as expected. Consider adding test cases that verify:

  1. The issuer ID is correctly stored in the URI parameters
  2. The method properly chains with other builder methods
  3. The built URL contains the issuer ID parameter in the expected format

Let's check if there are any existing tests for this file:

certificate-authority/service/grpc/signCertificate_test.go (2)

Line range hint 13-24: LGTM: Import changes look good.

The switch from kitNetGrpc to pkgGrpc appears to be part of a consistent refactoring effort across the codebase.


94-106: Well-structured refactoring of CSR creation helpers.

Good separation of concerns by splitting createCSR into two functions. This enables better testing of scenarios involving different keys for the same device ID.

http-gateway/uri/uri.go (1)

27-27: Verify the usage pattern of IssuerIDKey in the codebase.

Since this is part of the Certificate Revocation List implementation, let's verify how this constant is being used across the codebase to ensure consistent parameter handling.

✅ Verification successful

Based on the results, I can now generate the final response:

The usage of IssuerIDKey is consistent across the codebase

The constant is properly defined and used in both the http-gateway and certificate-authority services:

  • Used as a URL parameter key in certificate-authority/service/uri/uri.go for signing revocation list endpoint
  • Referenced in HTTP parameter handling in certificate-authority/service/http/revocationList.go
  • Used in test utilities in http-gateway/test/http.go
  • Consistently spelled as "issuerId" in all occurrences including protobuf definitions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Analyze the usage pattern of IssuerIDKey in the codebase

# Test 1: Find direct references to the constant
echo "=== Direct references to IssuerIDKey ==="
rg --type go "IssuerIDKey"

# Test 2: Find URL patterns using the parameter name
echo -e "\n=== URL patterns with issuerId parameter ==="
rg --type go "issuerId"

# Test 3: Look for related handler functions
echo -e "\n=== Related handler functions ==="
ast-grep --pattern 'func $$$($_, $_, $_) {
  $$$
  issuerId := $$$
  $$$
}'

Length of output: 1258

certificate-authority/pb/README.md (2)

123-128: LGTM! Well-documented certificate tracking fields.

The new fields serial and issuer_id are properly documented with clear descriptions and BSON tags. These fields are essential for certificate tracking and revocation list implementation.


154-154: LGTM! Clear description for DeletedSigningRecords.

The description "Revoke or delete certificates" is concise and accurately describes the purpose of this message type.

certificate-authority/store/mongodb/revocationList_test.go (1)

237-269: LGTM! Well-implemented helper function.

The helper function correctly handles concurrent operations with proper synchronization using WaitGroup and atomic operations. The retry logic appropriately handles race conditions that may occur during parallel execution.

bundle/nginx/nginx.conf.template (1)

Line range hint 123-136: LGTM! The certificate authority endpoint configuration looks secure.

The updated location block correctly:

  • Consolidates certificate-related endpoints under a single configuration
  • Maintains proper SSL certificate validation
  • Sets appropriate security headers
  • Follows the established pattern for secure service proxying

Let's verify the certificate authority service integration:

✅ Verification successful

Based on the search results, I can now generate the final response since I have sufficient information to verify the certificate authority service integration:

Certificate authority endpoint configuration is correctly integrated

The location block changes are properly integrated with the certificate authority service as evidenced by:

  • The paths match the gRPC gateway bindings defined in certificate-authority/pb/service.proto
  • SSL certificate paths are consistently used across the nginx configuration
  • The configuration follows the same secure pattern used for other internal services
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the certificate authority service configuration and related proto definitions

# Test 1: Check if the certificate authority proto defines the HTTP bindings for these paths
rg -A 5 "(/certificate-authority|/api/v1/sign)"

# Test 2: Ensure SSL certificate paths exist in the configuration
rg "/data/certs/(internal/endpoint|root_ca)"

Length of output: 81186

certificate-authority/store/cqldb/signingRecords.go (2)

342-367: LGTM! Well-structured implementation with proper error handling.

The changes to LoadSigningRecords demonstrate good practices:

  • Efficient iterator pattern for processing large datasets
  • Proper error handling and resource cleanup
  • Prevention of duplicate records

368-374: ⚠️ Potential issue

Security Concern: Implement proper certificate revocation handling.

The current implementation deletes records instead of maintaining a proper Certificate Revocation List (CRL). This approach has several security implications:

  • Loss of historical data about revoked certificates
  • No audit trail of revocations
  • Potential security risks if relying parties have cached the certificates

A proper CRL implementation should:

  1. Mark certificates as revoked while retaining the records
  2. Include revocation reason and timestamp
  3. Support CRL distribution points
  4. Maintain an audit trail

Let's verify if there are any existing revoked certificates that need migration:

Would you like me to:

  1. Design a proper CRL implementation schema?
  2. Create a migration plan for existing certificates?
  3. Open a GitHub issue to track this security enhancement?
certificate-authority/store/mongodb/signingRecords_test.go (3)

101-103: LGTM! Good improvement in error handling.

The early return after error check follows the fail-fast principle and prevents unnecessary code execution.


Line range hint 477-485: LGTM! Test execution flow is well-structured.

The test maintains proper error handling, sorting, and comparison of results.


302-304: Verify interface compatibility for handler changes.

The replacement of Handle with process might break interface compatibility. Additionally, process is a less descriptive name compared to Handle.

Let's check for interface implementations and usages:

certificate-authority/store/cqldb/signingRecords_test.go (3)

5-5: LGTM: Appropriate import for certificate serial numbers

The addition of "math/big" is necessary for handling large integer serial numbers in X.509 certificates.


386-388: LGTM: Improved function naming

The rename from Handle to process better describes the function's purpose of processing signing records.


369-379: ⚠️ Potential issue

Review test logic for expired records

The test expects records to be empty after calling DeleteNonDeviceExpiredRecords, but this function returns ErrNotSupported. This suggests a mismatch between the test's expectations and the actual implementation.

Let's verify if this is intentional:

Consider one of these approaches:

  1. If the feature is not supported, update the test to expect records to remain
  2. If the feature should be supported, implement it and update the error handling
✅ Verification successful

Test logic for expired records is correct

The test logic is correct because:

  1. The CqlDB implementation explicitly returns ErrNotSupported since expired records are automatically deleted by Cassandra itself (as documented in the interface comment).
  2. The test verifies this behavior by checking that DeleteNonDeviceExpiredRecords returns ErrNotSupported.
  3. The empty records check (require.Empty(t, h1.lcs)) is also correct as it verifies that Cassandra's TTL mechanism worked after waiting for 3 seconds.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if DeleteNonDeviceExpiredRecords is implemented elsewhere
rg -A 5 "DeleteNonDeviceExpiredRecords"

# Check for any related TODO or FIXME comments
rg -i "todo.*delete.*expired|fixme.*delete.*expired"

Length of output: 3779

certificate-authority/pb/doc.html (2)

494-511: Review the new CredentialStatus fields

The addition of serial and issuer_id fields enhances certificate tracking capabilities:

  • serial: Tracks the serial number of issued certificates
  • issuer_id: Provides a unique identifier for the certificate issuer

These fields are essential for implementing Certificate Revocation List (CRL) functionality as they help uniquely identify certificates and their issuers.


Line range hint 386-443: Verify the impact of new API endpoints

The addition of new API endpoints with the /certificate-authority prefix while maintaining the old ones suggests a transition period. This could lead to confusion about which endpoint to use.

Let's check if there are any references to these endpoints in other files:

Consider:

  1. Documenting which endpoint is preferred
  2. Adding deprecation notices for the old endpoints if they are being phased out
  3. Including version migration guidelines in the API documentation
certificate-authority/store/store.go (1)

41-41: Verify Compatibility of LoadSigningRecords Signature Change

The LoadSigningRecords method now uses the Process[SigningRecord] generic function type. Ensure that all implementations of the Store interface have been updated to reflect this change to prevent any type compatibility issues.

You can run the following script to find all implementations and verify their signatures:

✅ Verification successful

This will help us find all implementations of the LoadSigningRecords method and verify their signatures.


LoadSigningRecords Signature Change is Properly Implemented

The verification shows that both implementations of the Store interface (MongoDB and CQLDB) have been correctly updated to use the Process[SigningRecord] generic function type in their LoadSigningRecords method signatures:

  • certificate-authority/store/mongodb/signingRecords.go: func (s *Store) LoadSigningRecords(ctx context.Context, owner string, query *store.SigningRecordsQuery, p store.Process[store.SigningRecord]) error
  • certificate-authority/store/cqldb/signingRecords.go: func (s *Store) LoadSigningRecords(ctx context.Context, owner string, query *store.SigningRecordsQuery, p store.Process[store.SigningRecord]) error
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all implementations of LoadSigningRecords in the codebase.

# Expectation: All implementations should use the updated signature with Process[SigningRecord].
rg -A 3 'func.*LoadSigningRecords\(.*Process\[SigningRecord\]'

Length of output: 64


Script:

#!/bin/bash
# Let's first find all files that might contain LoadSigningRecords implementations
rg -l "LoadSigningRecords"

# Then let's look at the actual implementations with more context
rg -B 2 -A 5 "func.*LoadSigningRecords"

Length of output: 3412

certificate-authority/service/http/revocationList.go (4)

27-48: Function createCRL is correctly implemented

The createCRL function correctly constructs a CRL using the provided revocation list, issuer certificate, and private key. The error handling and logic are appropriate.


80-82: Ensure proper handling of write errors to the response

The error returned by w.Write(crl) is currently being returned, which is good. Ensure that any non-nil errors are properly handled by the caller to prevent unnoticed failures.


85-89: Error handling in revocationList method is appropriate

The revocationList method correctly calls writeRevocationList and handles any errors by returning an appropriate HTTP response.


71-71: ⚠️ Potential issue

Correct the typo in method name GetCRLConfiguation

There is a typo in the method name GetCRLConfiguation. It should be GetCRLConfiguration.

Run the following script to verify the correct method name:

pkg/security/certificateSigner/certificateSigner.go (3)

20-20: LGTM

The CRLDistributionPoints field has been correctly added to the SignerConfig struct to support certificate revocation list distribution points.


38-42: LGTM

The WithCRLDistributionPoints option function is properly implemented to set the CRL distribution points in the signer configuration.


Line range hint 84-128: LGTM

The Sign method has been appropriately updated to utilize the new parseCertificateRequest function and to include CRLDistributionPoints in the certificate template.

certificate-authority/service/grpc/signCertificate.go (2)

166-169: Verify the appropriateness of gRPC error codes used.

Throughout the SignCertificate method, errors are returned with codes.InvalidArgument. Some of these errors might be better represented with different gRPC error codes, such as codes.Internal for server errors.

Review the error codes to ensure they accurately represent the nature of the errors according to gRPC best practices.


Line range hint 29-58: Ensure all callers of toSigningRecord are updated with the new parameter.

The function toSigningRecord now includes the additional parameter issuerID. Make sure that all calls to this function throughout the codebase are updated to pass the issuerID to prevent any argument mismatch errors.

Run the following script to verify all usages:

✅ Verification successful

All callers of toSigningRecord are properly updated with the new parameter

Based on the search results, there is only one caller of toSigningRecord in certificate-authority/service/grpc/signer.go, and it correctly passes all three required parameters: owner, s.issuerID, and template. This matches the function signature defined in signCertificate.go. No further updates are needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check all calls to `toSigningRecord` to ensure they include the new `issuerID` parameter.

# Test: Search for calls to `toSigningRecord` and display the number of arguments passed.
rg 'toSigningRecord\(' -A 0 -B 0

Length of output: 288

certificate-authority/service/grpc/signer.go (12)

10-10: Importing github.com/google/uuid for UUID generation.

The addition of the uuid package is appropriate for generating issuer IDs based on the public key.


13-13: Importing uri package for CRL distribution points.

The inclusion of certificate-authority/service/uri is appropriate for constructing CRL distribution point URIs required for CRL management.


23-23: Adding issuerID field to the Signer struct.

The issuerID field is added to uniquely identify the issuer based on the public key. This is appropriate for managing CRLs and associating certificates with their issuers.


26-29: Adding CRL configuration to Signer struct.

The addition of the crl struct within Signer to store CRL server address and validity duration enables CRL support, which is essential for certificate revocation management.


139-141: Adding GetCertificate method to Signer.

The addition of the GetCertificate method allows external components to access the signer's certificate, which can be useful for validation or logging purposes.


147-149: Adding GetCRLConfiguration method to Signer.

This method provides access to the CRL server address and validity duration, which is useful for CRL management and distribution point configuration.


151-153: Adding IsCRLEnabled method to Signer.

This method allows checking if CRL is enabled, enhancing code clarity and facilitating conditional logic based on CRL support.


155-161: Adding newCertificateSigner method for code reuse.

The newCertificateSigner method simplifies the creation of certificate signers based on the identitySigner flag, improving code maintainability and reducing duplication.


162-186: Refactoring signing logic into sign method.

The new sign method consolidates the signing logic for both standard and identity certificates, improving code reuse and maintainability. The inclusion of CRL distribution points when CRL is enabled is appropriate.


188-190: Updating Sign method to use new sign method.

The Sign method now utilizes the consolidated sign function, which streamlines the signing process and reduces code duplication.


192-193: Updating SignIdentityCSR method to use new sign method.

The SignIdentityCSR method now calls sign with isIdentityCertificate set to true, appropriately reusing the signing logic.


48-54: 🛠️ Refactor suggestion

Consider security implications of using SHA1 in UUID generation.

The getIssuerID function uses uuid.NewSHA1 to generate an issuer ID from the public key:

return uuid.NewSHA1(uuid.NameSpaceX500, publicKeyRaw).String(), nil

Since SHA1 is considered cryptographically weak, even though it's used here for generating a UUID, consider if this could introduce any security concerns or potential for collision.

Consider using a more secure hash function if the uuid package supports it, such as SHA256, to reduce the risk of collisions.

certificate-authority/store/mongodb/revocationList.go (4)

75-75: Duplicate Comment

This issue has been previously addressed in the past review comments.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 75-75: Database query built from user-controlled sources
This query depends on a user-provided value.


169-169: Duplicate Comment

This issue has been previously addressed in the past review comments.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 169-169: Database query built from user-controlled sources
This query depends on a user-provided value.


209-209: Duplicate Comment

This issue has been previously addressed in the past review comments.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 209-209: Database query built from user-controlled sources
This query depends on a user-provided value.


178-217: Verify the correctness of the includeExpired filter logic

When includeExpired is false, the filter modifies the query to return only non-expired certificates. Ensure that this logic aligns with the intended functionality and that it correctly filters out expired certificates.

Verification Script:

✅ Verification successful

Based on the examination of the code and tests, I can now provide the final response:

The includeExpired filter logic in GetRevocationList is correctly implemented

The implementation correctly filters expired certificates when includeExpired is false by:

  1. Using a MongoDB $elemMatch to match documents containing at least one non-expired certificate
  2. Using $filter in the projection to return only non-expired certificates in the results
  3. Comparing certificate validity (ValidUntil) against the current time (now)

The test cases verify this behavior:

  • "all from issuer0" test confirms retrieval of all certificates when includeExpired=true
  • "no valid from issuer0" test verifies that an error is returned when no valid certificates exist and includeExpired=false
  • "non-expired from issuer4" test validates that only non-expired certificates are returned when includeExpired=false
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the GetRevocationList function correctly filters expired certificates when includeExpired is false.

# Test: Fetch a revocation list with includeExpired=false and ensure no expired certificates are returned.
# Expected Result: All certificates in the revocation list have ValidUntil >= current time.

# Note: Replace <issuerID> with a valid issuer ID for testing.
issuerID="<issuerID>"
currentTime=$(date +%s%N)

# MongoDB query simulation (pseudocode)
mongo --eval "
db.revocationList.find({
    _id: '$issuerID',
    certificates: {
        \$elemMatch: {
            ValidUntil: { \$gte: $currentTime }
        }
    }
}, {
    certificates: {
        \$filter: {
            input: '\$certificates',
            as: 'cert',
            cond: { \$gte: ['\$\$cert.ValidUntil', $currentTime] }
        }
    }
})
"

Length of output: 542


Script:

#!/bin/bash
# Let's analyze the implementation by looking at tests and related code

# Find test files related to revocation list
fd "revocation.*test.*" 

# Search for test cases specifically testing the includeExpired functionality
rg -l "includeExpired.*GetRevocationList|GetRevocationList.*includeExpired" 

# Look for any other usages of GetRevocationList to understand the expected behavior
ast-grep --pattern 'GetRevocationList($$$)'

# Search for any comments or documentation about the expired certificates filtering
rg -i "expired.*(certificate|revocation)" 

Length of output: 70327


Script:

#!/bin/bash
# Let's examine the test files to understand the expected behavior of includeExpired parameter

# Look at the revocation list test files
rg -A 10 "GetRevocationList.*includeExpired" certificate-authority/store/mongodb/revocationList_test.go
rg -A 10 "GetRevocationList.*includeExpired" certificate-authority/store/revocationList_test.go

# Check if there are any other test cases related to expired certificates in the revocation list
rg -A 10 "expired.*certificate.*revocation" certificate-authority/store/mongodb/revocationList_test.go

Length of output: 579


Script:

#!/bin/bash
# Let's look at the test cases and implementation more comprehensively

# Find the test cases for GetRevocationList
rg -B 10 "GetRevocationList.*includeExpired" certificate-authority/store/mongodb/revocationList_test.go

# Look at the test helper function
rg -A 10 "CheckRevocationList" certificate-authority/store/revocationList_test.go

# Check the store interface definition
rg -A 5 "type.*Store.*interface" certificate-authority/store/store.go

Length of output: 1059


Script:

#!/bin/bash
# Let's examine the test file content to understand the test cases

# Get the full content of the test file
cat certificate-authority/store/mongodb/revocationList_test.go

# Look for any test data setup related to expired certificates
rg -B 5 "ValidUntil.*now" certificate-authority/store/mongodb/revocationList_test.go
rg -B 5 "ValidUntil.*time" certificate-authority/store/mongodb/revocationList_test.go

Length of output: 9802

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 209-209: Database query built from user-controlled sources
This query depends on a user-provided value.

certificate-authority/service/http/requestHandler.go Outdated Show resolved Hide resolved
certificate-authority/service/http/requestHandler.go Outdated Show resolved Hide resolved
certificate-authority/service/grpc/config.go Outdated Show resolved Hide resolved
certificate-authority/pb/signingRecords.proto Outdated Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Outdated Show resolved Hide resolved
certificate-authority/store/mongodb/revocationList.go Outdated Show resolved Hide resolved
certificate-authority/store/mongodb/revocationList.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 32

🧹 Outside diff range and nitpick comments (26)
pkg/security/x509/crl.go (1)

8-17: Enhance error handling and messages

While the implementation is functional, consider these improvements:

  1. Wrap the original error for better debugging
  2. Provide more specific error messages about URL requirements

Consider this enhancement:

 func ValidateCRLDistributionPointAddress(s string) error {
 	u, err := url.ParseRequestURI(s)
 	if err != nil {
-		return fmt.Errorf("invalid address(%s)", s)
+		return fmt.Errorf("invalid CRL distribution point address %q: %w", s, err)
 	}
 	if !u.IsAbs() {
-		return fmt.Errorf("invalid relative URL address(%s)", s)
+		return fmt.Errorf("CRL distribution point address %q must be absolute URL", s)
 	}
 	return nil
 }
certificate-authority/service/http/requestHandler.go (1)

57-59: Consider improving the error message specificity.

The error message could be more specific about what failed during handler registration.

-		return nil, fmt.Errorf("failed to register certificate-authority handler: %w", err)
+		return nil, fmt.Errorf("failed to register certificate-authority gRPC gateway handler: %w", err)
certificate-authority/store/mongodb/store.go (1)

37-51: LGTM: Well-designed iterator implementation

The generic MongoIterator implementation provides a clean abstraction over mongo.Cursor with proper error handling and type safety.

Consider adding a doc comment to describe the purpose of MongoIterator:

// MongoIterator provides a generic type-safe iterator over MongoDB cursor results
certificate-authority/store/store.go (1)

53-54: Consider separating Get and Issue operations

The method GetLatestIssuedOrIssueRevocationList combines two distinct operations. This could make error handling and testing more complex. Consider splitting into two methods:

  1. GetLatestValidRevocationList
  2. IssueNewRevocationList

This separation would:

  • Make the interface more predictable
  • Simplify error handling
  • Make testing easier
  • Allow for more specific error cases
certificate-authority/pb/service.proto (1)

80-86: Consider separating revocation from cleanup operations.

While the documentation improvement clarifies the dual purpose, consider:

  1. Splitting this into two separate endpoints:
    • /certificate-authority/api/v1/signing/records/revoke for certificate revocation
    • /certificate-authority/api/v1/signing/records/cleanup for expired record deletion

This separation would:

  • Make the API more intuitive
  • Allow different authorization policies for each operation
  • Enable better monitoring and auditing of revocation events
certificate-authority/service/grpc/deleteSigningRecords_test.go (2)

25-28: Consider using test helpers for JWT token creation.

While the current implementation works, consider extracting the token creation logic into a test helper function since it might be reused across other test files dealing with authentication.

+func createTestToken(t *testing.T, owner string) string {
+    return config.CreateJwtToken(t, jwt.MapClaims{
+        ownerClaim: owner,
+    })
+}

Line range hint 1-119: Consider adding CRL-specific test cases.

While the basic CRUD operations are well tested, consider adding specific test cases for CRL-related scenarios:

  1. Deleting records for revoked certificates
  2. Handling multiple records with the same issuer
  3. Validation of serial number formats

Would you like me to help draft these additional test cases?

certificate-authority/service/cleanDatabase_test.go (1)

Line range hint 93-94: Consider making the test more reliable.

The test uses real time delays (time.Sleep(4 * time.Second)), which could lead to flaky tests in CI environments. Consider using a mock clock or time provider to make the test more deterministic.

Example approach using a mock clock:

type mockClock struct {
    currentTime time.Time
}

func (m *mockClock) Now() time.Time {
    return m.currentTime
}

func (m *mockClock) Advance(d time.Duration) {
    m.currentTime = m.currentTime.Add(d)
}
certificate-authority/service/grpc/getSigningRecords_test.go (1)

92-92: Consider using url.Parse for robust URL construction.

While the URL construction works, it would be more robust to use url.Parse or url.URL to handle URL construction properly.

-"https://"+config.CERTIFICATE_AUTHORITY_HTTP_HOST
+(&url.URL{
+    Scheme: "https",
+    Host:   config.CERTIFICATE_AUTHORITY_HTTP_HOST,
+}).String()
certificate-authority/service/http/signCertificate_test.go (1)

Line range hint 1-130: Consider adding comprehensive CRL-specific test cases

Since this is part of a Certificate Revocation List implementation, consider adding test cases that specifically verify:

  1. Certificates are always issued with unique serial numbers
  2. Revoked certificate serials are tracked
  3. New certificates cannot reuse serials from revoked certificates

This will ensure the CRL implementation maintains proper certificate uniqueness and tracking.

certificate-authority/service/config.go (2)

44-47: Improve error message specificity.

The current error message wraps the entire signer config, making it unclear which parameter caused the error. Consider making it more specific to help with troubleshooting.

-	return fmt.Errorf("signer('%v') - %w", c.Signer, err)
+	return fmt.Errorf("failed to create signer: %w", err)

69-71: Add field documentation.

Consider adding documentation for the ExternalAddress field to explain its purpose and format requirements.

 type HTTPConfig struct {
+	// ExternalAddress is the publicly accessible URL for the CRL distribution point
+	// It must be a valid HTTPS URL that clients can use to fetch certificate revocation lists
 	ExternalAddress string            `yaml:"externalAddress" json:"externalAddress"`
 	Addr            string            `yaml:"address" json:"address"`
 	Server          httpServer.Config `yaml:",inline" json:",inline"`
 }
certificate-authority/test/service.go (2)

25-31: Consider adding host configuration validation

While the function correctly sets up the HTTP configuration, it might be beneficial to add validation for the CERTIFICATE_AUTHORITY_HTTP_HOST constant to ensure it's properly formatted and available.

 func MakeHTTPConfig() service.HTTPConfig {
+	if config.CERTIFICATE_AUTHORITY_HTTP_HOST == "" {
+		panic("CERTIFICATE_AUTHORITY_HTTP_HOST is not set")
+	}
 	return service.HTTPConfig{
 		ExternalAddress: "https://" + config.CERTIFICATE_AUTHORITY_HTTP_HOST,
 		Addr:            config.CERTIFICATE_AUTHORITY_HTTP_HOST,
 		Server:          config.MakeHttpServerConfig(),
 	}
 }

33-43: Enhance CRL configuration documentation and flexibility

A few suggestions for improvement:

  1. The MongoDB-only limitation for CRL should be documented with a comment explaining why.
  2. Consider making the expiration time configurable through environment variables or configuration.
+// MakeCRLConfig creates a CRL configuration. Currently, CRL is only supported
+// for MongoDB as it requires specific storage capabilities for managing
+// revocation lists efficiently.
 func MakeCRLConfig() grpc.CRLConfig {
 	if config.ACTIVE_DATABASE() == database.MongoDB {
 		return grpc.CRLConfig{
 			Enabled:   true,
-			ExpiresIn: time.Hour,
+			ExpiresIn: config.GetEnvDuration("CRL_EXPIRES_IN", time.Hour),
 		}
 	}
 	return grpc.CRLConfig{
 		Enabled: false,
 	}
 }
certificate-authority/service/grpc/signer_internal_test.go (1)

117-146: Enhance CRL test coverage with additional scenarios.

Good progress on CRL test cases! Consider adding these scenarios to strengthen the test coverage:

  1. Empty CRL server address with CRL-enabled configuration
  2. Edge cases:
    • CRL server with trailing slash
    • CRL server with query parameters
    • Zero/negative ExpiresIn duration

Example test case:

{
    name: "crl enabled but empty server",
    args: args{
        signerConfig: SignerConfig{
            CertFile: urischeme.URIScheme(fullChainCrt),
            KeyFile:  urischeme.URIScheme(intermediate2Key),
            CRL: CRLConfig{
                Enabled:   true,
                ExpiresIn: time.Hour,
            },
        },
        crlServer: "",
    },
    wantErr: true,
},
certificate-authority/service/service.go (1)

123-123: Review direct database access in HTTP handlers.

The change to pass dbStorage directly to HTTP service instead of accessing through the CA server suggests a potential architectural concern. Consider:

  1. Whether this bypasses important business logic in the CA server
  2. If proper encapsulation is maintained
  3. Whether all database operations are properly audited and logged

This architectural change might impact:

  • Security (direct DB access vs. controlled access through CA server)
  • Maintainability (scattered business logic)
  • Auditability (tracking certificate operations)

Consider keeping the database access encapsulated within the CA server and exposing only necessary operations through well-defined interfaces.

certificate-authority/store/mongodb/signingRecords.go (1)

121-121: Add documentation for the RevokeSigningRecords method

Consider adding documentation to explain the method's purpose, parameters, and behavior, especially regarding the handling of expired certificates.

+// RevokeSigningRecords revokes signing records for the given owner and query.
+// It handles expired certificates by deleting them without adding them to the revocation list.
+// For valid certificates, it adds them to their respective issuer's revocation list before deletion.
 func (s *Store) RevokeSigningRecords(ctx context.Context, ownerID string, query *store.RevokeSigningRecordsQuery) (int64, error) {
certificate-authority/service/http/revocationList_test.go (3)

25-44: LGTM! Consider adding boundary value tests.

The validation logic is thorough and handles all necessary CRL fields correctly. However, consider adding test cases for edge cases such as empty certificate lists and maximum-sized serial numbers.


49-49: Consider using a fixed timestamp for tests.

Using time.Now() in tests can lead to flaky behavior. Consider using a fixed timestamp:

-now := time.Now()
+now := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)

163-168: Add HTTP status code assertions.

The test should verify the expected HTTP status codes for different scenarios:

 httpResp := httpgwTest.HTTPDo(t, request)
+require.Equal(t, http.StatusOK, httpResp.StatusCode)
 respBody, err := io.ReadAll(httpResp.Body)
certificate-authority/service/grpc/signCertificate.go (1)

63-94: Consider enhancing error handling for edge cases.

While the function handles the basic cases well, consider these improvements:

  1. Return a specific error when no record is found (currently returns nil, nil)
  2. Add logging for better debugging of lookup paths

Consider this enhancement:

 func (s *CertificateAuthorityServer) getSigningRecord(ctx context.Context, signingRecord *pb.SigningRecord) (*pb.SigningRecord, error) {
     // ... existing code ...
     if err != nil {
         return nil, err
     }
+    if originalSr == nil {
+        return nil, fmt.Errorf("no signing record found for %s", signingRecord.GetId())
+    }
     return originalSr, nil
 }
certificate-authority/store/mongodb/revocationList_test.go (1)

190-235: Consider improving parallel test reliability and readability.

The parallel test implementation has a few areas for improvement:

  1. The magic number 100 in the retry loop should be a named constant
  2. The test might be flaky due to timing dependencies

Consider these improvements:

+const (
+    maxRetries = 100
+    concurrentWorkers = 10
+)

-for range 100 {
+for range maxRetries {

Also, consider adding jitter to the retry mechanism to reduce contention:

time.Sleep(time.Duration(rand.Int63n(100)) * time.Millisecond)
certificate-authority/store/cqldb/signingRecords.go (1)

342-367: LGTM with a minor suggestion about error variable naming.

The implementation correctly handles the migration to the new Process type and maintains proper error handling. However, consider renaming errClose to closeErr to align with Go's common error variable naming conventions.

-errClose := i.close()
+closeErr := i.close()
 if err == nil {
-    return errClose
+    return closeErr
 }
 return err
certificate-authority/store/cqldb/signingRecords_test.go (3)

Line range hint 41-90: Add validation test cases for Serial and IssuerId

The test suite should include cases that verify the validation of the new fields:

  • Invalid serial number formats
  • Invalid issuer ID formats (non-UUID)
  • Empty/nil values

Consider adding these test cases:

{
    name: "invalid serial format",
    args: args{
        sub: &store.SigningRecord{
            Id:         id1,
            Owner:      "owner",
            CommonName: "commonName",
            Credential: &pb.CredentialStatus{
                Serial:   "invalid",
                IssuerId: "42424242-4242-4242-4242-424242424242",
            },
        },
    },
    wantErr: true,
},
{
    name: "invalid issuer ID format",
    args: args{
        sub: &store.SigningRecord{
            Id:         id1,
            Owner:      "owner",
            CommonName: "commonName",
            Credential: &pb.CredentialStatus{
                Serial:   big.NewInt(42).String(),
                IssuerId: "invalid",
            },
        },
    },
    wantErr: true,
},

Line range hint 557-600: Add sequential benchmark for baseline comparison

The current benchmark uses concurrent updates which might mask potential performance issues with the new fields. Consider adding a sequential benchmark for baseline comparison.

Add this benchmark function:

func BenchmarkSigningRecordsSequential(b *testing.B) {
    // Same setup as BenchmarkSigningRecords
    
    for i := uint32(0); i < uint32(b.N); i++ {
        b.StopTimer()
        err := s.ClearTable(ctx)
        require.NoError(b, err)
        b.StartTimer()
        
        // Sequential updates
        for _, l := range data {
            err := s.UpdateSigningRecord(ctx, l)
            assert.NoError(b, err)
        }
    }
}

Line range hint 1-600: Consider additional security measures for CRL implementation

While the basic structure for CRL is in place, consider these security aspects:

  1. Ensure serial numbers are cryptographically secure when generated in production
  2. Consider adding tests for serial number uniqueness
  3. Add validation for minimum serial number length

Would you like assistance in implementing these security measures?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 36e6847 and 0b23411.

⛔ Files ignored due to path filters (10)
  • certificate-authority/config.yaml is excluded by !**/*.yaml
  • certificate-authority/pb/service.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • certificate-authority/pb/service.swagger.json is excluded by !**/*.json
  • certificate-authority/pb/service_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/signingRecords.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • charts/plgd-hub/templates/certificate-authority/config.yaml is excluded by !**/*.yaml
  • charts/plgd-hub/values.yaml is excluded by !**/*.yaml
  • device-provisioning-service/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • device-provisioning-service/pb/service.swagger.json is excluded by !**/*.json
📒 Files selected for processing (56)
  • bundle/nginx/nginx.conf.template (1 hunks)
  • certificate-authority/pb/README.md (3 hunks)
  • certificate-authority/pb/doc.html (7 hunks)
  • certificate-authority/pb/service.proto (2 hunks)
  • certificate-authority/pb/signingRecords.go (3 hunks)
  • certificate-authority/pb/signingRecords.proto (2 hunks)
  • certificate-authority/pb/signingRecords_test.go (1 hunks)
  • certificate-authority/service/cleanDatabase_test.go (5 hunks)
  • certificate-authority/service/config.go (3 hunks)
  • certificate-authority/service/config_test.go (1 hunks)
  • certificate-authority/service/grpc/config.go (2 hunks)
  • certificate-authority/service/grpc/config_test.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords_test.go (4 hunks)
  • certificate-authority/service/grpc/getSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/getSigningRecords_test.go (5 hunks)
  • certificate-authority/service/grpc/server.go (2 hunks)
  • certificate-authority/service/grpc/server_test.go (1 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signCertificate_test.go (4 hunks)
  • certificate-authority/service/grpc/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/grpc/signer_internal_test.go (3 hunks)
  • certificate-authority/service/http/config.go (1 hunks)
  • certificate-authority/service/http/requestHandler.go (1 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/service/http/service.go (2 hunks)
  • certificate-authority/service/http/signCertificate_test.go (6 hunks)
  • certificate-authority/service/http/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/service.go (2 hunks)
  • certificate-authority/service/uri/uri.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords_test.go (18 hunks)
  • certificate-authority/store/mongodb/bulkWriter.go (0 hunks)
  • certificate-authority/store/mongodb/config.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList_test.go (1 hunks)
  • certificate-authority/store/mongodb/signingRecords.go (3 hunks)
  • certificate-authority/store/mongodb/signingRecords_test.go (13 hunks)
  • certificate-authority/store/mongodb/store.go (3 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList_test.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • certificate-authority/test/revocationList.go (1 hunks)
  • certificate-authority/test/service.go (2 hunks)
  • charts/plgd-hub/README.md (0 hunks)
  • device-provisioning-service/Makefile (1 hunks)
  • device-provisioning-service/pb/service.proto (4 hunks)
  • http-gateway/test/http.go (1 hunks)
  • http-gateway/uri/uri.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (0 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (0 hunks)
  • pkg/security/x509/crl.go (1 hunks)
💤 Files with no reviewable changes (4)
  • certificate-authority/store/mongodb/bulkWriter.go
  • charts/plgd-hub/README.md
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🚧 Files skipped from review as they are similar to previous changes (24)
  • bundle/nginx/nginx.conf.template
  • certificate-authority/pb/README.md
  • certificate-authority/pb/signingRecords.proto
  • certificate-authority/pb/signingRecords_test.go
  • certificate-authority/service/config_test.go
  • certificate-authority/service/grpc/config_test.go
  • certificate-authority/service/grpc/deleteSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords.go
  • certificate-authority/service/grpc/server.go
  • certificate-authority/service/grpc/server_test.go
  • certificate-authority/service/grpc/signCertificate_test.go
  • certificate-authority/service/grpc/signIdentityCertificate_test.go
  • certificate-authority/service/http/config.go
  • certificate-authority/service/http/service.go
  • certificate-authority/service/http/signIdentityCertificate_test.go
  • certificate-authority/service/uri/uri.go
  • certificate-authority/store/cqldb/revocationList.go
  • certificate-authority/store/mongodb/config.go
  • certificate-authority/store/revocationList_test.go
  • certificate-authority/test/revocationList.go
  • device-provisioning-service/Makefile
  • device-provisioning-service/pb/service.proto
  • http-gateway/test/http.go
  • http-gateway/uri/uri.go
🧰 Additional context used
📓 Learnings (2)
certificate-authority/store/mongodb/revocationList.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
certificate-authority/store/mongodb/signingRecords.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
🪛 GitHub Check: CodeQL
certificate-authority/store/mongodb/revocationList.go

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.

🔇 Additional comments (75)
pkg/security/x509/crl.go (2)

1-6: LGTM: Clean package structure with appropriate imports

The package name and imports are well-organized and follow Go conventions.


8-17: Verify consistent URL validation across the codebase

Let's ensure this validation is consistently applied wherever CRL distribution points are handled.

✅ Verification successful

Let me gather more specific information about the CRL-related code to make a better assessment.


Let me search for any other URL validation functions and CRL-related code to make a thorough assessment.


Based on the search results, I can now provide a final assessment. The code shows that the ValidateCRLDistributionPointAddress function is consistently used throughout the codebase:

  1. It's used in the certificate authority's HTTP configuration validation (certificate-authority/service/config.go)
  2. It's used in the certificate signer's CRL setup (certificate-authority/service/grpc/signer.go)
  3. The CRL distribution points are properly propagated through the certificate signer configuration (pkg/security/certificateSigner/certificateSigner.go)

The validation is appropriately applied at all points where CRL distribution point URLs are handled, ensuring consistent URL validation across the codebase.

URL validation is consistently applied for CRL distribution points

The validation function is used at all required points in the codebase where CRL distribution point URLs are configured or validated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other CRL distribution point URL handling in the codebase
# that might need to use this validation function

# Look for CRL-related URL handling
rg -l "(?i)(crl|distribution.*point|revocation.*list).*\b(url|address|endpoint)\b"

# Look for direct URL parsing that might need this validation
ast-grep --pattern 'url.Parse$_($$$)'

Length of output: 224


Script:

#!/bin/bash
# Check the actual content of files that mention CRL/distribution points
rg -A 5 -B 5 "(?i)(crl|distribution.*point|revocation.*list).*\b(url|address|endpoint)\b"

# Look specifically for imports or usage of the x509 package where this validation function resides
rg -l "\".*security/x509\""

# Check for any other URL validation functions that might be doing similar work
ast-grep --pattern 'func $_($_ string) error {
  $$$
  url.Parse$_($$$)
  $$$
}'

Length of output: 60814


Script:

#!/bin/bash
# Look for URL validation functions and CRL-related code
rg -A 5 -B 5 "func.*ValidateURL|func.*ValidateAddress|func.*ValidateCRL"

# Check for CRL distribution point URL usage
rg -A 5 -B 5 "CRLDistributionPoint|DistributionPoint.*URL"

# Look for URL validation in tests
rg -A 5 "url.Parse.*test" 

Length of output: 6555

certificate-authority/service/http/requestHandler.go (4)

5-5: LGTM: Import statements are well-organized.

The new imports are properly organized and necessary for the added functionality.

Also applies to: 7-7, 14-15


19-25: LGTM: Type definition follows Go best practices.

The struct has been properly made package-private and the new fields are well-organized.


30-41: LGTM: Parameter validation is thorough.

The implementation properly validates all required dependencies, preventing potential nil pointer panics.


49-50: Address pending CRL-related concerns.

While the CRL route registration is implemented correctly, there are two important items that need to be addressed:

  1. Cache Control Headers: The CRL endpoint should include appropriate cache control headers to optimize performance.
  2. Documentation: The CRL feature flag needs proper documentation and configuration guidance.

These issues were previously identified in the past reviews and still need to be addressed. Would you like assistance with implementing either of these improvements?

certificate-authority/pb/signingRecords.go (2)

6-6: LGTM: Appropriate import for certificate serial number handling.

The addition of math/big is correct for handling certificate serial numbers which can be arbitrarily large integers.


67-69: LGTM: Clean delegation of credential validation.

The changes correctly delegate credential validation to the new CredentialStatus.Validate method, reducing code duplication.

Let's verify that all credential validations are properly handled:

✅ Verification successful

Based on the verification results, I can now provide a final response:

Credential validation delegation is properly implemented and tested

The verification confirms:

  • The CredentialStatus.Validate() method has proper test coverage in certificate-authority/pb/signingRecords_test.go
  • The delegation pattern is correctly implemented with proper nil checks
  • No other credential validation implementations that could conflict were found
  • The validation logic is comprehensive, checking all required fields (date, validUntilDate, certificatePem, serial, issuerId)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any missed credential validations in tests or related files

# Test 1: Look for test coverage of credential validation
rg -l "TestCredentialStatus.*Validate|TestSigningRecord.*Validate" --type go

# Test 2: Check for any direct field access that might bypass validation
ast-grep --pattern 'credential.$$$' --type go

# Test 3: Look for other credential validation implementations that might conflict
rg "func.*Validate.*Credential" --type go

Length of output: 398


Script:

#!/bin/bash
# Let's improve our verification with correct syntax and broader checks

# Check for test coverage
rg "func Test.*Credential.*|func Test.*SigningRecord.*" --type go -A 5

# Check credential validation patterns correctly
ast-grep --pattern 'if credential := $_.GetCredential(); credential != nil {
  $$$
}'

# Look for credential-related validation methods
rg "func.*Validate" --type go -A 2

# Check direct credential field access
rg "credential\." --type go -A 2

Length of output: 87638

certificate-authority/service/grpc/config.go (2)

40-40: LGTM!

The CRL configuration is properly integrated into the SignerConfig structure with appropriate serialization tags.


16-22: Enhance security constraints for CRL configuration

The current CRL configuration lacks several important security constraints:

  1. No maximum validity period for CRLs is enforced
  2. No validation exists to ensure CRL validity period doesn't exceed the CA certificate's validity
  3. Consider adding a minimum update frequency field to ensure timely revocation updates

Let's check if these constraints are handled elsewhere:

Consider adding:

  1. MaxValidityPeriod field with a reasonable default (e.g., 7 days)
  2. MinUpdateFrequency field to enforce regular updates
  3. Validation to ensure CRL validity doesn't exceed the CA cert's validity
certificate-authority/store/mongodb/store.go (4)

7-7: LGTM: Store struct refactoring

The removal of bulkWriter in favor of logger and the addition of multierror handling aligns well with the architectural changes described in the PR objectives.

Also applies to: 20-20


53-75: Previous review comment is still applicable

The suggestion to continue processing after encountering an error remains valid for this code segment.


100-103: LGTM: Improved error handling in clearDatabases

The use of multierror for aggregating collection drop errors provides better error reporting.


82-92: LGTM: Improved store initialization

The use of NewStoreWithCollections provides better initialization structure. However, let's verify the index configuration.

✅ Verification successful

The search results show consistent usage of MongoDB indexes across different services. For the certificate-authority service, the index configuration appears correct and follows the established patterns:

  1. The signingRecordsCol has two indexes:

    • commonNameKeyQueryIndex for efficient queries on common name + owner
    • deviceIDKeyQueryIndex for efficient queries on device ID + owner
  2. The revocationListCol has no indexes which is acceptable if it doesn't require specific query patterns.

The implementation aligns with other services in the codebase that use similar compound indexes for owner-based queries. For example:

  • identity-store uses owner+deviceID indexes
  • m2m-oauth-server uses ID+owner indexes
  • device-provisioning-service uses similar owner-based compound indexes

Index configuration is properly implemented

The index setup follows the established patterns across the codebase and provides efficient querying capabilities for the certificate authority's common use cases.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify index configuration consistency across the codebase
# Look for other collections that might need similar indexes

# Search for collection index definitions
rg -g '*.go' "mongo\.IndexModel" -A 5

Length of output: 15127

certificate-authority/store/store.go (2)

13-17: LGTM: Well-defined error variables

The new error variables follow Go conventions and provide clear, specific error cases needed for CRL operations.


56-57: Verify transaction safety for revocation operation

The operation involves two steps: removing records and adding them to the revocation list. This should be atomic to prevent data inconsistency.

certificate-authority/pb/service.proto (3)

57-60: LGTM! The additional binding maintains API consistency.

The new endpoint follows the same pattern as SignIdentityCertificate, maintaining a consistent API structure.


67-73: Enhance documentation for streaming behavior.

While the endpoint addition is good, the documentation "Get signed certificate records" could be more descriptive about:

  • The streaming nature of the response
  • Any pagination or batch size limitations
  • Expected response format

Additionally, note that the previous review comments about streaming implementation (context cancellation, backpressure management) should still be addressed in the handler implementation.


41-44: LGTM! Verify security controls for the new endpoint.

The additional binding follows consistent API design patterns. Ensure that the new endpoint /certificate-authority/api/v1/sign/identity-csr is properly secured with the same authentication and authorization controls as the existing endpoint.

✅ Verification successful

Based on the evidence gathered, I can now provide a final response regarding the security of the new endpoint:

The new endpoint is properly secured with authentication controls

The code analysis reveals that:

  • The service uses a common authentication middleware for all endpoints (CreateAuthMiddleware)
  • JWT token validation is implemented through the validator package
  • Both HTTP and gRPC services are configured with proper authorization:
    • HTTP service is initialized with auth middleware and token validation
    • gRPC service uses auth interceptors via server.NewAuth(validator)
  • The new endpoint inherits these security controls as part of the service's global configuration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if authentication middleware is consistently applied
rg -A 5 "certificate-authority/api/v1/sign/identity-csr" bundle/nginx/nginx.conf.template

Length of output: 89


Script:

#!/bin/bash
# Let's try a broader search to understand the security setup
# First, check for any auth middleware or security configurations
rg -i "auth.*middleware|security.*config" -A 5

# Also search for the base path to see routing setup
rg "/certificate-authority/api" -A 5

# Check for any gRPC interceptors or middleware in Go files
ast-grep --pattern 'func $_(ctx context.Context, req *$_) (*$_, error) {
  $$$
}'

Length of output: 124199


Script:

#!/bin/bash
# Let's check for authentication middleware configuration in the certificate authority service
rg -A 10 "CreateAuthMiddleware|authMiddleware" certificate-authority/

# Also check for any security interceptors in the service implementation
ast-grep --pattern 'func New$_($_) (*$_, error) {
  $$$
}'

# And look for any security configurations in the service setup
rg -A 5 "security.*config|auth.*config" certificate-authority/

Length of output: 1985


Script:

#!/bin/bash
# Let's check the HTTP server configuration and middleware setup
rg -A 10 "func New.*Server|func main" certificate-authority/service/

# Check for any gRPC interceptors that might handle auth
rg -A 10 "UnaryServerInterceptor|StreamServerInterceptor" certificate-authority/

# Look for JWT or auth token validation code
rg -A 5 "jwt|token|auth.*valid" certificate-authority/

Length of output: 18942

certificate-authority/store/revocationList.go (1)

1-10: LGTM: Package structure and imports are appropriate.

The package name and imports align well with the CRL storage functionality.

certificate-authority/service/grpc/deleteSigningRecords_test.go (5)

5-5: LGTM: Required imports for enhanced functionality.

The addition of math/big is appropriate for handling certificate serial numbers, and pkgGrpc is needed for token context management.

Also applies to: 17-17


53-62: LGTM: Good security test coverage.

The new test case for missing token is a valuable addition to security testing, ensuring proper authentication checks.


109-113: LGTM: Improved error handling in tests.

The error handling has been enhanced with proper checks and early returns, making the test results more reliable.


100-100: Verify HTTPS configuration for production readiness.

The server initialization now includes the HTTPS host, which is good. However, we should ensure this aligns with the CRL distribution point requirements.

#!/bin/bash
# Check if the HTTPS configuration is consistently used for CRL endpoints
echo "Checking HTTPS configuration in CRL related code..."
rg "crl.*endpoint|distribution.*point" 

echo "Checking certificate authority HTTP host usage..."
rg "CERTIFICATE_AUTHORITY_HTTP_HOST"

39-40: Verify serial number and issuer ID format consistency.

The test uses appropriate fields for certificate tracking, but we should verify that these formats align with the actual CRL implementation requirements.

✅ Verification successful

Based on the search results, I can now provide a conclusive response about the serial number and issuer ID format consistency:

Serial number and issuer ID formats are consistent with implementation requirements

The verification shows:

  • The serial number format using big.NewInt(42).String() in the test aligns with the RevocationListCertificate struct which stores serials as strings
  • The issuer ID format using UUID pattern "42424242-4242-4242-4242-424242424242" is consistent across all test files and is validated in the codebase (pb/signingRecords.go validates issuer IDs using uuid.Parse)
  • This format is used consistently across multiple test files in the certificate-authority module, including store implementations for both MongoDB and CQLDB
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for consistent serial number and issuer ID formats across the codebase
echo "Checking serial number format consistency..."
rg -A 2 "Serial.*big\.NewInt|Serial.*String\(\)" 

echo "Checking issuer ID format consistency..."
rg -A 2 "IssuerId.*[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"

Length of output: 2216


Script:

#!/bin/bash
# Let's try a more focused search for serial numbers and issuer IDs

# Check serial number formats in test files
echo "Checking serial number formats in tests..."
rg -l "Serial.*" --type go --type test

# Check actual serial number implementations
echo -e "\nChecking serial number implementations..."
rg -A 3 "type.*Record.*struct" --type go

# Check issuer ID patterns
echo -e "\nChecking issuer ID patterns..."
rg -A 2 "IssuerId.*" --type go

# Look for any CRL or certificate record related structs
echo -e "\nChecking certificate record structures..."
ast-grep --pattern 'type $_ struct {
  $$$
  Serial $$$
  $$$
}'

Length of output: 16807

certificate-authority/service/cleanDatabase_test.go (3)

8-8: LGTM: Import changes align with new requirements.

The addition of math/big supports the new Serial field, and the package alias change maintains consistency across the codebase.

Also applies to: 21-21


79-79: LGTM: Package alias update.

The context creation logic remains unchanged, only the package reference has been updated.

#!/bin/bash
# Description: Verify consistent usage of pkgGrpc across the codebase
# Expect: No instances of kitNetGrpc remain

rg 'kitNetGrpc' --type go

52-53: Verify UUID format for IssuerId field.

The new fields enhance certificate tracking capabilities. However, let's verify the UUID format used in other test cases.

✅ Verification successful

UUID format is consistent across test files

The IssuerId field consistently uses the UUID format "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" across all test files in the certificate-authority module. The test value "42424242-4242-4242-4242-424242424242" follows this standard format.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check UUID format consistency across test files
# Expected format: "42424242-4242-4242-4242-424242424242"

rg -A 1 'IssuerId.*:.*"[0-9a-f-]{36}"' --type go

Length of output: 46650


Script:

#!/bin/bash
# Search for UUID format patterns in test files
rg -A 1 'IssuerId.*:.*"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"' --type go

Length of output: 4908

certificate-authority/service/grpc/getSigningRecords_test.go (3)

7-7: LGTM: Required import for certificate serial number handling.

The addition of "math/big" import is appropriate for handling certificate serial numbers as large integers.


101-101: LGTM: Consistent with package refactoring.

The context creation change aligns with the package alias update.


20-20: Verify consistent usage of the new package alias.

The package alias has been changed from kitNetGrpc to pkgGrpc. Let's verify this change is consistent across the codebase.

#!/bin/bash
# Description: Check for any remaining references to the old package alias
# and verify consistent usage of the new one

echo "Checking for old alias usage..."
rg "kitNetGrpc" -l

echo "Verifying new alias usage pattern..."
rg "pkgGrpc.*CtxWithToken" -l
pkg/security/certificateSigner/certificateSigner.go (3)

Line range hint 66-82: LGTM! Well-structured CSR parsing function

The function properly handles:

  • PEM decoding
  • CSR parsing
  • Signature validation
  • Error cases

18-21: Consider validating CRL distribution points URLs

While the addition of CRLDistributionPoints is correct, consider adding validation to ensure the URLs are properly formatted and accessible. This could prevent issues with invalid CRL endpoints being configured.

Let's check if there's URL validation elsewhere in the codebase:

Consider implementing validation either:

  1. At configuration time using a validator interface
  2. In the WithCRLDistributionPoints option function

Line range hint 84-128: Consider CRL update frequency in certificate validity period

The certificate validity period should be aligned with CRL update frequency to ensure timely revocation capability. Long-lived certificates with infrequently updated CRLs could pose security risks.

Let's check for CRL update configuration:

Consider:

  1. Documenting the relationship between certificate validity and CRL update frequency
  2. Adding validation to ensure the certificate validity period doesn't exceed maximum recommended duration based on CRL update frequency
  3. Implementing CRL caching and refresh mechanisms if not already present
certificate-authority/service/http/signCertificate_test.go (4)

16-16: LGTM: Import changes improve maintainability

The centralization of URI definitions through certAuthURI and the update to pkgGrpc align with best practices for configuration management.

Also applies to: 18-18


86-86: LGTM: Token extraction update is consistent

The update to use pkgGrpc.TokenFromOutgoingMD maintains consistent token handling across the codebase.


116-116: LGTM: URI usage is consistent

The update to use certAuthURI.SignCertificate maintains consistent URI management. However, let's verify all certificate-related endpoints are using the centralized URIs.

#!/bin/bash
# Search for any hardcoded certificate-related URIs that should use certAuthURI
rg -g '!*.md' -g '!*.txt' "/v[0-9]+/api/certificate-authority" 

Also applies to: 128-128


70-70: Verify token validation in the service implementation

The token handling update looks good. However, since this is part of a Certificate Revocation List implementation, we should verify that the service properly validates tokens for certificate operations.

✅ Verification successful

Based on the gathered information, I can now generate the final response. The code shows that authentication and token validation are properly implemented in the certificate authority service:

Token validation is properly implemented in the service

The service has comprehensive token validation through:

  • HTTP service using validator.Config for authorization configuration
  • gRPC service using auth interceptors for token validation
  • Token validation before certificate operations through ownerToUUID function that extracts and validates owner from token

The token handling update in the test is consistent with the service's security implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for token validation in the service implementation
rg -A 5 "func.*Sign.*Certificate" | rg -B 5 "ValidateToken|Authentication"

Length of output: 64


Script:

#!/bin/bash
# Let's search for the service implementation of SignCertificate
ast-grep --pattern 'func ($service $_) SignCertificate($ctx context.Context, $req $_) ($resp $_)'

Length of output: 99


Script:

#!/bin/bash
# Let's also check for any authentication middleware or interceptors
rg -g '!*.md' "func.*(Authentication|Auth).*Interceptor" -A 5

Length of output: 6899


Script:

#!/bin/bash
# Search for token validation in the context of certificate operations
rg -g '!*.md' "ValidateToken|Authentication" certificate-authority/

Length of output: 69


Script:

#!/bin/bash
# Let's check how the service is initialized and configured with auth
rg -g '!*.md' "NewService|MakeService" certificate-authority/ -A 10

Length of output: 69


Script:

#!/bin/bash
# Let's also check the main function to see how auth is set up
rg -g '!*.md' "func main" certificate-authority/ -A 20

Length of output: 1084


Script:

#!/bin/bash
# Check for gRPC server setup in certificate authority
rg -g '!*.md' "grpc.NewServer|Listen" certificate-authority/ -B 10 -A 10

Length of output: 74


Script:

#!/bin/bash
# Let's check the run function in the certificate authority service
rg -g '!*.md' "func run" certificate-authority/ -B 5 -A 20

Length of output: 1764


Script:

#!/bin/bash
# Let's also check the service configuration structure
rg -g '!*.md' "type Config struct" certificate-authority/ -A 15

Length of output: 3358


Script:

#!/bin/bash
# Check for any auth-related imports in the service files
rg -g '!*.md' '^import \($' -A 15 certificate-authority/service/

Length of output: 35368

certificate-authority/service/config.go (1)

16-16: LGTM!

The import is correctly aliased and properly used for CRL distribution point validation.

certificate-authority/test/service.go (3)

10-10: LGTM: Import added for grpc package

The import is necessary for accessing the CRLConfig type used in the new CRL implementation.


53-59: LGTM: Good modularization of configuration

The changes improve the code organization by:

  1. Extracting HTTP configuration into a separate function
  2. Adding CRL configuration in a logical location
  3. Maintaining the validation step for the complete configuration

33-43: Verify CRL implementation completeness

Since this is part of the CRL implementation, let's verify the related components:

✅ Verification successful

CRL implementation appears complete and properly integrated

The verification shows a complete CRL implementation with all necessary components in place:

  • CRL configuration is properly validated with appropriate constraints (minimum 1-minute expiry)
  • HTTP handler is registered when CRL is enabled (/revocation-list endpoint)
  • MongoDB implementation includes proper CRL storage and handling
  • CRL distribution points are correctly configured in certificates when enabled
  • Comprehensive test coverage exists for both config validation and functionality

The conditional CRL configuration based on MongoDB in the test file is consistent with the overall implementation.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CRL implementation completeness

# Test 1: Check if CRL handler is properly registered in HTTP server
echo "Checking CRL handler registration..."
rg -p "CRLEnabled.*?{.*?}" -A 10

# Test 2: Verify MongoDB implementation for CRL
echo "Checking MongoDB CRL implementation..."
ast-grep --pattern 'func ($HANDLER *$TYPE) HandleCRL($CTX context.Context, $REQ *$REQ_TYPE)'

# Test 3: Look for CRL-related tests
echo "Checking CRL test coverage..."
fd -e go -x rg -l "TestCRL"

Length of output: 563


Script:

#!/bin/bash
# Let's try different search patterns to verify CRL implementation

# Check for CRL-related code in MongoDB implementation
echo "Checking MongoDB CRL implementation..."
rg -p "CRL" -t go ./certificate-authority -A 5

# Check for HTTP/gRPC handler registration
echo "Checking handler registration..."
rg -p "func.*CRL" -t go ./certificate-authority

# Check the test file found earlier
echo "Checking CRL test content..."
cat ./certificate-authority/service/grpc/config_test.go

# Look for CRL configuration usage
echo "Checking CRL config usage..."
rg "CRLConfig" -t go ./certificate-authority

Length of output: 15353

certificate-authority/service/grpc/signer_internal_test.go (1)

7-7: LGTM: Import and struct field additions are appropriate.

The addition of the time import and crlServer field properly supports the new CRL functionality.

Also applies to: 52-52

certificate-authority/service/service.go (2)

122-123: Verify CRL feature flag implementation.

The addition of CRLEnabled configuration is good for feature control, but please ensure:

  1. Default configuration values are documented
  2. Error handling exists for scenarios where CRL is enabled but required configuration is missing
  3. Migration guide exists for enabling CRL in production

Let's verify the CRL configuration handling:

#!/bin/bash
# Check for CRL configuration documentation
rg -g 'README*' -g '*.md' 'CRL.*configuration|Certificate Revocation List'

# Verify error handling when CRL is enabled
ast-grep --pattern 'if $_.CRLEnabled {
  $$$
}'

103-103: Verify the external address configuration for CRL distribution.

The addition of ExternalAddress parameter is likely for CRL distribution points in certificates. Ensure that:

  1. The external address is properly configured in production environments
  2. The address is accessible from certificate consumers

Let's verify the external address usage:

✅ Verification successful

External address configuration for CRL distribution is properly integrated

The verification shows that:

  1. The external address is validated through ValidateCRLDistributionPointAddress to ensure it's an absolute URL
  2. It's used as crlServerAddress in the CA server and signer for CRL distribution points
  3. The configuration is properly tested and validated in both test and production code
  4. The CRL functionality is properly guarded with configuration options (CRLConfig.Enabled)

The changes are well-integrated and maintain proper validation of the external address configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CRL distribution point URL construction
ast-grep --pattern 'config.APIs.HTTP.ExternalAddress'

# Verify if the external address is used in CRL-related code
rg -A 5 'ExternalAddress.*CRL'

Length of output: 126


Script:

#!/bin/bash
# Let's search for the usage of ExternalAddress in the codebase
rg -A 5 "ExternalAddress"

# Search for CRL-related code patterns
ast-grep --pattern 'type CertificateAuthorityServer struct {
  $$$
}'

# Search for NewCertificateAuthorityServer implementation
ast-grep --pattern 'func NewCertificateAuthorityServer($$$) ($_, $_) {
  $$$
}'

Length of output: 12304


Script:

#!/bin/bash
# Let's verify the CRL-related functionality and external address usage
rg -A 5 "crlServerAddress"

# Search for CRL distribution point validation
ast-grep --pattern 'func ValidateCRLDistributionPointAddress($_) $_'

# Search for CRL configuration validation
rg -A 5 "CRLConfig"

Length of output: 12478

certificate-authority/store/mongodb/signingRecords.go (4)

Line range hint 22-27: LGTM! Good simplification of error handling.

The simplified error handling maintains the same functionality while making the code more concise.


178-188: LGTM! Good use of generics and error handling.

The updated method signature using store.Process[store.SigningRecord] and the proper handling of mongo.ErrNilDocument demonstrate good practices.


29-39: ⚠️ Potential issue

Security Concern: Include 'owner' in the update filter

The security concern from the previous review is still valid. The current implementation allows updating records based solely on _id, which could permit unauthorized updates of records owned by other users.

Apply this diff to include the owner in the filter:

-	filter := bson.M{"_id": signingRecord.GetId()}
+	filter := bson.M{
+		"_id":           signingRecord.GetId(),
+		store.OwnerKey:  signingRecord.Owner,
+	}

156-166: 🛠️ Refactor suggestion

Improve error handling for revocation list updates

The current implementation stops at the first error when updating revocation lists. Consider aggregating errors to ensure all valid records are processed.

Apply this diff to aggregate errors:

+	var resultErr error
 	for issuerID, record := range irs {
 		query := store.UpdateRevocationListQuery{
 			IssuerID:            issuerID,
 			RevokedCertificates: record.certificates,
 		}
 		_, err := s.UpdateRevocationList(ctx, &query)
 		if err != nil {
-			return 0, err
+			resultErr = multierror.Append(resultErr, err)
 		}
 	}
+	if resultErr != nil {
+		return 0, resultErr
+	}
certificate-authority/service/grpc/signCertificate.go (4)

Line range hint 29-60: LGTM: Well-structured implementation of issuerID handling.

The changes to include issuerID in the signing record are properly implemented, with good practices for UUID generation and time handling.


136-149: LGTM: Clean implementation of signing record updates.

The function properly orchestrates the signing record update process, with good error handling and conditional revocation list updates.


166-170: LGTM: Good defensive programming with credential validation.

The added nil check for the credential and improved error handling enhance the robustness of the certificate signing process.


96-133: Consider potential race condition in revocation list creation.

When creating a new revocation list, there's a potential race condition between checking for existence and creation. While the current error handling catches duplicate IDs, consider using a more atomic operation if your store supports it.

Let's verify the revocation list handling in the codebase:

Consider implementing an atomic "upsert" operation in the store interface if supported by your database:

// Example interface addition
type Store interface {
    UpsertRevocationList(ctx context.Context, list *store.RevocationList) error
}
certificate-authority/service/grpc/signer.go (7)

27-30: LGTM: Well-structured CRL configuration.

The new crl struct field is well-organized, containing both the server address and validity duration for the CRL configuration.


49-55: LGTM: Robust issuer ID generation.

The function generates a deterministic UUID based on the certificate's public key, ensuring consistent issuer IDs across restarts.


77-83: LGTM: Proper CRL configuration validation.

Good practice to validate the CRL server address before enabling CRL functionality.


108-108: LGTM: Clean integration of CRL support.

The updates maintain the existing certificate validation logic while cleanly integrating CRL support for both root and intermediate CA scenarios.

Also applies to: 130-130


162-167: LGTM: Clean separation of signer types.

Good practice to separate identity certificate signer from standard certificate signer while reusing common configuration logic.


195-200: LGTM: Well-designed public interface.

The public signing methods provide a clean interface while properly handling both standard and identity certificate signing scenarios.


146-147: Verify certificate chain access requirements.

The GetCertificate method only returns the leaf certificate. Verify if access to the full certificate chain is needed by any consumers.

✅ Verification successful

Let me gather more context about the certificate chain usage by searching for related code patterns.


Let me search for the actual usage of the certificate chain to understand if the full chain is needed.


Based on the analysis of the code, I can now provide the final response:

GetCertificate implementation is correct as is.

The current implementation returning only the leaf certificate (s.certificate[0]) is appropriate because:

  1. The only consumer (createCRL) only needs the leaf certificate for CRL generation
  2. The full chain verification is handled during signer initialization, not by consumers
  3. The certificate chain is maintained internally by the signer for its own verification purposes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of GetCertificate to verify if full chain access is needed
rg -A 3 "GetCertificate\(\)"

Length of output: 1506


Script:

#!/bin/bash
# Search for certificate chain related patterns
rg -A 3 "certificate\[|certChain|CertChain|chain"

# Also check the struct definition and initialization
ast-grep --pattern 'type Signer struct {
  $$$
  certificate $$$
  $$$
}'

Length of output: 33691


Script:

#!/bin/bash
# Search for certificate chain usage in the CA service
rg -A 5 "s\.certificate\[|GetCertificate\(\)" certificate-authority/

# Search for certificate chain related functions
ast-grep --pattern 'func $name($_) $ret {
  $$$
  certificate[$_]
  $$$
}'

Length of output: 1783

certificate-authority/store/mongodb/revocationList_test.go (2)

1-17: LGTM! Package declaration and imports are well-organized.

The test package is correctly suffixed with _test and includes all necessary imports for testing and MongoDB operations.


1-347: Verify comprehensive security testing coverage.

The test suite covers critical security scenarios for certificate revocation, but consider adding explicit test cases for:

  1. Malformed certificate data
  2. Edge cases in certificate validity periods
  3. Revocation list size limits

Let's verify the test coverage:

✅ Verification successful

Security test coverage is adequate

The existing test coverage is comprehensive and includes:

  • Input validation for revocation list updates
  • Duplicate certificate serial number handling
  • UUID validation for issuer IDs
  • Certificate signing request validation
  • Proper error handling for invalid inputs
  • Parallel execution safety checks
  • Expiration time validation

The original review comment's suggestions for additional test cases are already covered in the implementation and tests:

  1. Malformed certificate data - covered by validation in UpdateRevocationList
  2. Edge cases in validity periods - covered in TestUpdateRevocationList
  3. Revocation list size handling - covered in parallel execution tests
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for additional security-related test cases in the codebase
rg -l "TestRevocation.*Security|TestInvalid.*Certificate" --type go

Length of output: 69


Script:

#!/bin/bash
# Let's check for all test files related to certificates and revocation
rg -l "Test.*Certificate|Test.*Revocation" --type go

# Also check the actual implementation files for validation logic
ast-grep --pattern 'func $_(ctx context.Context, $cert $_) error {
  $$$
}'

Length of output: 2208


Script:

#!/bin/bash
# Let's examine the test coverage in certificate-authority related files
rg "func Test" -A 5 certificate-authority/service/http/revocationList_test.go
rg "func Test" -A 5 certificate-authority/service/http/signCertificate_test.go

# Check validation logic in the implementation
rg "func.*UpdateRevocationList|func.*GetRevocationList" -A 5 certificate-authority/store/mongodb/revocationList.go

Length of output: 2039

certificate-authority/store/mongodb/signingRecords_test.go (3)

101-101: LGTM! Good improvement to error handling.

The early return after error check follows the fail-fast principle and improves code clarity.


44-45: Consider diversifying test data for new fields.

The new Serial and IssuerId fields use the same values across all test cases. To improve test coverage, consider:

  • Testing different serial number formats and lengths
  • Testing invalid UUID formats for IssuerId
  • Adding specific test cases for these new fields

Let's verify if there are any validation requirements for these fields:

Also applies to: 64-65, 83-84, 217-218, 283-284, 326-327, 341-342, 356-357, 371-372


302-304: Verify impact of handler interface change.

The replacement of Handle(ctx context.Context, iter store.SigningRecordIter) with process(sr *store.SigningRecord):

  1. Removes context propagation which might be needed for cancellation
  2. Changes the method name to be less descriptive
  3. Represents a breaking change that might affect other code

Let's check for other implementations of this interface:

certificate-authority/store/cqldb/signingRecords_test.go (3)

5-5: LGTM: Required import for certificate serial numbers

The addition of math/big is appropriate for handling certificate serial numbers which require arbitrary-precision arithmetic.


369-369: LGTM: Proper usage of LoadSigningRecords

The test correctly uses nil query to load all records and properly implements the handler pattern.

Also applies to: 377-377


386-388: Verify all callers of the renamed handler function

The handler function has been renamed from Handle to process. While the new name is more descriptive, we should verify that all callers have been updated.

certificate-authority/pb/doc.html (3)

349-349: LGTM: Method descriptions are clear and consistent.

The updated descriptions for GetSigningRecords and DeleteSigningRecords methods accurately reflect their functionality. The changes align with the PR objective of implementing Certificate Revocation List.

Also applies to: 356-356


494-511: LGTM: Well-documented certificate tracking enhancements.

The addition of serial and issuer_id fields to CredentialStatus improves certificate tracking capabilities:

  • serial field enables proper certificate revocation tracking
  • issuer_id supports multi-CA scenarios with its UUID-based identification
  • Both fields are well-documented with clear bson tags

551-551: LGTM: Description accurately reflects enhanced functionality.

The updated description for DeletedSigningRecords clearly indicates its dual purpose of revoking or deleting certificates, which aligns with the Certificate Revocation List implementation objective.

certificate-authority/store/mongodb/revocationList.go (4)

16-16: Previous feedback still applies here.


71-71: Previous feedback still applies here.


134-134: Previous feedback still applies here.


169-169: Previous feedback still applies here.

pkg/security/x509/crl.go Show resolved Hide resolved
certificate-authority/pb/signingRecords.go Show resolved Hide resolved
certificate-authority/service/grpc/config.go Show resolved Hide resolved
certificate-authority/service/grpc/config.go Show resolved Hide resolved
certificate-authority/store/store.go Show resolved Hide resolved
certificate-authority/pb/doc.html Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (16)
certificate-authority/service/http/service.go (1)

27-27: Add documentation for the store parameter.

Consider adding a doc comment explaining the role of the store.Store parameter and its relationship to CRL functionality.

+// New creates a new HTTP service for the certificate authority.
+// The store parameter is required for managing certificate revocation lists when CRLEnabled is true.
 func New(serviceName string, config Config, s store.Store, ca *grpcService.CertificateAuthorityServer, validator *validator.Validator, fileWatcher *fsnotify.Watcher, logger log.Logger, tracerProvider trace.TracerProvider) (*Service, error) {
certificate-authority/service/grpc/deleteSigningRecords_test.go (1)

100-100: Consider making the URL scheme configurable.

While using https:// is secure, consider making the URL scheme configurable for development/testing scenarios.

-ca, err := grpc.NewCertificateAuthorityServer(ownerClaim, config.HubID(), "https://"+config.CERTIFICATE_AUTHORITY_HTTP_HOST, test.MakeConfig(t).Signer, store, fileWatcher, logger)
+ca, err := grpc.NewCertificateAuthorityServer(ownerClaim, config.HubID(), config.CERTIFICATE_AUTHORITY_URL_SCHEME+"://"+config.CERTIFICATE_AUTHORITY_HTTP_HOST, test.MakeConfig(t).Signer, store, fileWatcher, logger)
certificate-authority/service/grpc/getSigningRecords_test.go (1)

43-44: Consider adding test cases for edge cases.

While the test data is correctly structured, consider adding test cases for:

  1. Invalid serial number formats
  2. Invalid UUID formats for IssuerId
  3. Empty/null values for both fields

This would help ensure robust validation in the implementation.

pkg/security/certificateSigner/certificateSigner.go (2)

19-22: LGTM! Consider documenting the field.

The new CRLDistributionPoints field is appropriately added to the SignerConfig struct. Consider adding a documentation comment to describe the expected format of the URLs and any validation requirements.

 type SignerConfig struct {
 	ValidNotBefore        time.Time
 	ValidNotAfter         time.Time
+	// CRLDistributionPoints contains a list of URLs where the Certificate Revocation List can be obtained.
+	// Each URL should be an HTTP/HTTPS endpoint serving the CRL in DER format.
 	CRLDistributionPoints []string
 	OverrideCertTemplate  func(template *x509.Certificate) error
 }

Line range hint 67-83: Enhance error messages for better debugging.

While the error handling is correct, consider making the error messages more specific to help with troubleshooting.

 func parseCertificateRequest(csr []byte) (*x509.CertificateRequest, error) {
 	csrBlock, _ := pem.Decode(csr)
 	if csrBlock == nil {
-		return nil, errors.New("pem not found")
+		return nil, errors.New("failed to decode PEM block from CSR")
 	}
certificate-authority/service/service.go (1)

122-123: LGTM! Good architectural decision.

The changes demonstrate good separation of concerns:

  1. CRL functionality is properly feature-flagged
  2. Direct database access for the HTTP service improves modularity by removing unnecessary coupling through the CA service

This design will make it easier to maintain and extend CRL functionality independently.

Consider documenting the rationale for this architectural decision in the service's design documentation to help future maintainers understand the separation of concerns between the HTTP service and CA service regarding CRL management.

certificate-authority/service/grpc/signer_internal_test.go (1)

68-69: Document the purpose of the validated field.

The validated field has been added to multiple test cases, but its purpose and significance aren't documented. Consider adding a comment explaining when and why this field should be set to true.

Also applies to: 79-80, 90-90, 102-102, 114-114

certificate-authority/service/config_test.go (1)

150-150: Add documentation about security implications.

Consider adding a comment block explaining the security implications of CRL distribution point validation, particularly why certain patterns are rejected.

Add this documentation:

+// TestHTTPConfigValidate verifies the validation logic for HTTP configuration,
+// particularly focusing on CRL distribution point security:
+// - Rejects relative paths to prevent path traversal
+// - Ensures absolute URLs to prevent DNS rebinding
+// - Validates HTTPS usage for secure CRL distribution
 func TestHTTPConfigValidate(t *testing.T) {
certificate-authority/service/grpc/signer.go (1)

189-191: Consider providing more context in error messages.

When signing fails, consider wrapping the error with additional context about the signing operation (identity vs. standard) to aid in debugging.

 if err != nil {
-    return nil, nil, err
+    return nil, nil, fmt.Errorf("failed to sign %s certificate: %w", 
+        map[bool]string{true: "identity", false: "standard"}[isIdentityCertificate], 
+        err)
 }
certificate-authority/service/grpc/signCertificate_test.go (2)

94-106: LGTM! Well-structured helper functions with good separation of concerns.

The refactoring improves test flexibility by separating key generation from CSR creation. Consider adding a small enhancement for test reliability.

Consider adding key size validation in createCSRWithKey:

 func createCSRWithKey(t *testing.T, commonName string, priv *ecdsa.PrivateKey) []byte {
+    require.Equal(t, priv.Curve, elliptic.P256(), "unexpected curve type")
     var cfg generateCertificate.Configuration
     cfg.Subject.CommonName = commonName
     csr, err := generateCertificate.GenerateCSR(cfg, priv)
     require.NoError(t, err)
     return csr
 }

153-197: LGTM! Critical security test case for device identity management.

The test effectively verifies that:

  1. The same device ID + same key combination is allowed (legitimate reuse)
  2. The same device ID + different key combination is rejected (prevents spoofing)

Consider adding a doc comment to explain the security implications:

+// TestCertificateAuthorityServerSignCSRWithSameDevice verifies the security constraint
+// that prevents device ID spoofing by ensuring that:
+// 1. A device can reuse its existing key (legitimate case)
+// 2. A device cannot register with a different key (potential spoofing attempt)
 func TestCertificateAuthorityServerSignCSRWithSameDevice(t *testing.T) {
certificate-authority/store/mongodb/revocationList.go (1)

193-197: Consider adding indexes for performance optimization

The query filters on validUntil field within the certificates array. Consider adding an index to optimize these queries, especially for large revocation lists.

Add an index on the certificates.validUntil field:

// Index definition to be added to your MongoDB initialization
{
    "certificates.validUntil": 1
}
certificate-authority/store/cqldb/signingRecords.go (1)

342-367: LGTM with a minor suggestion about error variable naming.

The implementation is solid with proper error handling, resource cleanup, and deduplication. However, consider renaming errClose to closeErr to better align with Go naming conventions for error variables.

-errClose := i.close()
+closeErr := i.close()
 if err == nil {
-    return errClose
+    return closeErr
 }
certificate-authority/store/mongodb/signingRecords_test.go (2)

44-45: Consider diversifying test data for new credential fields.

The new Serial and IssuerId fields are consistently populated with the same hardcoded values across all test cases. To ensure robust testing, consider:

  • Using different serial numbers to test various number ranges
  • Testing different UUID formats for IssuerId
  • Adding test cases for empty/invalid values

Example improvement:

func generateTestCredential(serial int64, issuerID string) *pb.CredentialStatus {
    return &pb.CredentialStatus{
        CertificatePem: "certificate",
        Date:           constDate().UnixNano(),
        ValidUntilDate: constDate().UnixNano(),
        Serial:         big.NewInt(serial).String(),
        IssuerId:       issuerID,
    }
}

Also applies to: 64-65, 83-84, 217-218, 283-284, 326-327, 341-342, 356-357, 371-372


302-304: Consider adding validation in the process method.

While the simplified handler implementation is clean, consider adding validation to ensure robust error handling:

 func (h *testSigningRecordHandler) process(sr *store.SigningRecord) (err error) {
+    if sr == nil {
+        return fmt.Errorf("signing record cannot be nil")
+    }
     h.lcs = append(h.lcs, sr)
     return nil
 }
certificate-authority/service/grpc/config.go (1)

Line range hint 43-71: Potential data race due to unprotected 'validated' field

The validated boolean field in SignerConfig is not protected against concurrent access. If Validate() is called concurrently by multiple goroutines, this could lead to a data race condition.

Consider using sync.Once to ensure thread-safe validation. Here's an example of how you could modify the code:

+import "sync"

 type SignerConfig struct {
     CAPool    interface{}         `yaml:"caPool" json:"caPool" description:"file path to the root certificates in PEM format"`
     KeyFile   urischeme.URIScheme `yaml:"keyFile" json:"keyFile" description:"file name of CA private key in PEM format"`
     CertFile  urischeme.URIScheme `yaml:"certFile" json:"certFile" description:"file name of CA certificate in PEM format"`
     ValidFrom string              `yaml:"validFrom" json:"validFrom" description:"format https://github.com/karrick/tparse"`
     ExpiresIn time.Duration       `yaml:"expiresIn" json:"expiresIn"`
     CRL       CRLConfig           `yaml:"crl" json:"crl"`

-    validated   bool                  `yaml:"-" json:"-"`
+    validateOnce sync.Once            `yaml:"-" json:"-"`
+    validateErr  error                `yaml:"-" json:"-"`
 }

 func (c *SignerConfig) Validate() error {
-    if c.validated {
-        return nil
-    }
+    c.validateOnce.Do(func() {
         caPoolArray, ok := strings.ToStringArray(c.CAPool)
         if !ok {
-            return fmt.Errorf("caPool('%v')", c.CAPool)
+            c.validateErr = fmt.Errorf("caPool('%v')", c.CAPool)
+            return
         }
         c.caPoolArray = urischeme.ToURISchemeArray(caPoolArray)
         if c.CertFile == "" {
-            return fmt.Errorf("certFile('%v')", c.CertFile)
+            c.validateErr = fmt.Errorf("certFile('%v')", c.CertFile)
+            return
         }
         if c.KeyFile == "" {
-            return fmt.Errorf("keyFile('%v')", c.KeyFile)
+            c.validateErr = fmt.Errorf("keyFile('%v')", c.KeyFile)
+            return
         }
         if c.ExpiresIn <= 0 {
-            return fmt.Errorf("expiresIn('%v')", c.ExpiresIn)
+            c.validateErr = fmt.Errorf("expiresIn('%v')", c.ExpiresIn)
+            return
         }
         _, err := tparse.ParseNow(time.RFC3339, c.ValidFrom)
         if err != nil {
-            return fmt.Errorf("validFrom('%v').%w", c.ValidFrom, err)
+            c.validateErr = fmt.Errorf("validFrom('%v').%w", c.ValidFrom, err)
+            return
         }
         if err := c.CRL.Validate(); err != nil {
-            return fmt.Errorf("crl.%w", err)
+            c.validateErr = fmt.Errorf("crl.%w", err)
+            return
         }
+    })
-    c.validated = true
-    return nil
+    return c.validateErr
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0b23411 and fb8c9e6.

⛔ Files ignored due to path filters (10)
  • certificate-authority/config.yaml is excluded by !**/*.yaml
  • certificate-authority/pb/service.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • certificate-authority/pb/service.swagger.json is excluded by !**/*.json
  • certificate-authority/pb/service_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/signingRecords.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • charts/plgd-hub/templates/certificate-authority/config.yaml is excluded by !**/*.yaml
  • charts/plgd-hub/values.yaml is excluded by !**/*.yaml
  • device-provisioning-service/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • device-provisioning-service/pb/service.swagger.json is excluded by !**/*.json
📒 Files selected for processing (56)
  • bundle/nginx/nginx.conf.template (1 hunks)
  • certificate-authority/pb/README.md (3 hunks)
  • certificate-authority/pb/doc.html (7 hunks)
  • certificate-authority/pb/service.proto (2 hunks)
  • certificate-authority/pb/signingRecords.go (3 hunks)
  • certificate-authority/pb/signingRecords.proto (2 hunks)
  • certificate-authority/pb/signingRecords_test.go (1 hunks)
  • certificate-authority/service/cleanDatabase_test.go (5 hunks)
  • certificate-authority/service/config.go (3 hunks)
  • certificate-authority/service/config_test.go (1 hunks)
  • certificate-authority/service/grpc/config.go (2 hunks)
  • certificate-authority/service/grpc/config_test.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords_test.go (4 hunks)
  • certificate-authority/service/grpc/getSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/getSigningRecords_test.go (5 hunks)
  • certificate-authority/service/grpc/server.go (2 hunks)
  • certificate-authority/service/grpc/server_test.go (1 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signCertificate_test.go (4 hunks)
  • certificate-authority/service/grpc/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/grpc/signer_internal_test.go (7 hunks)
  • certificate-authority/service/http/config.go (1 hunks)
  • certificate-authority/service/http/requestHandler.go (1 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/service/http/service.go (2 hunks)
  • certificate-authority/service/http/signCertificate_test.go (6 hunks)
  • certificate-authority/service/http/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/service.go (2 hunks)
  • certificate-authority/service/uri/uri.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords_test.go (18 hunks)
  • certificate-authority/store/mongodb/bulkWriter.go (0 hunks)
  • certificate-authority/store/mongodb/config.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList_test.go (1 hunks)
  • certificate-authority/store/mongodb/signingRecords.go (3 hunks)
  • certificate-authority/store/mongodb/signingRecords_test.go (13 hunks)
  • certificate-authority/store/mongodb/store.go (3 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList_test.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • certificate-authority/test/revocationList.go (1 hunks)
  • certificate-authority/test/service.go (2 hunks)
  • charts/plgd-hub/README.md (0 hunks)
  • device-provisioning-service/Makefile (1 hunks)
  • device-provisioning-service/pb/service.proto (4 hunks)
  • http-gateway/test/http.go (1 hunks)
  • http-gateway/uri/uri.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (0 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (0 hunks)
  • pkg/security/x509/crl.go (1 hunks)
💤 Files with no reviewable changes (4)
  • certificate-authority/store/mongodb/bulkWriter.go
  • charts/plgd-hub/README.md
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🚧 Files skipped from review as they are similar to previous changes (33)
  • bundle/nginx/nginx.conf.template
  • certificate-authority/pb/README.md
  • certificate-authority/pb/doc.html
  • certificate-authority/pb/service.proto
  • certificate-authority/pb/signingRecords.go
  • certificate-authority/pb/signingRecords.proto
  • certificate-authority/pb/signingRecords_test.go
  • certificate-authority/service/cleanDatabase_test.go
  • certificate-authority/service/grpc/config_test.go
  • certificate-authority/service/grpc/deleteSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords.go
  • certificate-authority/service/grpc/server.go
  • certificate-authority/service/grpc/server_test.go
  • certificate-authority/service/grpc/signIdentityCertificate_test.go
  • certificate-authority/service/http/config.go
  • certificate-authority/service/http/requestHandler.go
  • certificate-authority/service/http/revocationList_test.go
  • certificate-authority/service/http/signCertificate_test.go
  • certificate-authority/service/http/signIdentityCertificate_test.go
  • certificate-authority/service/uri/uri.go
  • certificate-authority/store/cqldb/revocationList.go
  • certificate-authority/store/mongodb/config.go
  • certificate-authority/store/mongodb/revocationList_test.go
  • certificate-authority/store/revocationList.go
  • certificate-authority/store/revocationList_test.go
  • certificate-authority/store/store.go
  • certificate-authority/test/revocationList.go
  • certificate-authority/test/service.go
  • device-provisioning-service/Makefile
  • device-provisioning-service/pb/service.proto
  • http-gateway/test/http.go
  • http-gateway/uri/uri.go
  • pkg/security/x509/crl.go
🧰 Additional context used
📓 Learnings (2)
certificate-authority/store/mongodb/revocationList.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
certificate-authority/store/mongodb/signingRecords.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
🪛 GitHub Check: CodeQL
certificate-authority/store/mongodb/revocationList.go

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.

🔇 Additional comments (60)
certificate-authority/service/http/service.go (4)

5-14: LGTM: Import changes are well-organized and necessary.

The new imports support the CRL functionality and follow Go's import organization best practices.


23-23: LGTM: Appropriate encapsulation of requestHandler.

The change from exported to unexported type improves encapsulation by making the request handler an internal implementation detail.


Line range hint 52-56: LGTM: Proper error handling in requestHandler initialization.

The code properly handles initialization errors by closing the service before returning the error, preventing resource leaks.


27-34: Verify the security implications of the CRL endpoint pattern.

While the use of regexp.QuoteMeta is good for security, we should verify that the pattern SigningRevocationListBase + '/.*' doesn't allow access to unintended paths.

✅ Verification successful

Let me analyze the results and generate one more verification script to ensure we have all the necessary information.

The additional check will help us understand the API path structure and verify if there are any other handlers that might affect the security of the CRL endpoint pattern.


CRL endpoint pattern is secure and well-structured

The pattern is secure because:

  • The base path /api/v1/signing/crl is properly structured and namespaced
  • regexp.QuoteMeta escapes all regex metacharacters in the base path
  • The \/.* suffix pattern is consistent with other authenticated endpoints in the codebase
  • The CRL endpoint is only accessible via GET method
  • Similar pattern usage across the codebase shows this is a standard approach
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check the SigningRevocationListBase constant and its usage
rg -A 2 "SigningRevocationListBase.*=.*" 
# Check for any other similar endpoint patterns
rg -A 2 "regexp\.QuoteMeta.*\+ `/.*`"

Length of output: 1494


Script:

#!/bin/bash
# Check the API constant value and structure
rg "API.*=.*" certificate-authority/service/uri/uri.go

# Check if there are any other routes or handlers using SigningRevocationListBase
ast-grep --pattern 'func $FUNC($$$) {
  $$$
  SigningRevocationListBase
  $$$
}'

Length of output: 171

certificate-authority/store/mongodb/store.go (4)

37-51: Well-designed iterator implementation!

The generic MongoIterator[T] is a clean abstraction over mongo.Cursor that:

  • Provides type safety through generics
  • Follows the iterator pattern
  • Handles errors appropriately

53-75: Previous review comment about error handling is still applicable.

The current implementation stops processing on the first error, which limits the function's utility in handling partial failures.


99-104: Clean implementation of database cleanup!

The error handling using multierror is appropriate, and the implementation properly cleans up both collections.


19-21: Verify the performance impact of removing bulk operations.

The replacement of bulkWriter with logger suggests a shift from batch operations to individual operations. While this simplifies the code, it might impact performance for high-throughput scenarios.

certificate-authority/service/grpc/deleteSigningRecords_test.go (6)

5-5: LGTM: Import additions are appropriate.

The new imports support the serial number handling (math/big) and token context management (pkgGrpc).

Also applies to: 17-17


25-28: LGTM: Well-structured test setup.

Good practice to isolate token creation and context setup. This allows for better testing of authentication scenarios.


53-62: LGTM: Good security validation test case.

The new test case properly validates the authentication requirement by ensuring operations fail when the context lacks a valid token.


69-69: LGTM: Improved test case clarity with explicit contexts.

The addition of explicit context parameters makes the authentication requirements clearer in each test case.

Also applies to: 78-78


109-113: LGTM: Clean error handling pattern.

The error handling follows good practices with clear separation of error and success cases.


39-40: LGTM: Essential fields added for certificate tracking.

The addition of Serial and IssuerId fields enhances the credential tracking capabilities needed for the Certificate Revocation List implementation.

Let's verify the consistency of these new fields across the codebase:

✅ Verification successful

LGTM: Fields are consistently implemented across the codebase

The verification confirms that Serial and IssuerId fields are properly implemented in the Certificate Authority's data structures:

  • Found in certificate-authority/pb/signingRecords.pb.go as part of the CredentialStatus struct with correct types and BSON tags
  • Used consistently in test files across the certificate authority service
  • Properly integrated with the revocation list functionality in certificate-authority/store/revocationList.go
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the Serial and IssuerId fields are consistently implemented
# Look for the credential structure definition and usage
ast-grep --pattern 'type Credential struct {
  $$$
  Serial $$$
  IssuerId $$$
  $$$
}'

Length of output: 89


Script:

#!/bin/bash
# Let's try a broader search for credential structures and their fields
rg -i "credential.*struct" -A 10

# Also search for specific field usage patterns
rg "Serial.*string" -A 2
rg "IssuerId.*string" -A 2

# Search for test files that might use these fields
fd ".*test.go$" --exec rg -l "Serial|IssuerId"

Length of output: 17158

certificate-authority/service/grpc/getSigningRecords_test.go (3)

7-7: LGTM: Import changes are appropriate.

The addition of math/big is necessary for handling certificate serial numbers, and the package alias update maintains consistency with the new package structure.

Also applies to: 20-20


101-101: LGTM: Package update is consistent.

The context creation update correctly uses the new package alias while maintaining the same functionality.


92-92: Verify HTTP host configuration consistency.

The server initialization now includes the HTTP host parameter. Let's ensure this configuration is consistent across the codebase.

✅ Verification successful

Based on the results, I can generate the final response as we have sufficient information about the HTTP host configuration usage across the codebase.

HTTP host configuration is consistently used across the codebase

The verification shows that CERTIFICATE_AUTHORITY_HTTP_HOST is consistently used:

  • All server initializations properly prefix the host with "https://"
  • The configuration is defined in test/config/config.go as "localhost:20012"
  • The host is consistently used in both HTTP and gRPC test setups
  • External address configuration in service setup also follows the same pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent HTTP host configuration across tests and implementation

echo "Checking HTTP host configuration in test files..."
rg "CERTIFICATE_AUTHORITY_HTTP_HOST" -A 2

echo "Checking NewCertificateAuthorityServer usage..."
ast-grep --pattern 'NewCertificateAuthorityServer($$$, "https://" + $_, $$$)'

Length of output: 3650

pkg/security/certificateSigner/certificateSigner.go (4)

39-43: LGTM! Secure implementation with defensive copying.

The function correctly implements defensive copying using slices.Clone, preventing external modifications from affecting internal state.


85-92: LGTM! Good validation and error handling.

The changes properly validate CA certificate presence and handle CSR parsing errors.


Line range hint 129-134: LGTM! Secure certificate creation and chain building.

The implementation correctly uses a secure random number generator and properly builds the certificate chain.


110-122: ⚠️ Potential issue

Add security constraints to the certificate template.

While the CRL distribution points are correctly added, the certificate template should include key usage constraints as suggested in the previous review. This is important for security best practices.

Additionally, consider adding these security-related fields:

 template := x509.Certificate{
     // ... existing fields ...
+    BasicConstraints: x509.BasicConstraints{
+        IsCA:                  false,
+        MaxPathLen:           -1,
+    },
     CRLDistributionPoints: s.cfg.CRLDistributionPoints,
 }
certificate-authority/service/config.go (3)

16-16: LGTM!

The import is properly aliased and necessary for the CRL validation functionality.


69-71: LGTM!

The HTTPConfig struct changes are well-organized:

  • ExternalAddress field is properly tagged
  • Field ordering follows Go conventions

75-78: Verify CRL distribution point address validation implementation.

The validation is delegated to ValidateCRLDistributionPointAddress, but we should verify if it implements all necessary security checks as suggested in previous reviews.

#!/bin/bash
# Description: Verify the implementation of ValidateCRLDistributionPointAddress

# Test: Search for the validation function implementation
ast-grep --pattern 'func ValidateCRLDistributionPointAddress(address string) error {
  $$$
}'

# Test: Check for specific validation checks
rg -A 10 'func ValidateCRLDistributionPointAddress'

# Test: Look for test cases to understand validation coverage
rg -A 10 'TestValidateCRLDistributionPointAddress'
certificate-authority/service/service.go (1)

103-103: Verify external address validation.

The external address is now passed to the gRPC service. Ensure that this address is properly validated in the configuration loading to prevent invalid URLs in CRL distribution points.

✅ Verification successful

External address validation is properly implemented

The external address is validated through ValidateCRLDistributionPointAddress which ensures:

  • The address is a valid URL (via url.ParseRequestURI)
  • The URL is absolute (via IsAbs() check)
  • The validation is enforced in both config loading and gRPC service initialization
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for validation of ExternalAddress in config files
rg -A 5 "ExternalAddress.*validate|validate.*ExternalAddress" 

Length of output: 63


Script:

#!/bin/bash
# Let's search for the configuration struct and validation logic
rg -A 10 "type.*Config.*struct" certificate-authority/

# Also search for URL validation patterns
rg -A 5 "url\.|ValidateURL|ParseURL|IsValidURL" certificate-authority/

Length of output: 8375


Script:

#!/bin/bash
# Let's check the validation function for CRL distribution point address
rg -A 5 "ValidateCRLDistributionPointAddress" 

# Also check the implementation in the x509 package
fd -e go . | xargs rg -l "func.*ValidateCRLDistributionPointAddress"

Length of output: 1475


Script:

#!/bin/bash
# Let's check the complete validation in the x509 package
rg -A 10 "func ValidateCRLDistributionPointAddress" pkg/security/x509/crl.go

Length of output: 330

certificate-authority/service/grpc/signer_internal_test.go (4)

7-7: LGTM: Time import is required for CRL configuration.

The addition of the time import is appropriate for handling the new CRL expiration configurations in the test cases.


52-52: LGTM: CRL server parameter addition.

The crlServer field is a good addition to the args struct, enabling proper testing of CRL server configurations.


122-155: LGTM: Comprehensive CRL server test cases added.

The new test cases effectively cover:

  1. Valid CRL server configuration with proper URL
  2. Invalid CRL server with malformed URL
  3. CRL-specific fields like Enabled and ExpiresIn

This addresses the previous review comment requesting CRL server validation tests.


160-160: 🛠️ Refactor suggestion

Consider parameterizing ownerClaim and hubID.

As suggested in the previous review, consider making ownerClaim and hubID configurable through test parameters for better test flexibility.

Apply this change:

-got, err := NewSigner("ownerClaim", "hubID", tt.args.crlServer, tt.args.signerConfig)
+got, err := NewSigner(tt.args.ownerClaim, tt.args.hubID, tt.args.crlServer, tt.args.signerConfig)

And update the args struct:

 type args struct {
+    ownerClaim    string
+    hubID         string
     signerConfig  SignerConfig
     crlServer     string
 }
certificate-authority/service/config_test.go (1)

162-163: Verify test helper implementation.

The test relies on test.MakeHTTPConfig() for the valid case. Let's verify its implementation to ensure it creates a secure configuration.

✅ Verification successful

Let me gather more information about the HTTP server configuration since the initial results show that MakeHTTPConfig uses config.MakeHttpServerConfig().


Let me try searching with a different path pattern since the previous search didn't find the config package.


From the search results, I found the implementation of MakeHTTPConfig() in certificate-authority/test/service.go. Let me verify its specific implementation.


Let me check the implementation of MakeHttpServerConfig() since it's used in the MakeHTTPConfig() implementation.


Test helper implementation verified and secure.

The test.MakeHTTPConfig() creates a secure configuration with appropriate timeouts:

  • Uses MakeHttpServerConfig() which sets reasonable timeout values:
    • ReadTimeout: 8 seconds
    • ReadHeaderTimeout: 4 seconds
    • WriteTimeout: 16 seconds
    • IdleTimeout: 30 seconds
  • Sets proper external HTTPS address
  • Uses server configuration from the standard HTTP server package
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the implementation of test.MakeHTTPConfig()
# to ensure it creates a secure configuration with proper CRL settings

# Look for the test helper implementation
rg -A 10 "func MakeHTTPConfig" "certificate-authority/test"

# Check for any CRL-related constants or configurations
rg "CRL" "certificate-authority/test"

Length of output: 1158


Script:

#!/bin/bash
# Check the implementation of MakeHttpServerConfig and related security settings
rg -A 10 "func MakeHttpServerConfig" "certificate-authority/config"

# Look for any TLS or security-related configurations
rg "TLS|ReadTimeout|WriteTimeout|IdleTimeout" "certificate-authority/config"

Length of output: 282


Script:

#!/bin/bash
# Find config-related files first
fd config

# Then check the implementation of HTTP server config and security settings
rg -A 10 "func MakeHttpServerConfig"

# Look for any TLS or security-related configurations
rg "TLS|ReadTimeout|WriteTimeout|IdleTimeout"

Length of output: 83371


Script:

#!/bin/bash
# Get the full implementation of MakeHTTPConfig and related configurations
ast-grep --pattern 'func MakeHTTPConfig() service.HTTPConfig {
  $$$
}'

# Also check for any HTTP server config defaults
rg -A 5 "type HTTPConfig struct" "certificate-authority/service"

Length of output: 2460


Script:

#!/bin/bash
# Look for MakeHttpServerConfig implementation in test/config directory
rg -A 10 "func MakeHttpServerConfig" "test/config"

# Also check the httpServer.Config structure
rg -A 5 "type Config struct" "pkg/net/http/server"

Length of output: 1094

certificate-authority/store/mongodb/signingRecords.go (5)

9-14: LGTM: Import additions and error handling simplification

The new imports support the added functionality, and the simplified error handling in CreateSigningRecord is appropriate since MongoDB's error messages are sufficiently descriptive.

Also applies to: 26-26


29-39: Security: Include owner in update filter

The previous security concern remains valid. The update filter should include the owner field to prevent unauthorized updates of records owned by other users.


121-151: LGTM: Well-structured revocation logic

The implementation correctly:

  • Separates the handling of expired and valid records
  • Uses efficient data structures for tracking records by issuer
  • Properly collects necessary certificate information for revocation

156-165: Consider aggregating errors during revocation list updates

The current implementation stops on the first error, potentially leaving some revocation lists unprocessed. Consider aggregating errors to ensure all lists are processed.


178-188: LGTM: Improved type safety and error handling

The changes improve the function by:

  • Using a type-safe Process interface
  • Adding proper handling for nil documents
  • Maintaining clean error propagation
certificate-authority/service/grpc/signCertificate.go (3)

Line range hint 29-60: LGTM: Clean implementation of issuerID addition.

The function correctly integrates the new issuerID parameter and follows good practices for UUID generation and timestamp handling.


136-149: LGTM: Clean implementation with proper error handling.

The function effectively coordinates the signing record update process with revocation list management.


166-169: LGTM: Improved robustness with credential validation.

The added null check for credential prevents potential issues and provides clear error messages.

certificate-authority/service/grpc/signer.go (6)

27-30: LGTM: Well-structured CRL configuration.

The CRL configuration is properly encapsulated in a nested struct with clear fields for server address and validity duration.


49-55: LGTM: Robust issuer ID generation.

The implementation correctly generates a deterministic UUID based on the public key, with proper error handling and appropriate namespace selection.


108-108: LGTM: Clean refactoring of signer initialization.

The changes properly integrate the new CRL configuration while maintaining existing certificate chain validation logic.

Also applies to: 130-130


146-147: LGTM: Well-designed getter methods.

The getters for certificate and CRL configuration provide clean access to necessary information while maintaining encapsulation.

Also applies to: 154-160


162-167: LGTM: Clean factory method implementation.

The function provides a clean interface for creating appropriate certificate signers while promoting code reuse.


195-200: LGTM: Clean public API for signing operations.

The methods provide a clear interface for different types of signing operations while sharing common implementation details.

certificate-authority/service/grpc/signCertificate_test.go (2)

13-19: LGTM! Import changes maintain package consistency.

The update from kitNetGrpc to pkgGrpc aligns with the codebase's package standardization.


73-73: LGTM! Context setup properly handles authorization.

The update to use pkgGrpc.CtxWithToken maintains consistent authorization handling across the codebase.

Also applies to: 138-138

certificate-authority/store/mongodb/revocationList.go (3)

25-27: LGTM! Well-structured error handling

The error handling is comprehensive with proper wrapping of MongoDB-specific errors and clear error messages.

Also applies to: 112-114


128-143: Consider handling expired signing records

Based on the learnings from signingRecords.go, expired signing records are deleted but not added to the revocation list. Consider whether these expired records should be included in the revocation list for audit purposes.

Let's verify the current handling of expired records:

#!/bin/bash
# Search for expired record handling in the codebase
rg -A 10 'expired.*signing.*record'

71-71: Ensure proper validation of map keys before using in MongoDB query

While the code validates individual certificates, it's important to ensure that the serial numbers used as map keys are properly sanitized before being used in MongoDB queries to prevent potential injection attacks.

Let's verify the format of serial numbers in the codebase:

certificate-authority/store/cqldb/signingRecords.go (1)

368-374: ⚠️ Potential issue

Critical Security Issue: Certificate deletion instead of revocation.

I strongly agree with the previous review comment about implementing proper certificate revocation. Deleting certificates instead of marking them as revoked is a significant security risk and compliance issue:

  1. Violates RFC 5280 requirements for certificate revocation
  2. Prevents proper certificate status checking
  3. Eliminates audit trail for revoked certificates
  4. Could allow reuse of revoked certificate serial numbers

This should be prioritized as a critical security enhancement. The previous review provided a detailed implementation guide that aligns with industry standards.

Let's verify if any other components rely on certificate status checks:

#!/bin/bash
# Search for certificate status validation patterns
rg -g '!{*.sum,*.mod}' -i '(check|validate|verify).*certificate.*(status|revocation|revoked)'
certificate-authority/store/mongodb/signingRecords_test.go (2)

101-103: LGTM! Improved error handling.

The simplified error handling with early return improves code clarity and follows good practices.


Line range hint 477-485: LGTM! Comprehensive test coverage.

The test implementation properly validates the LoadSigningRecords functionality across various scenarios with appropriate error handling and assertions.

certificate-authority/store/cqldb/signingRecords_test.go (4)

386-388: LGTM: Handler function rename improves clarity

The rename from Handle to process better describes the function's purpose while maintaining the same implementation.


Line range hint 408-439: LGTM: Comprehensive test coverage for credential fields

The test cases thoroughly validate the new Serial and IssuerId fields across different scenarios, including:

  • Different Serial values (42, 43, 44)
  • Consistent IssuerId validation
  • Various filtering conditions

35-36: 🛠️ Refactor suggestion

Improve test data organization for new credential fields

The Serial and IssuerId fields are added across all test cases, but the implementation could be improved:

  1. The Serial values (42, 43, 44) follow a pattern but are scattered across the test file
  2. The IssuerId is duplicated across all test cases

Previous review comment about creating test helpers for Serial and IssuerId generation is still valid. Additionally, consider:

const (
    testIssuerID = "42424242-4242-4242-4242-424242424242"
)

func generateTestSerial(idx int) string {
    return big.NewInt(int64(42 + idx)).String()
}

Also applies to: 55-56, 110-111, 130-131, 150-151, 169-170, 294-295, 310-311, 326-327, 363-364, 408-409, 423-424, 438-439, 574-575


542-542: ⚠️ Potential issue

Fix hardcoded owner in LoadSigningRecords test

The hardcoded "owner" value prevents proper testing of owner-based filtering.

Apply the fix as suggested in the previous review:

-err := s.LoadSigningRecords(ctx, "owner", tt.args.query, h.process)
+err := s.LoadSigningRecords(ctx, tt.args.owner, tt.args.query, h.process)
certificate-authority/service/grpc/config.go (1)

Line range hint 47-71:

certificate-authority/service/http/revocationList.go (3)

23-25: 🛠️ Refactor suggestion

Consider using more specific error codes for better error handling

Currently, the errCannotGetRevocationList function maps all errors to codes.Internal. It's advisable to return more specific gRPC error codes based on the underlying error to provide clearer feedback to clients. For example:

  • store.ErrNotFoundcodes.NotFound
  • Validation errors (e.g., invalid issuer ID) → codes.InvalidArgument
  • Parsing errors → codes.InvalidArgument
  • Unexpected internal errors → codes.Internal

66-87: 🛠️ Refactor suggestion

Enhance HTTP response with security headers and caching directives

To improve security and performance, consider adding the following HTTP headers:

  • Security Headers:

    • X-Content-Type-Options: nosniff
    • X-Frame-Options: DENY
  • Caching Headers:

    • Cache-Control: public, max-age=3600
    • ETag header based on the CRL content for cache validation

Implementing these headers ensures better protection against certain types of attacks and optimizes client-side caching of the CRL.


52-64: 🛠️ Refactor suggestion

Implement exponential backoff and context checks in retry mechanism

The tryGetRevocationList method currently retries immediately without delay and does not check for context cancellation. Improving the retry logic with exponential backoff and context awareness enhances reliability and responsiveness.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Outside diff range and nitpick comments (10)
certificate-authority/service/http/service.go (1)

29-34: Consider CRL configuration flexibility.

The current implementation enables/disables CRL functionality through a boolean flag. Consider if more granular configuration might be needed in the future, such as:

  • CRL update intervals
  • Different CRL endpoints for different certificate types
  • CRL caching settings

It might be worth planning for these potential requirements now to avoid future breaking changes.

certificate-authority/store/mongodb/store.go (1)

53-75: Add documentation for processCursor function.

Please add documentation explaining:

  • The purpose of the function
  • The generic type parameter T
  • The Process callback parameter
  • The return values (count and error)

Apply this diff:

+// processCursor iterates over a MongoDB cursor and processes each document using the provided callback.
+// It returns the count of successfully processed documents and any errors encountered during iteration.
+// Type parameter T represents the document type to be processed.
 func processCursor[T any](ctx context.Context, cr *mongo.Cursor, p store.Process[T]) (int, error) {
certificate-authority/service/grpc/deleteSigningRecords_test.go (1)

25-28: Consider using test helpers for JWT token creation

While the token creation is functional, consider extracting this common test setup into a dedicated test helper function, as it's likely to be reused across other test files.

+func createTestToken(t *testing.T, owner string) string {
+    return config.CreateJwtToken(t, jwt.MapClaims{
+        ownerClaim: owner,
+    })
+}
pkg/security/certificateSigner/certificateSigner.go (1)

Line range hint 67-83: Consider enhancing error messages for better debugging.

While the error handling is comprehensive, consider making the error messages more specific to help with troubleshooting.

-		return nil, errors.New("pem not found")
+		return nil, errors.New("failed to decode PEM block from CSR")
certificate-authority/test/service.go (2)

33-43: Consider making CRL configuration more flexible.

A few concerns about the current implementation:

  1. The CRL expiration time is hard-coded to 1 hour
  2. CRL is only enabled for MongoDB without clear justification

Consider:

  1. Making the expiration time configurable through environment variables or configuration files
  2. Document why CRL is only supported with MongoDB
  3. Add validation for the expiration time to ensure it's reasonable (e.g., not too short or too long)

Example configuration structure:

type CRLConfig struct {
    Enabled   bool
    ExpiresIn time.Duration `env:"CRL_EXPIRES_IN" default:"1h" validate:"required,min=15m,max=24h"`
}

25-43: Add tests for new configuration functions.

The new MakeHTTPConfig and MakeCRLConfig functions should have corresponding test cases to verify:

  1. Correct configuration generation
  2. Proper handling of different database types for CRL
  3. Validation of configuration values

Would you like me to help generate test cases for these new functions?

certificate-authority/service/grpc/signer_internal_test.go (1)

117-150: LGTM: Good test coverage for CRL server functionality.

The test cases effectively cover both success and failure scenarios for CRL server configuration. Consider adding a few more edge cases:

  1. Empty CRL server URL with CRL enabled
  2. Valid URL but with CRL disabled
  3. HTTPS URL with invalid certificate
certificate-authority/service/service.go (1)

Line range hint 103-123: Consider implementing periodic CRL generation.

While the code sets up the infrastructure for CRL support, consider adding a periodic task (similar to the existing cleanup job) that:

  1. Generates and updates the CRL periodically
  2. Handles CRL caching to prevent database load
  3. Monitors CRL size and implements pagination if needed

You could utilize the existing cron scheduler infrastructure:

// Example structure for periodic CRL generation
_, err = s.NewJob(
    gocron.CronJob(config.Signer.CRL.UpdateInterval, true),
    gocron.NewTask(func() {
        if err := generateAndStoreCRL(ctx, dbStorage); err != nil {
            logger.Error("Failed to generate CRL", err)
        }
    }),
)
certificate-authority/store/mongodb/signingRecords_test.go (1)

302-304: Consider improving the handler implementation.

The current implementation has a few potential improvements:

  1. The method name 'process' could be more descriptive, e.g., 'appendSigningRecord'
  2. The error return is unused as the method always returns nil

Consider this refactor:

-func (h *testSigningRecordHandler) process(sr *store.SigningRecord) (err error) {
+func (h *testSigningRecordHandler) appendSigningRecord(sr *store.SigningRecord) {
 	h.lcs = append(h.lcs, sr)
-	return nil
}
certificate-authority/store/mongodb/revocationList.go (1)

191-214: Consider adding an index on Certificates.ValidUntil for performance optimization

To enhance query performance when filtering non-expired certificates, consider adding an index on the Certificates.ValidUntil field, especially as the number of certificates grows.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between fb8c9e6 and e573b2b.

⛔ Files ignored due to path filters (10)
  • certificate-authority/config.yaml is excluded by !**/*.yaml
  • certificate-authority/pb/service.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • certificate-authority/pb/service.swagger.json is excluded by !**/*.json
  • certificate-authority/pb/service_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/signingRecords.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • charts/plgd-hub/templates/certificate-authority/config.yaml is excluded by !**/*.yaml
  • charts/plgd-hub/values.yaml is excluded by !**/*.yaml
  • device-provisioning-service/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • device-provisioning-service/pb/service.swagger.json is excluded by !**/*.json
📒 Files selected for processing (56)
  • bundle/nginx/nginx.conf.template (1 hunks)
  • certificate-authority/pb/README.md (3 hunks)
  • certificate-authority/pb/doc.html (7 hunks)
  • certificate-authority/pb/service.proto (2 hunks)
  • certificate-authority/pb/signingRecords.go (3 hunks)
  • certificate-authority/pb/signingRecords.proto (2 hunks)
  • certificate-authority/pb/signingRecords_test.go (1 hunks)
  • certificate-authority/service/cleanDatabase_test.go (5 hunks)
  • certificate-authority/service/config.go (3 hunks)
  • certificate-authority/service/config_test.go (1 hunks)
  • certificate-authority/service/grpc/config.go (2 hunks)
  • certificate-authority/service/grpc/config_test.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords_test.go (4 hunks)
  • certificate-authority/service/grpc/getSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/getSigningRecords_test.go (5 hunks)
  • certificate-authority/service/grpc/server.go (2 hunks)
  • certificate-authority/service/grpc/server_test.go (1 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signCertificate_test.go (4 hunks)
  • certificate-authority/service/grpc/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/grpc/signer_internal_test.go (3 hunks)
  • certificate-authority/service/http/config.go (1 hunks)
  • certificate-authority/service/http/requestHandler.go (1 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/service/http/service.go (2 hunks)
  • certificate-authority/service/http/signCertificate_test.go (6 hunks)
  • certificate-authority/service/http/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/service.go (2 hunks)
  • certificate-authority/service/uri/uri.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords_test.go (18 hunks)
  • certificate-authority/store/mongodb/bulkWriter.go (0 hunks)
  • certificate-authority/store/mongodb/config.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList_test.go (1 hunks)
  • certificate-authority/store/mongodb/signingRecords.go (3 hunks)
  • certificate-authority/store/mongodb/signingRecords_test.go (13 hunks)
  • certificate-authority/store/mongodb/store.go (3 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList_test.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • certificate-authority/test/revocationList.go (1 hunks)
  • certificate-authority/test/service.go (2 hunks)
  • charts/plgd-hub/README.md (0 hunks)
  • device-provisioning-service/Makefile (1 hunks)
  • device-provisioning-service/pb/service.proto (4 hunks)
  • http-gateway/test/http.go (1 hunks)
  • http-gateway/uri/uri.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (0 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (0 hunks)
  • pkg/security/x509/crl.go (1 hunks)
💤 Files with no reviewable changes (4)
  • certificate-authority/store/mongodb/bulkWriter.go
  • charts/plgd-hub/README.md
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
✅ Files skipped from review due to trivial changes (1)
  • certificate-authority/service/uri/uri.go
🚧 Files skipped from review as they are similar to previous changes (35)
  • bundle/nginx/nginx.conf.template
  • certificate-authority/pb/README.md
  • certificate-authority/pb/service.proto
  • certificate-authority/pb/signingRecords.go
  • certificate-authority/pb/signingRecords.proto
  • certificate-authority/pb/signingRecords_test.go
  • certificate-authority/service/cleanDatabase_test.go
  • certificate-authority/service/config.go
  • certificate-authority/service/config_test.go
  • certificate-authority/service/grpc/config_test.go
  • certificate-authority/service/grpc/deleteSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords_test.go
  • certificate-authority/service/grpc/server.go
  • certificate-authority/service/grpc/server_test.go
  • certificate-authority/service/grpc/signCertificate_test.go
  • certificate-authority/service/grpc/signIdentityCertificate_test.go
  • certificate-authority/service/http/config.go
  • certificate-authority/service/http/requestHandler.go
  • certificate-authority/service/http/revocationList_test.go
  • certificate-authority/service/http/signIdentityCertificate_test.go
  • certificate-authority/store/cqldb/revocationList.go
  • certificate-authority/store/cqldb/signingRecords_test.go
  • certificate-authority/store/mongodb/config.go
  • certificate-authority/store/mongodb/revocationList_test.go
  • certificate-authority/store/mongodb/signingRecords.go
  • certificate-authority/store/revocationList.go
  • certificate-authority/store/revocationList_test.go
  • certificate-authority/store/store.go
  • certificate-authority/test/revocationList.go
  • device-provisioning-service/Makefile
  • device-provisioning-service/pb/service.proto
  • http-gateway/test/http.go
  • http-gateway/uri/uri.go
  • pkg/security/x509/crl.go
🧰 Additional context used
📓 Learnings (1)
certificate-authority/store/mongodb/revocationList.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
🪛 GitHub Check: CodeQL
certificate-authority/store/mongodb/revocationList.go

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.

🔇 Additional comments (42)
certificate-authority/service/http/service.go (4)

5-14: LGTM: Import changes are appropriate.

The new imports are necessary for implementing CRL functionality and follow Go's import organization best practices.


52-52: LGTM: Proper initialization and error handling.

The RequestHandler initialization properly includes the new store parameter and maintains good error handling practices.


27-46: LGTM: Secure implementation of CRL whitelist.

The implementation includes several positive security aspects:

  1. Proper regex escaping using QuoteMeta
  2. Specific HTTP method restriction
  3. Conditional enablement via config
  4. Clear authorization rules
#!/bin/bash
# Verify no other endpoints are using the SigningRevocationListBase path
rg "SigningRevocationListBase" --type go -C 3

23-23: Verify the impact of making requestHandler private.

The change from RequestHandler to requestHandler makes the field private. While this improves encapsulation, we should verify there are no external dependencies on this field.

✅ Verification successful

Let me gather more information to verify if there are any external usages of the RequestHandler field.


Based on the search results, I can now generate the final response since I have enough information to verify the impact of making requestHandler private.

No external usage found for RequestHandler field

The change from RequestHandler to requestHandler in certificate-authority/service/http/service.go is safe. The field is only used internally within the package and there are no external dependencies accessing this field directly.

The search results show that:

  1. The field is initialized privately through newRequestHandler() function
  2. No code outside the package attempts to access this field directly
  3. All interactions with the request handler are encapsulated within the package's methods
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any usage of RequestHandler field access
rg -l "\.RequestHandler\b" --type go

Length of output: 1709


Script:

#!/bin/bash
# Search for any direct usage of RequestHandler in the codebase
rg "RequestHandler" --type go -C 2

# Also search for any struct initialization that might set this field
ast-grep --pattern 'service := &Service{
  $$$
}'

Length of output: 194699

certificate-authority/service/grpc/config.go (2)

16-22: LGTM! Well-structured CRL configuration.

The struct is well-defined with appropriate fields and tags.


58-58: LGTM! Improved error messages.

The error messages are now more clear and consistent.

Also applies to: 62-62

certificate-authority/store/mongodb/store.go (2)

100-103: Add logging for sensitive database operations.

The clearDatabases method performs critical operations (dropping collections) without any logging. In a certificate authority system, such operations should be logged for audit purposes.
[security]
Apply this diff:

 func (s *Store) clearDatabases(ctx context.Context) error {
+	s.logger.Info("Clearing certificate authority databases")
 	var errs *multierror.Error
 	errs = multierror.Append(errs, s.Collection(signingRecordsCol).Drop(ctx))
 	errs = multierror.Append(errs, s.Collection(revocationListCol).Drop(ctx))
+	if err := errs.ErrorOrNil(); err != nil {
+		s.logger.Error("Failed to clear databases", log.ErrorKey, err)
+	}
 	return errs.ErrorOrNil()
 }

19-21: Verify the impact of removing bulkWriter.

The replacement of bulkWriter with logger suggests bulk write operations are no longer supported. This could impact performance if bulk operations are still needed elsewhere in the codebase.

✅ Verification successful

Removal of bulkWriter is justified and safe

The removal of bulkWriter is a valid change because:

  1. The certificate authority module now uses direct MongoDB operations (InsertOne, UpdateOne, DeleteMany, InsertMany) instead of bulk operations
  2. The only bulk operation needed (InsertMany) is used directly in revocationList.go without requiring the bulkWriter middleware
  3. The signing records operations are single-document operations that don't benefit from bulk writing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining bulk operation usage that might be affected
rg -l 'bulk|Bulk' --type go

Length of output: 575


Script:

#!/bin/bash
# Let's check if there are any bulk operations in the certificate-authority module
rg -g 'certificate-authority/**' -B 3 -A 3 'bulk|Bulk'

# Let's also check the actual implementation to see if bulk operations were replaced with single operations
ast-grep --pattern 'func ($x *Store) $method($$$) {
  $$$
}'  certificate-authority/store/mongodb/store.go

Length of output: 164


Script:

#!/bin/bash
# Let's check the git history of this file to understand the changes
git log -p certificate-authority/store/mongodb/store.go | grep -A 10 -B 10 "bulkWriter"

# Let's also check if there are any write operations in the current implementation
rg -g 'certificate-authority/**' "InsertOne|UpdateOne|DeleteOne|InsertMany|UpdateMany|DeleteMany" --type go

Length of output: 4858

certificate-authority/service/grpc/deleteSigningRecords_test.go (4)

5-5: LGTM: Proper handling of certificate serial numbers

The addition of math/big import and the new fields Serial and IssuerId in CredentialStatus align with standard X.509 certificate practices, where certificate serial numbers need to handle large integers.

Also applies to: 39-40


53-62: LGTM: Good error case coverage

The new test case "missing token with ownerClaim in ctx" properly validates the authentication requirement for the DeleteSigningRecords operation.


109-113: LGTM: Improved error handling pattern

The updated error handling pattern with early return on error is clean and follows good testing practices.


100-100: Verify HTTPS configuration across environments

The server initialization now includes the HTTPS URL constructed from CERTIFICATE_AUTHORITY_HTTP_HOST. Ensure this configuration is properly set across all deployment environments.

✅ Verification successful

Let me analyze the results and generate a final response.

HTTPS configuration is consistently applied across the codebase

The verification shows that the HTTPS scheme is consistently used across all relevant components:

  • Test configurations properly set up the HTTPS URL in certificate-authority/test/service.go
  • All gRPC server initializations in test files correctly use the HTTPS scheme
  • Resource Directory service correctly references the Certificate Authority with HTTPS
  • HTTP endpoints in tests properly use the configured host
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for CERTIFICATE_AUTHORITY_HTTP_HOST usage to verify consistent HTTPS scheme
rg -l "CERTIFICATE_AUTHORITY_HTTP_HOST" | while read -r file; do
  echo "=== $file ==="
  rg "CERTIFICATE_AUTHORITY_HTTP_HOST" "$file" -A 2 -B 2
done

Length of output: 4644

pkg/security/certificateSigner/certificateSigner.go (3)

19-22: LGTM! SignerConfig struct changes are well-structured.

The addition of CRLDistributionPoints field is appropriate for storing CRL distribution point URLs.


39-43: LGTM! Proper implementation of defensive copying.

The use of slices.Clone is the correct approach for safely copying the distribution points slice.


85-92: Verify CRL Distribution Point URLs.

Consider adding validation for CRLDistributionPoints URLs to ensure they are well-formed and accessible.

certificate-authority/service/http/signCertificate_test.go (3)

16-18: LGTM! Import changes improve modularity

The transition to centralized URI management via certAuthURI and the update to pkgGrpc enhance the codebase organization.


115-115: LGTM! URI management centralization

The transition to certAuthURI.SignCertificate improves maintainability by centralizing URI management.

Also applies to: 127-127


54-60: ⚠️ Potential issue

Add verification for certificate uniqueness

The test case for signing with the same CSR should verify that consecutive signing operations produce different certificates (unique serial numbers). This verification is crucial for proper certificate revocation tracking.

Add verification logic to the test case:

 {
   name: "valid - new with the same csr",
   args: args{
     req: &pb.SignCertificateRequest{
       CertificateSigningRequest: csr,
     },
   },
+  verify: func(t *testing.T, got *pb.SignCertificateResponse, previous *pb.SignCertificateResponse) {
+    require.NotEqual(t, previous.Certificate.Serial, got.Certificate.Serial,
+      "certificates signed with same CSR must have unique serial numbers")
+  },
 },

Likely invalid or redundant comment.

certificate-authority/test/service.go (3)

10-10: LGTM!

The gRPC package import is necessary for the new CRL configuration functionality.


53-59: LGTM!

The changes improve modularity by extracting configuration logic into separate functions while maintaining proper validation.


25-31: Verify HTTPS configuration for external address.

While the function correctly sets up the HTTP configuration, there are a few security considerations:

  1. The external address is hardcoded to use HTTPS
  2. There's no validation of the host values from the config package

Let's verify the test configuration setup:

✅ Verification successful

HTTPS configuration is correctly set up for testing environment

The verification shows that:

  1. The external HTTPS address is appropriate as the service integrates with a proper TLS setup:
    • TLS configurations are properly defined in test/config/config.go
    • Certificate management is handled through dedicated functions (MakeTLSServerConfig, MakeTLSClientConfig)
  2. The plain host address for internal communication is correct as it's used within the test environment on localhost
  3. The HTTP server configuration in MakeHttpServerConfig includes appropriate security timeouts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if TLS/HTTPS is properly configured in test environment

# Test 1: Check if HTTPS certificates are configured
rg -A 5 "CERTIFICATE_AUTHORITY_HTTP" test/config/

# Test 2: Check if there are any TLS-related environment variables
rg "TEST_.*CERT|TEST_.*KEY" test/config/

Length of output: 542


Script:

#!/bin/bash
# Let's check the HTTP server configuration setup

# Check MakeHttpServerConfig implementation
rg -A 10 "MakeHttpServerConfig" test/config/

# Check if there are any TLS/certificate configurations in the server setup
ast-grep --pattern 'func MakeHttpServerConfig() $_ {
  $$$
}'

# Look for any TLS-related configurations in the entire test directory
rg -g '*.go' "TLS|Certificate" test/

Length of output: 11146

certificate-authority/service/grpc/signer_internal_test.go (2)

7-7: LGTM: Import and struct field additions are appropriate.

The addition of the time import and crlServer field properly supports the new CRL-related test cases.

Also applies to: 52-52


155-155: Previous review comment about parameterizing values is still applicable.

The hardcoded "ownerClaim" and "hubID" values limit test flexibility.

certificate-authority/service/service.go (2)

122-123: Document CRL-related error handling in HTTP endpoints.

With CRL functionality being conditionally enabled and direct database access for CRL distribution, ensure that:

  1. HTTP endpoints properly handle cases when CRL is disabled
  2. Database errors during CRL retrieval are properly handled and logged

Let's verify the HTTP service implementation:

#!/bin/bash
# Search for CRL-related error handling in HTTP package
rg -A 10 "func.*CRL" certificate-authority/service/http/

# Search for CRL-related configuration documentation
rg -A 5 "CRL.*Enabled" 

103-103: Validate the external address before passing it to the GRPC service.

The external address is crucial for CRL as it will be embedded in issued certificates as the CRL distribution point. Consider validating that it's a valid HTTPS URL before passing it to the service.

Let's check if the external address validation is implemented:

certificate-authority/service/grpc/signer.go (2)

49-55: LGTM: Well-implemented issuer ID generation.

The function correctly generates a deterministic UUID based on the certificate's public key, ensuring consistent issuer identification across restarts.


166-190: LGTM: Well-structured signing logic consolidation.

The sign method effectively:

  • Consolidates duplicate code between identity and standard certificate signing
  • Properly handles CRL distribution points
  • Maintains clear separation of concerns
certificate-authority/service/grpc/signCertificate.go (1)

Line range hint 29-60: LGTM: Well-structured certificate record creation.

The updated toSigningRecord function properly integrates the new issuerID parameter and correctly handles the certificate serial number, enhancing the tracking capabilities of the certificate authority.

certificate-authority/store/cqldb/signingRecords.go (2)

342-367: LGTM! Well-structured implementation of the signing records loader.

The implementation demonstrates good practices:

  • Proper error handling and resource cleanup
  • Efficient deduplication of records
  • Context-aware for cancellation support

368-374: ⚠️ Potential issue

Critical: Implement proper certificate revocation mechanism.

The current implementation deletes records instead of implementing proper certificate revocation. This remains a significant security concern as previously noted in the past review.

The deletion approach:

  1. Violates RFC 5280 requirements for certificate revocation
  2. Loses critical audit trail information
  3. Makes it impossible to check certificate revocation status

Given the security implications, this should be tracked as a high-priority issue. Would you like me to create a GitHub issue to track this security enhancement?

certificate-authority/store/mongodb/signingRecords_test.go (3)

44-45: LGTM: Consistent implementation of new credential fields.

The new Serial and IssuerId fields have been properly added to all test cases with consistent values. The Serial field correctly uses big.NewInt(42).String() for conversion, and the IssuerId follows the UUID format.

Also applies to: 64-65, 83-84, 217-218, 283-284, 326-327, 341-342, 356-357, 371-372


101-101: LGTM: Improved error handling with early return.

The addition of early return after error check follows Go's idiomatic error handling pattern and improves code readability.


44-45: Verify integration with certificate revocation logic.

The new Serial and IssuerId fields are crucial for certificate tracking. Let's verify their integration with the certificate revocation logic.

✅ Verification successful

Based on the gathered information, I can now provide the final response:

Integration with certificate revocation logic is properly implemented

The Serial and IssuerId fields are correctly integrated with the certificate revocation system:

  • The RevocationListCertificate structure properly uses the Serial field for tracking revoked certificates
  • The Store interface includes comprehensive revocation-related operations (SupportsRevocationList, UpdateRevocationList, etc.)
  • The MongoDB implementation handles certificate revocation with proper tracking of serial numbers
  • The fields are properly tagged for database storage (bson:"serial")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the new fields are properly integrated with certificate revocation

# Test 1: Check for certificate revocation related code that uses these fields
echo "Checking for certificate revocation implementation..."
rg -l "CertificateRevocation|RevocationList|Revoke" --type go

# Test 2: Check for proper usage of Serial and IssuerId in the service
echo "Checking usage of Serial and IssuerId fields..."
rg "Serial.*IssuerId|IssuerId.*Serial" --type go

Length of output: 1396


Script:

#!/bin/bash
# Let's check the implementation details of certificate revocation

# Check revocation list implementation
echo "=== Checking RevocationList implementation ==="
rg -A 10 "type.*RevocationList" --type go

# Check how Serial and IssuerId are used in revocation context
echo -e "\n=== Checking Serial and IssuerId usage in revocation context ==="
ast-grep --pattern 'func $_($_) {
  $$$
  Serial $$$
  $$$
}'

# Check the actual revocation logic
echo -e "\n=== Checking revocation logic implementation ==="
rg -A 10 "func.*[Rr]evoke" --type go

# Check if these fields are used in queries
echo -e "\n=== Checking query implementations ==="
rg -A 5 "Find.*Serial|Find.*IssuerId" --type go

Length of output: 5817


Script:

#!/bin/bash
# Let's examine the revocation implementation more closely

# Check the RevokeSigningRecords implementation in MongoDB store
echo "=== Checking MongoDB RevokeSigningRecords implementation ==="
rg -A 30 "func.*RevokeSigningRecords.*mongodb" --type go

# Check how RevocationListCertificate is created/used
echo -e "\n=== Checking RevocationListCertificate usage ==="
rg -A 10 "RevocationListCertificate.*Serial" --type go

# Check store interface definition
echo -e "\n=== Checking Store interface definition ==="
rg -A 20 "type Store interface" --type go

# Check if there are any tests validating Serial and IssuerId in revocation
echo -e "\n=== Checking relevant test cases ==="
rg -A 10 "Test.*Revoke.*Serial|Test.*Revoke.*IssuerId" --type go

Length of output: 11471

certificate-authority/pb/doc.html (4)

349-349: Method descriptions are now more precise and accurate.

The updated descriptions better reflect the actual functionality:

  • GetSigningRecords: Simplified description for clarity
  • DeleteSigningRecords: Now accurately describes both revocation and deletion capabilities

Also applies to: 356-356


386-391: Dual HTTP bindings require documentation and migration strategy.

The addition of new HTTP endpoints with /certificate-authority prefix maintains backward compatibility but requires proper documentation.

Let's check if documentation exists for these dual bindings:

#!/bin/bash
# Check for documentation about API versioning or dual bindings
echo "Searching for API documentation..."
rg -l "api.*version|/certificate-authority/api" --type md certificate-authority/

Also applies to: 403-409, 420-426, 437-443


551-551: Message description accurately reflects dual functionality.

The updated description for DeletedSigningRecords now correctly indicates both revocation and deletion capabilities.


494-511: New fields enhance certificate tracking capabilities.

The addition of serial and issuer_id fields in CredentialStatus improves certificate management by:

  • Tracking certificate serial numbers for better auditing
  • Including issuer identification for enhanced traceability

Let's verify the field usage in the codebase:

✅ Verification successful

Let me gather more context about the usage of these fields in the protobuf definitions and related code:


Based on the comprehensive analysis of the codebase, I can now provide the final response:

The new fields are properly integrated and validated throughout the codebase.

The serial and issuer_id fields in CredentialStatus are:

  • Properly defined in protobuf with correct BSON tags
  • Validated in CredentialStatus.Validate() method
  • Used consistently across test cases and implementations
  • Integrated with certificate signing workflow in signCertificate.go
  • Tracked in MongoDB and CQL database implementations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check usage of new fields
echo "Checking usage of new fields..."
rg "serial|issuerId" --type go certificate-authority/

Length of output: 2694


Script:

#!/bin/bash
# Check protobuf definitions and related code
echo "Checking protobuf definitions..."
rg "CredentialStatus" -A 5 -B 5 certificate-authority/

# Check for any validation or business logic
echo "Checking validation logic..."
ast-grep --pattern 'func $_($_) error {
  $$$
  serial $$$
  $$$
}'

Length of output: 55133

certificate-authority/store/mongodb/revocationList.go (5)

29-42: Proper validation and error handling in InsertRevocationLists method

The InsertRevocationLists function correctly validates each RevocationList before insertion and handles duplicate key errors appropriately.


49-110: Efficient update preparation in getRevocationListUpdate method

The method effectively prepares updates to the revocation list by filtering out duplicates and validating certificates. The use of an aggregation pipeline to identify existing certificates is well-designed.


116-181: Robust handling of revocation list updates in UpdateRevocationList method

The UpdateRevocationList function appropriately updates or creates revocation lists, correctly managing the revocation list number and handling concurrent updates with conditional filtering.


183-225: Effective retrieval of revocation lists in GetRevocationList method

The function efficiently retrieves the revocation list and correctly filters out expired certificates when needed, with appropriate validation of issuerID.

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.


227-243: Well-designed revocation list retrieval in GetLatestIssuedOrIssueRevocationList

This function accurately retrieves the latest issued revocation list or issues a new one if the existing list is expired, ensuring that clients always receive up-to-date revocation information.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🧹 Outside diff range and nitpick comments (19)
certificate-authority/store/mongodb/store.go (1)

90-92: Consider adding security-relevant logging.

Given this is a Certificate Authority service, consider adding structured logging for security-relevant operations such as:

  • Certificate revocations
  • Database clearing operations
  • Error conditions that might indicate security issues

Example usage:

 s := Store{
 	Store:  m,
 	logger: logger,
 }
+// Add logging middleware or wrapper
+s.logger = s.logger.With(log.String("component", "ca-store"))
certificate-authority/service/grpc/deleteSigningRecords_test.go (1)

25-28: Consider adding CRL-specific test cases.

While the basic CRUD operations are tested, consider adding specific test cases for:

  1. Revoking certificates with different reason codes
  2. Handling expired certificates in deletion
  3. Verifying CRL entry timestamps

Would you like me to help generate additional test cases for these CRL-specific scenarios?

Also applies to: 69-69, 78-78

pkg/security/certificateSigner/certificateSigner.go (1)

Line range hint 67-83: Consider defining custom error types for better error handling

While the error handling is comprehensive, using custom error types would improve error handling in the calling code.

Consider implementing this improvement:

+var (
+    ErrPEMNotFound = errors.New("pem not found")
+    ErrInvalidCSRSignature = errors.New("invalid CSR signature")
+)

 func parseCertificateRequest(csr []byte) (*x509.CertificateRequest, error) {
     csrBlock, _ := pem.Decode(csr)
     if csrBlock == nil {
-        return nil, errors.New("pem not found")
+        return nil, ErrPEMNotFound
     }

     certificateRequest, err := x509.ParseCertificateRequest(csrBlock.Bytes)
     if err != nil {
         return nil, err
     }

     err = certificateRequest.CheckSignature()
     if err != nil {
-        return nil, err
+        return nil, fmt.Errorf("%w: %v", ErrInvalidCSRSignature, err)
     }

     return certificateRequest, nil
 }
certificate-authority/test/service.go (1)

25-31: Consider adding validation for configuration values.

While the function correctly sets up the HTTP configuration, it might be beneficial to add validation for the host values to ensure they are not empty or malformed.

 func MakeHTTPConfig() service.HTTPConfig {
+	host := config.CERTIFICATE_AUTHORITY_HTTP_HOST
+	if host == "" {
+		panic("CERTIFICATE_AUTHORITY_HTTP_HOST is not set")
+	}
 	return service.HTTPConfig{
-		ExternalAddress: "https://" + config.CERTIFICATE_AUTHORITY_HTTP_HOST,
-		Addr:            config.CERTIFICATE_AUTHORITY_HTTP_HOST,
+		ExternalAddress: "https://" + host,
+		Addr:            host,
 		Server:          config.MakeHttpServerConfig(),
 	}
 }
certificate-authority/service/grpc/signer_internal_test.go (1)

134-150: Expand invalid CRL server test scenarios.

Consider adding test cases for additional invalid scenarios:

  1. Malformed URLs (e.g., missing protocol, invalid characters)
  2. Unsupported protocols (e.g., ftp://)
  3. Empty string
  4. Very long URLs that might exceed length limits

Example test case:

{
    name: "with crl server - invalid protocol",
    args: args{
        signerConfig: SignerConfig{
            CertFile:  urischeme.URIScheme(fullChainCrt),
            KeyFile:   urischeme.URIScheme(intermediate2Key),
            ValidFrom: "2001-01-01T00:00:00Z",
            ExpiresIn: time.Hour,
            CRL: CRLConfig{
                Enabled:   true,
                ExpiresIn: time.Hour,
            },
        },
        crlServer: "ftp://invalid.example.com",
    },
    wantErr: true,
},
certificate-authority/service/service.go (1)

Line range hint 103-123: Excellent error handling and resource cleanup pattern.

The implementation maintains a robust error handling pattern using closerFn to ensure proper cleanup of resources. This is particularly important for long-lived services managing critical resources like certificates.

Consider documenting this pattern in the project's best practices guide if not already done, as it's a good example of proper resource management in Go services.

certificate-authority/store/revocationList_test.go (3)

13-42: Enhance test coverage for ParseBigInt.

Consider adding these test cases to improve coverage:

  • Empty string
  • Very large numbers (e.g., numbers > int64)
  • Negative numbers
  • Numbers with leading/trailing spaces

Example additions:

 tests := []struct {
     // ... existing cases ...
+    {
+        name:  "Empty string",
+        input: "",
+        wantErr: true,
+    },
+    {
+        name:  "Very large number",
+        input: "115792089237316195423570985008687907853269984665640564039457584007913129639936",
+        want:  new(big.Int).SetString("115792089237316195423570985008687907853269984665640564039457584007913129639936", 10),
+    },
+    {
+        name:  "Negative number",
+        input: "-123456789",
+        want:  big.NewInt(-123456789),
+    },
+    {
+        name:  "Number with spaces",
+        input: "  123456789  ",
+        wantErr: true,
+    },
 }

44-87: Add edge cases for certificate validation.

Consider adding these test cases:

  • Invalid serial number format (e.g., special characters)
  • Future revocation time
  • Very long serial number

Example additions:

 tests := []struct {
     // ... existing cases ...
+    {
+        name: "Invalid serial number format",
+        input: store.RevocationListCertificate{
+            Serial:     "12345@#$%",
+            Revocation: revocation.UnixNano(),
+        },
+        wantErr: true,
+    },
+    {
+        name: "Future revocation time",
+        input: store.RevocationListCertificate{
+            Serial:     "12345",
+            Revocation: time.Now().Add(24 * time.Hour).UnixNano(),
+        },
+        wantErr: true,
+    },
 }

89-201: Add edge cases for revocation list validation.

The test suite is well-structured with good coverage. Consider adding these test cases:

  • Duplicate serial numbers in certificates list
  • Empty certificates list
  • Very large number value

Example additions:

 tests := []struct {
     // ... existing cases ...
+    {
+        name: "Duplicate serial numbers",
+        input: store.RevocationList{
+            Id:         uuid.New().String(),
+            IssuedAt:   revocation.UnixNano(),
+            ValidUntil: revocation.Add(time.Minute).UnixNano(),
+            Number:     "1",
+            Certificates: []*store.RevocationListCertificate{
+                validCertificate,
+                validCertificate,
+            },
+        },
+        wantErr: true,
+    },
+    {
+        name: "Empty certificates list",
+        input: store.RevocationList{
+            Id:           uuid.New().String(),
+            IssuedAt:     revocation.UnixNano(),
+            ValidUntil:   revocation.Add(time.Minute).UnixNano(),
+            Number:       "1",
+            Certificates: []*store.RevocationListCertificate{},
+        },
+        wantErr: true,
+    },
+    {
+        name: "Very large number",
+        input: store.RevocationList{
+            Id:           uuid.New().String(),
+            IssuedAt:     revocation.UnixNano(),
+            ValidUntil:   revocation.Add(time.Minute).UnixNano(),
+            Number:       "115792089237316195423570985008687907853269984665640564039457584007913129639936",
+            Certificates: []*store.RevocationListCertificate{validCertificate},
+        },
+        wantErr: true,
+    },
 }
certificate-authority/service/grpc/signer.go (1)

151-153: Fix typo in method name.

The method name GetCRLConfiguation contains a typo. It should be GetCRLConfiguration.

Apply this diff:

-func (s *Signer) GetCRLConfiguation() (string, time.Duration) {
+func (s *Signer) GetCRLConfiguration() (string, time.Duration) {
     return s.crl.serverAddress, s.crl.validFor
 }
certificate-authority/service/grpc/signCertificate.go (2)

141-145: Add logging for revocation list support status.

Consider adding debug logging when revocation list is not supported to help with troubleshooting.

Apply this diff:

     if s.store.SupportsRevocationList() {
         err = s.updateRevocationListForSigningRecord(ctx, signingRecord, prevSr)
         if err != nil {
             return err
         }
+    } else {
+        s.logger.Debug("skipping revocation list update: store does not support revocation lists")
     }

166-170: Improve error message specificity.

The error message "cannot create signing record" could be more specific about why the credential is required.

Apply this diff:

     credential := signingRecord.GetCredential()
     if credential == nil {
-        return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("cannot create signing record")))
+        return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("signing record requires a valid credential")))
     }
certificate-authority/service/grpc/signCertificate_test.go (2)

157-171: Consider using constants for configuration values

The test configuration setup is comprehensive, but consider extracting magic values like authority paths into named constants for better maintainability.

+const (
+    authorityPath = m2mOauthUri.Base
+)

Line range hint 1-197: Consider adding tests for additional edge cases

While the test coverage is good, consider adding tests for:

  • Certificate signing with expired tokens
  • CSR with invalid key sizes
  • Common names with special characters

Would you like me to help generate these additional test cases?

certificate-authority/store/mongodb/revocationList.go (1)

1-243: Consider tracking expired signing records in revocation list

Based on the learning from signingRecords.go, expired signing records are deleted but not tracked in the revocation list. This could potentially allow reuse of expired certificates.

Consider:

  1. Adding expired signing records to the revocation list before deletion
  2. Implementing a method to bulk add expired records to the revocation list
  3. Adding a background job to periodically check and add expired records

Would you like me to help implement any of these suggestions?

🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.

certificate-authority/store/cqldb/signingRecords.go (1)

342-367: LGTM with a minor suggestion about error variable naming.

The implementation correctly handles pagination, error propagation, and resource cleanup. Consider renaming errClose to closeErr to align with Go's common error variable naming convention.

-	errClose := i.close()
+	closeErr := i.close()
 	if err == nil {
-		return errClose
+		return closeErr
 	}
 	return err
certificate-authority/store/mongodb/signingRecords_test.go (1)

44-45: LGTM! Consider extracting test constants.

The new Serial and IssuerId fields are consistently added across all test cases with proper formatting. The use of big.Int for serials and UUID format for issuer IDs follows best practices.

Consider extracting these values as test constants at the top of the file to improve maintainability:

const (
    testSerial   = "42"
    testIssuerId = "42424242-4242-4242-4242-424242424242"
)

Also applies to: 64-65, 83-84, 217-218, 283-284, 326-327, 341-342, 356-357, 371-372

certificate-authority/service/http/revocationList.go (1)

27-50: Add unit tests for the createCRL function

The createCRL function is crucial for generating the Certificate Revocation List. Adding unit tests will help ensure its correctness and reliability across different scenarios.

Would you like assistance in creating unit tests for this function?

certificate-authority/service/http/revocationList_test.go (1)

93-93: Minor typo in skip message

There's a minor typo in the skip message. It should read: "Revocation list is not supported for CqlDB."

Apply this diff to correct the message:

 func TestRevocationList(t *testing.T) {
     if config.ACTIVE_DATABASE() == database.CqlDB {
-        t.Skip("revocation list not supported for CqlDB")
+        t.Skip("Revocation list is not supported for CqlDB")
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e573b2b and c19ad81.

⛔ Files ignored due to path filters (10)
  • certificate-authority/config.yaml is excluded by !**/*.yaml
  • certificate-authority/pb/service.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • certificate-authority/pb/service.swagger.json is excluded by !**/*.json
  • certificate-authority/pb/service_grpc.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • certificate-authority/pb/signingRecords.pb.go is excluded by !**/*.pb.go, !**/*.pb.go
  • charts/plgd-hub/templates/certificate-authority/config.yaml is excluded by !**/*.yaml
  • charts/plgd-hub/values.yaml is excluded by !**/*.yaml
  • device-provisioning-service/pb/service.pb.gw.go is excluded by !**/*.pb.gw.go, !**/*.pb.gw.go
  • device-provisioning-service/pb/service.swagger.json is excluded by !**/*.json
📒 Files selected for processing (57)
  • bundle/nginx/nginx.conf.template (1 hunks)
  • certificate-authority/pb/README.md (3 hunks)
  • certificate-authority/pb/doc.html (7 hunks)
  • certificate-authority/pb/service.proto (2 hunks)
  • certificate-authority/pb/signingRecords.go (3 hunks)
  • certificate-authority/pb/signingRecords.proto (2 hunks)
  • certificate-authority/pb/signingRecords_test.go (1 hunks)
  • certificate-authority/service/cleanDatabase_test.go (5 hunks)
  • certificate-authority/service/config.go (3 hunks)
  • certificate-authority/service/config_test.go (1 hunks)
  • certificate-authority/service/grpc/config.go (2 hunks)
  • certificate-authority/service/grpc/config_test.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/deleteSigningRecords_test.go (4 hunks)
  • certificate-authority/service/grpc/getSigningRecords.go (1 hunks)
  • certificate-authority/service/grpc/getSigningRecords_test.go (5 hunks)
  • certificate-authority/service/grpc/server.go (2 hunks)
  • certificate-authority/service/grpc/server_test.go (1 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signCertificate_test.go (4 hunks)
  • certificate-authority/service/grpc/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/grpc/signer_internal_test.go (3 hunks)
  • certificate-authority/service/http/config.go (1 hunks)
  • certificate-authority/service/http/requestHandler.go (1 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/service/http/service.go (2 hunks)
  • certificate-authority/service/http/signCertificate_test.go (6 hunks)
  • certificate-authority/service/http/signIdentityCertificate_test.go (3 hunks)
  • certificate-authority/service/service.go (2 hunks)
  • certificate-authority/service/uri/uri.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords.go (1 hunks)
  • certificate-authority/store/cqldb/signingRecords_test.go (18 hunks)
  • certificate-authority/store/mongodb/bulkWriter.go (0 hunks)
  • certificate-authority/store/mongodb/config.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList.go (1 hunks)
  • certificate-authority/store/mongodb/revocationList_test.go (1 hunks)
  • certificate-authority/store/mongodb/signingRecords.go (3 hunks)
  • certificate-authority/store/mongodb/signingRecords_test.go (13 hunks)
  • certificate-authority/store/mongodb/store.go (3 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList_test.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • certificate-authority/test/revocationList.go (1 hunks)
  • certificate-authority/test/service.go (2 hunks)
  • charts/plgd-hub/README.md (0 hunks)
  • device-provisioning-service/Makefile (1 hunks)
  • device-provisioning-service/pb/service.proto (4 hunks)
  • device-provisioning-service/service/provisionFail_test.go (1 hunks)
  • http-gateway/test/http.go (1 hunks)
  • http-gateway/uri/uri.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (0 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (0 hunks)
  • pkg/security/x509/crl.go (1 hunks)
💤 Files with no reviewable changes (4)
  • certificate-authority/store/mongodb/bulkWriter.go
  • charts/plgd-hub/README.md
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🚧 Files skipped from review as they are similar to previous changes (33)
  • bundle/nginx/nginx.conf.template
  • certificate-authority/pb/README.md
  • certificate-authority/pb/service.proto
  • certificate-authority/pb/signingRecords.go
  • certificate-authority/pb/signingRecords.proto
  • certificate-authority/pb/signingRecords_test.go
  • certificate-authority/service/cleanDatabase_test.go
  • certificate-authority/service/config.go
  • certificate-authority/service/grpc/config.go
  • certificate-authority/service/grpc/config_test.go
  • certificate-authority/service/grpc/deleteSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords.go
  • certificate-authority/service/grpc/getSigningRecords_test.go
  • certificate-authority/service/grpc/server.go
  • certificate-authority/service/grpc/server_test.go
  • certificate-authority/service/grpc/signIdentityCertificate_test.go
  • certificate-authority/service/http/config.go
  • certificate-authority/service/http/signCertificate_test.go
  • certificate-authority/service/http/signIdentityCertificate_test.go
  • certificate-authority/service/uri/uri.go
  • certificate-authority/store/cqldb/revocationList.go
  • certificate-authority/store/cqldb/signingRecords_test.go
  • certificate-authority/store/mongodb/config.go
  • certificate-authority/store/mongodb/revocationList_test.go
  • certificate-authority/store/mongodb/signingRecords.go
  • certificate-authority/store/revocationList.go
  • certificate-authority/store/store.go
  • certificate-authority/test/revocationList.go
  • device-provisioning-service/Makefile
  • device-provisioning-service/pb/service.proto
  • http-gateway/test/http.go
  • http-gateway/uri/uri.go
  • pkg/security/x509/crl.go
🧰 Additional context used
📓 Learnings (1)
certificate-authority/store/mongodb/revocationList.go (1)
Learnt from: Danielius1922
PR: plgd-dev/hub#1383
File: certificate-authority/store/mongodb/signingRecords.go:139-141
Timestamp: 2024-10-28T17:11:50.454Z
Learning: In `certificate-authority/store/mongodb/signingRecords.go`, within the `RevokeSigningRecords` method, expired signing records are deleted but not added to the revocation list.
🪛 GitHub Check: CodeQL
certificate-authority/store/mongodb/revocationList.go

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.

🔇 Additional comments (57)
certificate-authority/service/http/requestHandler.go (5)

5-15: LGTM: Import changes are well-organized and necessary.

The new imports support the added functionality and follow Go's import organization best practices.


49-50: Cache control headers needed for CRL endpoint.

Referring to the previous review comment about adding cache control headers for the CRL endpoint. This is still applicable as the implementation registers the endpoint without caching headers.


42-62: LGTM: Well-structured implementation with proper error handling.

The implementation demonstrates good practices:

  • Proper initialization of dependencies
  • Conditional feature flag handling
  • Clean integration with GRPC
  • Comprehensive error handling

29-41: Verify impact of breaking changes in constructor.

The changes introduce two breaking changes:

  1. Unexported newRequestHandler function
  2. Added required store parameter

Please ensure all callers are updated accordingly.

#!/bin/bash
# Search for external usage of NewRequestHandler
rg "NewRequestHandler" --type go --glob '!certificate-authority/service/http/**'

19-25: Verify impact of unexported type change.

The renaming of RequestHandler to requestHandler is a breaking change if the type was previously used by external packages.

certificate-authority/service/http/service.go (5)

23-23: LGTM! Good encapsulation.

Making the requestHandler type private improves encapsulation by hiding implementation details.


27-27: LGTM! Clean dependency injection.

The addition of the store parameter follows good dependency injection practices and maintains clear separation of concerns.


36-46: Verify the migration from kitNetHttp to pkgHttp package.

The change from kitNetHttp.NewDefaultAuthorizationRules to pkgHttp.NewDefaultAuthorizationRules suggests a package migration.

Let's verify no remaining references to the old package exist:

#!/bin/bash
# Check for any remaining references to kitNetHttp
rg "kitNetHttp"

Line range hint 52-56: Verify the newRequestHandler implementation.

The initialization looks good with proper error handling, but let's verify the implementation of the newRequestHandler function.

Let's check the implementation:

#!/bin/bash
# Look for newRequestHandler implementation
ast-grep --pattern 'func newRequestHandler($$$) ($$$) {
  $$$
}'

28-34: 🛠️ Refactor suggestion

Consider restricting the CRL endpoint pattern.

The current pattern SigningRevocationListBase + /.*`` matches any characters after the base path. This might be too permissive and could potentially expose unintended paths.

Let's check the intended CRL path format:

Consider using a more specific pattern that matches only the expected format of CRL paths. For example, if CRLs are identified by UUIDs:

-			URI:    regexp.MustCompile(regexp.QuoteMeta(uri.SigningRevocationListBase) + `\/.*`),
+			URI:    regexp.MustCompile(regexp.QuoteMeta(uri.SigningRevocationListBase) + `\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`),
certificate-authority/store/mongodb/store.go (5)

7-7: LGTM: Import and struct changes align with new error handling approach.

The replacement of bulkWriter with logger and addition of multierror package support better error handling and logging capabilities.

Also applies to: 20-20


37-51: Documentation and error handling issues persist in MongoIterator.

The previously identified issues regarding documentation and error handling in MongoIterator remain unaddressed.


53-75: Error handling in processCursor can be improved.

The previously identified issue regarding breaking the loop on first error remains unaddressed.


82-85: Missing indices for revocationListCol persist.

The previously identified issue regarding missing indices for revocationListCol remains unaddressed.


100-103: LGTM: Improved error handling in clearDatabases.

The error handling has been improved using multierror to properly aggregate errors from dropping both collections.

certificate-authority/service/grpc/deleteSigningRecords_test.go (5)

5-5: LGTM: Required imports for CRL implementation.

The addition of math/big is appropriate for handling certificate serial numbers, which are typically large integers in X.509 certificates.

Also applies to: 17-17


53-62: LGTM: Enhanced security with token validation test.

Good addition of the "missing token" test case. This improves security coverage by ensuring proper authentication checks.


109-113: LGTM: Improved error handling in tests.

The enhanced error handling with explicit checks improves test reliability.


39-40: Verify serial number format compliance with RFC 5280.

The addition of Serial and IssuerId fields aligns with CRL requirements. However, ensure that:

  1. The serial number format complies with RFC 5280 Section 4.1.2.2
  2. The IssuerId format is consistently used across the codebase

Let's verify the serial number format implementation:

✅ Verification successful

Based on the gathered information, I can now provide a final response:

Serial number implementation complies with RFC 5280 requirements

The implementation uses big.Int with proper random generation via crypto/rand and a 128-bit limit (serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)), which ensures:

  • Positive integers only (no negative values found in codebase)
  • Maximum 20 octets as per RFC 5280
  • Cryptographically secure random generation
  • Proper string conversion for storage

The IssuerId format is consistently used as UUID across all test files and implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check serial number handling across the codebase
# Expect: Consistent big.Int string conversion and RFC 5280 compliance

# Search for serial number handling patterns
rg -A 3 "Serial.*big\.Int"

# Check for potential negative serial numbers (not allowed by RFC 5280)
ast-grep --pattern 'big.NewInt(-$_)'

Length of output: 67


Script:

#!/bin/bash
# Let's try a broader search for serial number handling patterns
rg -A 3 "Serial.*String\(\)"

# Search for any serial number related code
rg -A 3 "Serial.*:.*"

# Look for serial number type definitions
ast-grep --pattern 'type $_ struct {
  $$$
  Serial $_ 
  $$$
}'

# Search for big.Int usage with serial numbers
rg -A 3 "big\."

Length of output: 40776


Script:

#!/bin/bash
# Let's check the actual serial number generation and validation logic
rg -A 5 "serialNumber.*:=.*rand\." 

# Look for any serial number validation code
ast-grep --pattern 'func $_ ($_) error {
  $$$
  serial := $$$
  $$$
}'

# Check for any RFC 5280 related comments or validation
rg -i "rfc.*5280"

Length of output: 575


100-100: Verify HTTPS configuration for CRL distribution point.

The server instantiation now includes the HTTPS URL, which is crucial for CRL distribution. Ensure that:

  1. The HTTPS endpoint is properly configured for CRL access
  2. The URL format follows RFC 5280 requirements for CRL distribution points

Let's verify the CRL endpoint configuration:

✅ Verification successful

Based on the search results, I can now verify the CRL configuration. Let me gather more specific information about the CRL implementation.


Let me try a different approach to verify the CRL configuration.


Based on the search results, I can now provide a final verification response.

HTTPS configuration for CRL distribution point is properly implemented.

The implementation shows:

  1. The CRL URL is properly validated through ValidateCRLDistributionPointAddress which ensures:
    • Valid URL format
    • Absolute HTTPS URL (via u.IsAbs() check)
  2. The CRL distribution point is correctly constructed:
    • Uses the validated HTTPS server address
    • Follows proper path construction: path.Join(s.crl.serverAddress, uri.SigningRevocationListBase, s.issuerID)
  3. The CRL URL is properly injected into certificates via WithCRLDistributionPoints
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CRL endpoint configuration
# Expect: Consistent HTTPS URL format and CRL-specific endpoints

# Check for CRL endpoint definitions
rg -A 5 "CRL.*endpoint|DistributionPoint"

# Verify HTTPS usage across the codebase
rg "https://" --type go

Length of output: 24966


Script:

#!/bin/bash
# Check CRL validation and URL construction
ast-grep --pattern 'func $_(crlServerAddress string) $_ {
  $$$
  ValidateCRLDistributionPointAddress($$$)
  $$$
}'

# Check CRL URL construction and usage
ast-grep --pattern 'WithCRLDistributionPoints($$$)'

Length of output: 171


Script:

#!/bin/bash
# Check CRL validation implementation
rg -A 10 "func ValidateCRLDistributionPointAddress"

# Check how CRL URL is constructed and used in the certificate authority
rg -A 10 "crl\.serverAddress" --type go

Length of output: 3435

pkg/security/certificateSigner/certificateSigner.go (4)

11-11: LGTM: Clean import and struct field addition

The addition of the slices package and CRLDistributionPoints field is well-structured and appropriate for the CRL implementation.

Also applies to: 21-21


39-43: LGTM: Secure implementation of CRL distribution points option

The implementation correctly uses slices.Clone for defensive copying, addressing the previous review feedback.


110-122: ⚠️ Potential issue

Add key usage constraints for enhanced security

The previous review comment about adding key usage constraints is still valid and should be addressed for better security.


Line range hint 85-129: Verify error handling for potential security leaks

Let's ensure that error messages don't leak sensitive information.

✅ Verification successful

Let me verify the code further by checking the error handling in the certificate signing code.


No security concerns found in error handling or cryptographic operations

The verification shows:

  • Error messages are generic and don't leak sensitive information
  • Proper use of crypto/rand for cryptographic operations
  • Clean error handling pattern that doesn't expose internal details
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential sensitive information leaks in error messages
rg -n 'fmt\.Errorf.*%[vswp].*private' .
rg -n 'errors\.New.*private' .
rg -n 'log\..*private' .

# Search for potentially unsafe crypto operations
ast-grep --pattern 'rand.Read($$$)'
ast-grep --pattern 'math/rand'

Length of output: 653


Script:

#!/bin/bash
# Check error handling in the certificate signer
rg -n "return.*nil.*err" pkg/security/certificateSigner/
rg -n "return.*err" pkg/security/certificateSigner/

# Check if crypto/rand is used instead of math/rand
rg -n "rand\." pkg/security/certificateSigner/

Length of output: 1889

certificate-authority/test/service.go (3)

10-10: LGTM!

The new import is required for accessing the grpc.CRLConfig type used in the new CRL configuration.


53-53: LGTM!

The changes improve modularity by extracting HTTP and CRL configuration into separate functions while maintaining config validation.

Also applies to: 59-59


33-43: Review CRL configuration design decisions.

Several concerns about the current implementation:

  1. The expiration time is hard-coded to 1 hour. Consider making this configurable through environment variables or configuration files.
  2. CRL is only enabled for MongoDB without clear documentation explaining why it's not supported for other databases.
  3. No validation of the expiration time to ensure it's reasonable (not too short or too long).

Let's check if CRL is supported in other database implementations:

Consider the following improvements:

  1. Make the expiration time configurable:
 func MakeCRLConfig() grpc.CRLConfig {
+	crlExpiryDuration := os.Getenv("TEST_CRL_EXPIRY_DURATION")
+	expiresIn := time.Hour // default
+	if crlExpiryDuration != "" {
+		var err error
+		expiresIn, err = time.ParseDuration(crlExpiryDuration)
+		if err != nil {
+			panic(fmt.Sprintf("invalid TEST_CRL_EXPIRY_DURATION: %v", err))
+		}
+	}
+
 	if config.ACTIVE_DATABASE() == database.MongoDB {
 		return grpc.CRLConfig{
 			Enabled:   true,
-			ExpiresIn: time.Hour,
+			ExpiresIn: expiresIn,
 		}
 	}
  1. Add documentation explaining the database-specific behavior:
+// MakeCRLConfig creates a CRL configuration for testing.
+// Currently, CRL is only supported with MongoDB as it requires specific
+// database capabilities for managing certificate revocation lists.
 func MakeCRLConfig() grpc.CRLConfig {
certificate-authority/service/grpc/signer_internal_test.go (3)

52-52: LGTM: Clean field addition for CRL server configuration.

The new field follows Go naming conventions and uses an appropriate type for URL storage.


155-155: Parameterize ownerClaim and hubID values.

The hardcoded values "ownerClaim" and "hubID" limit test flexibility. Consider moving these to the test case struct as suggested in the previous review.


117-133: Enhance CRL server test coverage.

While the test case validates the configuration acceptance, consider adding assertions to verify:

  1. The CRL configuration is correctly propagated to the signer
  2. The CRL refresh interval is properly set
  3. The initial CRL fetch behavior
certificate-authority/service/service.go (2)

Line range hint 103-107: LGTM: External address parameter added for CRL support.

The addition of ExternalAddress parameter is consistent with CRL implementation requirements, likely used for CRL distribution point URLs in certificates.

Let's verify the usage of external address in the gRPC service:

#!/bin/bash
# Description: Verify how the external address is used in the gRPC service
# Test: Search for external address usage in certificate-related code
ast-grep --pattern 'ExternalAddress'

122-123: LGTM: CRL feature flag properly configured.

The CRLEnabled flag is correctly propagated from the signer configuration, allowing for conditional enabling of CRL functionality.

Let's verify the CRL configuration usage:

✅ Verification successful

Let me try another search strategy to verify the CRL configuration usage.


Based on the search results, I can now provide a final response about the CRL feature flag verification:

CRL feature flag is properly configured and consistently used throughout the codebase

The CRL configuration is correctly propagated and used:

  • The CRLEnabled flag from config is properly passed to HTTP service initialization
  • When enabled, it:
    • Adds CRL endpoints to the HTTP whitelist (service/http/service.go)
    • Registers the CRL handler route (service/http/requestHandler.go)
    • Sets up CRL distribution points in certificate signing (service/grpc/signer.go)
  • The implementation includes proper validation of CRL configuration (service/grpc/config.go)
  • Test coverage exists for both enabled and disabled states (service/grpc/config_test.go)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify how the CRL configuration is used
# Test: Search for CRL-related configuration and endpoints
rg -A 5 'CRLEnabled'

Length of output: 149


Script:

#!/bin/bash
# Search for CRL-related code and configuration using ripgrep
rg -i "crl" -A 5 --type go

Length of output: 33946

certificate-authority/service/config_test.go (1)

150-210: ⚠️ Potential issue

Add comprehensive test cases for CRL validation.

While the test structure is well-organized and follows good practices, it's missing critical test cases for CRL distribution point validation. As mentioned in the previous review, please add test cases for:

  1. Empty ExternalAddress
  2. HTTPS URL validation (currently missing)
  3. Maximum length validation
  4. Special characters in URLs
  5. Edge cases (localhost, internal addresses)

These cases are essential for ensuring robust CRL distribution point validation in a production environment.

Here's an additional test case to validate HTTPS requirement:

 tests := []struct {
     name    string
     args    args
     wantErr bool
 }{
+    {
+        name: "non-https external address",
+        args: args{
+            cfg: func() service.HTTPConfig {
+                cfg := test.MakeHTTPConfig()
+                cfg.ExternalAddress = "http://example.com/crl"
+                return cfg
+            }(),
+        },
+        wantErr: true,
+    },
+    {
+        name: "external address exceeds maximum length",
+        args: args{
+            cfg: func() service.HTTPConfig {
+                cfg := test.MakeHTTPConfig()
+                cfg.ExternalAddress = "https://" + strings.Repeat("a", 2048) + ".com/crl"
+                return cfg
+            }(),
+        },
+        wantErr: true,
+    }
 }
certificate-authority/store/revocationList_test.go (1)

1-201: Well-structured test implementation with good coverage.

The test file follows Go testing best practices:

  • Table-driven tests with clear test cases
  • Fixed timestamps for reliable testing
  • Proper error handling and assertions
  • Clear separation of concerns between different test functions
certificate-authority/service/grpc/signer.go (3)

49-55: LGTM: Well-implemented issuer ID generation.

The getIssuerID function generates a deterministic UUID based on the public key, ensuring consistent and unique issuer identification.


166-190: LGTM: Well-structured signing implementation.

The signing logic is well-organized with:

  • Proper reuse through the common sign method
  • Correct handling of CRL distribution points
  • Good error propagation

63-66: ⚠️ Potential issue

Fix: Handle time parsing error.

The error from tparse.ParseNow is still being ignored. This could lead to unexpected behavior if the time string is invalid.

Apply this diff to handle the error:

 validFrom: func() time.Time {
-    t, _ := tparse.ParseNow(time.RFC3339, signerConfig.ValidFrom)
+    t, err := tparse.ParseNow(time.RFC3339, signerConfig.ValidFrom)
+    if err != nil {
+        return time.Now() // Fallback to current time
+    }
     return t
 },

Likely invalid or redundant comment.

certificate-authority/service/grpc/signCertificate.go (1)

29-29: LGTM! Function signature and credential fields updated correctly.

The changes properly integrate the new serial and issuerId fields into the signing record creation process.

Also applies to: 57-58

certificate-authority/service/grpc/signCertificate_test.go (3)

13-19: LGTM: Package migration looks good

The migration from kitNetGrpc to pkgGrpc is consistently applied across the file, including the context token setup.

Also applies to: 73-73, 138-138


94-106: Well-structured refactor of CSR creation functions

The split into createCSRWithKey and createCSR improves code reusability and enables testing of key reuse scenarios, which is important for certificate management and revocation testing.


153-197: Verify error type for device ID reuse with different key

The test correctly verifies that using the same device ID with a different key is rejected. Consider adding an error type verification to ensure the specific error condition.

-	require.Error(t, err)
+	require.ErrorIs(t, err, expectedError)
+	require.Contains(t, err.Error(), "device ID already registered with different key")
certificate-authority/store/mongodb/revocationList.go (3)

50-110: LGTM! Secure implementation with proper input validation

The implementation correctly:

  • Validates user input using cert.Validate()
  • Uses parameterized queries to prevent injection
  • Handles duplicate certificates appropriately

183-225: LGTM! Well-implemented retrieval with proper filtering

The implementation effectively:

  • Validates issuerID format
  • Uses MongoDB's aggregation for efficient filtering
  • Handles errors appropriately
🧰 Tools
🪛 GitHub Check: CodeQL

[failure] 217-217: Database query built from user-controlled sources
This query depends on a user-provided value.


124-126: ⚠️ Potential issue

Add nil check before returning originalRevocationList

When needsUpdate is false, the method returns upd.originalRevocationList without checking if it's nil.

Add a nil check to prevent potential panic:

 if !needsUpdate {
+    if upd.originalRevocationList == nil {
+        return nil, fmt.Errorf("original revocation list is nil")
+    }
     return upd.originalRevocationList, nil
 }

Likely invalid or redundant comment.

certificate-authority/store/cqldb/signingRecords.go (1)

368-374: ⚠️ Potential issue

Critical: Implement proper certificate revocation mechanism.

The current implementation deletes records instead of implementing proper certificate revocation. This approach has significant security implications as previously noted in the past review comment.

This is a critical security concern as:

  1. It violates RFC 5280 requirements for certificate revocation
  2. It prevents maintaining an audit trail of revoked certificates
  3. It makes it impossible to query the revocation status of previously issued certificates

Let's verify if there are any other components relying on certificate revocation status:

#!/bin/bash
# Search for code that checks certificate revocation status
rg -g '!{vendor,.*pb.go}' -A 3 'revocation|revoked|CRL|OCSP'

Would you like me to create a high-priority security issue to track the implementation of proper certificate revocation?

certificate-authority/store/mongodb/signingRecords_test.go (2)

100-103: LGTM! Simplified error handling.

The error handling has been improved by removing redundant checks and using an early return pattern, which makes the code more concise while maintaining the same behavior.


302-304: Verify the impact of handler interface changes.

The handler interface has been simplified by removing the iteration logic, but this change might affect other parts of the codebase that depend on this interface.

Let's verify the usage of this interface:

device-provisioning-service/service/provisionFail_test.go (1)

314-314: LGTM! The change improves test reliability.

Setting ExpiresIn = time.Second instead of 0 provides a more realistic test scenario by allowing the certificate to transition from valid to expired state, better simulating real-world certificate expiration behavior.

certificate-authority/pb/doc.html (4)

349-349: LGTM! Clear and accurate method descriptions.

The updated descriptions for GetSigningRecords and DeleteSigningRecords methods accurately reflect their functionality.

Also applies to: 356-356


386-391: Dual HTTP bindings already documented.

The addition of /certificate-authority prefixed endpoints is consistent with the existing documentation requirements.

Also applies to: 403-409, 420-426, 437-443


494-511: LGTM! Well-documented new fields.

The new serial and issuer_id fields in CredentialStatus are properly documented with:

  • Clear descriptions of their purpose
  • Proper bson tags
  • Detailed explanation of the issuer_id computation formula

551-551: LGTM! Consistent description.

The description update for DeletedSigningRecords aligns with the DeleteSigningRecords method functionality.

certificate-authority/service/http/revocationList.go (4)

73-73: ⚠️ Potential issue

Correct the misspelling in method name GetCRLConfiguation

There is a typo in the method name GetCRLConfiguation(). It should be GetCRLConfiguration().

Apply this diff to fix the typo:

-	_, validFor := signer.GetCRLConfiguation()
+	_, validFor := signer.GetCRLConfiguration()

Likely invalid or redundant comment.


74-75: 🛠️ Refactor suggestion

Make retry count configurable instead of hardcoded

The retry count tries is currently hardcoded to 3. To enhance flexibility and maintainability, consider making it configurable through application settings.

Apply this diff to load tries from configuration:

 // TODO: make configurable
-const tries = 3
+tries := requestHandler.config.RetryCount

Please ensure that RetryCount is added to your configuration struct and properly initialized. Would you like assistance in updating the configuration to include this parameter?

Likely invalid or redundant comment.


69-70: ⚠️ Potential issue

Return a BadRequest error for invalid issuer IDs

Currently, if the issuerID is invalid, the error is returned directly, which may result in an internal server error being sent to the client. Instead, return a BadRequest error to indicate that the client provided invalid input.

Apply this diff to return a BadRequest error:

 if _, err := uuid.Parse(issuerID); err != nil {
-	return err
+	return pkgHttp.BadRequest("%v: invalid issuer ID", err)
 }

Likely invalid or redundant comment.


27-50: ⚠️ Potential issue

Add input validation to prevent nil pointer dereferences

The createCRL function does not check if the input parameters rl, issuer, or priv are nil. This could lead to nil pointer dereferences and potential panics if any of these inputs are nil. Adding input validation at the beginning of the function enhances robustness.

Apply this diff to add input validation:

 func createCRL(rl *store.RevocationList, issuer *x509.Certificate, priv crypto.Signer) ([]byte, error) {
+	if rl == nil || issuer == nil || priv == nil {
+		return nil, errors.New("invalid input: revocation list, issuer certificate, and private key must not be nil")
+	}
 	number, err := store.ParseBigInt(rl.Number)
 	if err != nil {
 		return nil, err

Likely invalid or redundant comment.

certificate-authority/service/http/revocationList_test.go (1)

159-173: Good job adding the 'expired' test case

The test case for the expired revocation list is now implemented, ensuring the endpoint correctly handles expired lists.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (6)
pkg/security/certificateSigner/identityCertificateSigner.go (2)

Line range hint 11-28: Fix incomplete error handling in NewIdentityCertificateSigner

The function signature has been updated to return an error, but it's not properly handling potential errors from the New() function call. This could mask critical errors during certificate signing operations.

Apply this fix to properly propagate errors:

 func NewIdentityCertificateSigner(caCert []*x509.Certificate, caKey crypto.PrivateKey, opts ...Opt) (*CertificateSigner, error) {
        var cfg SignerConfig
        for _, o := range opts {
                o(&cfg)
        }
        overrideCertTemplate := func(template *x509.Certificate) error {
                template.UnknownExtKeyUsage = []asn1.ObjectIdentifier{ExtendedKeyUsage_IDENTITY_CERTIFICATE}
                template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyAgreement
                template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
                if cfg.OverrideCertTemplate != nil {
                        return cfg.OverrideCertTemplate(template)
                }
                return nil
        }
        opts = append(opts, WithOverrideCertTemplate(overrideCertTemplate))
-       return New(caCert, caKey, opts...)
+       signer, err := New(caCert, caKey, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return signer, nil
 }

Error handling needs to be updated in test/sdk/client.go

The function signature change in NewIdentityCertificateSigner requires updates to error handling in its callers. Found one caller that ignores the error:

  • test/sdk/client.go: Uses signer, _ := certificateSigner.NewIdentityCertificateSigner(...) which discards the error

Other callers properly handle the error:

  • pkg/security/certificateSigner/identityCertificateSigner_test.go: Properly checks error with require.NoError(t, err)
  • certificate-authority/service/grpc/signer.go: Returns the error through function return
🔗 Analysis chain

Line range hint 11-28: Verify the impact of error handling changes

Since this is a public API change (adding error return), we should verify all callers of this function have been updated to handle the error.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for all calls to NewIdentityCertificateSigner to verify error handling
rg -A 2 "NewIdentityCertificateSigner\(" --type go

Length of output: 2173


Script:

#!/bin/bash
# Let's try a different approach to find usages of NewIdentityCertificateSigner
# First, let's use ast-grep to find function calls
ast-grep --pattern 'NewIdentityCertificateSigner($$$)'

# Also search with ripgrep using word boundaries to be more precise
rg '\bNewIdentityCertificateSigner\b' --type go -A 3

Length of output: 2690

pkg/security/certificateSigner/certificateSigner_test.go (1)

24-24: Consider reducing the test certificate validity period.

The current validity period of 86400 hours (≈10 years) is quite long for test certificates. Consider using a shorter duration (e.g., 24-48 hours) to better align with testing purposes and security best practices.

-	signer, err := New(identityIntermediateCA, identityIntermediateCAKey, WithNotBefore(time.Now()), WithNotAfter(time.Now().Add(time.Hour*86400)))
+	signer, err := New(identityIntermediateCA, identityIntermediateCAKey, WithNotBefore(time.Now()), WithNotAfter(time.Now().Add(time.Hour*24)))
certificate-authority/service/grpc/signer.go (1)

166-193: Enhance error handling in the sign method.

The error from signer.Sign is returned directly without context. Consider wrapping errors with additional context to help with debugging.

Apply this diff:

     cert, err := signer.Sign(ctx, csr)
     if err != nil {
-        return nil, nil, err
+        return nil, nil, fmt.Errorf("failed to sign certificate: %w", err)
     }
certificate-authority/service/http/revocationList.go (2)

73-73: Correct the misspelling in method name GetCRLConfiguration.

There's a typo in the method name GetCRLConfiguration(). Ensuring correct spelling improves code readability and maintains consistency.

Apply this diff to fix the typo:

 	signer := requestHandler.cas.GetSigner()
-	_, validFor := signer.GetCRLConfiguration()
+	_, validFor := signer.GetCRLConfiguration()

89-93: Consider logging errors for better observability.

In the revocationList handler, errors are sent to the client but not logged. Logging errors can help in monitoring and debugging.

Apply this diff to add error logging:

 func (requestHandler *requestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
 	if err := requestHandler.writeRevocationList(w, r); err != nil {
+		requestHandler.logger.Errorf("Failed to write revocation list: %v", err)
 		serverMux.WriteError(w, errCannotGetRevocationList(err))
 	}
 }

Ensure that requestHandler has a logger field initialized.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between c19ad81 and d2afb59.

📒 Files selected for processing (8)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (1 hunks)
  • test/sdk/client.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • certificate-authority/service/http/revocationList_test.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🔇 Additional comments (15)
pkg/security/certificateSigner/identityCertificateSigner.go (1)

Line range hint 16-20: Verify security implications of certificate template overrides

The function allows overriding certificate templates through cfg.OverrideCertTemplate. While this provides flexibility, it could potentially allow overriding critical security parameters. Consider:

  1. Adding validation to prevent weakening of key usage flags
  2. Documenting security requirements for template overrides
#!/bin/bash
# Search for all template override implementations to verify security
rg "WithOverrideCertTemplate\(" --type go -A 10
pkg/security/certificateSigner/certificateSigner_test.go (2)

24-26: LGTM! Error handling properly implemented.

The addition of error handling for the New() function call improves the robustness of the test helper.


Line range hint 29-89: Consider adding CRL-specific test cases.

Since this PR implements Certificate Revocation List functionality, consider adding test cases that verify:

  1. CRL distribution points in the issued certificates
  2. Certificate revocation status checking
  3. Error cases for revoked certificates

This will ensure the new CRL functionality is properly tested.

pkg/security/certificateSigner/certificateSigner.go (4)

20-24: LGTM! Well-structured SignerConfig.

The SignerConfig struct is well-organized with logical grouping of fields. The new CRLDistributionPoints field is appropriately typed as []string for storing distribution point URLs.


67-77: LGTM! Robust constructor with validation.

The constructor now properly validates the configuration before creating the signer instance. The error handling is well-implemented, and the changes maintain backward compatibility.


Line range hint 80-96: LGTM! Well-structured CSR parsing.

The helper function properly handles PEM decoding, CSR parsing, and signature validation with clear error messages.


Line range hint 98-142: Consider validating certificate extensions.

While the Sign method is well-implemented, consider adding validation for certificate extensions to prevent potential security issues with malicious or incorrect extensions in the CSR.

 func (s *CertificateSigner) Sign(_ context.Context, csr []byte) ([]byte, error) {
     // ... existing code ...
     parsedCSR, err := parseCertificateRequest(csr)
     if err != nil {
         return nil, err
     }
+    // Validate extensions
+    for _, ext := range parsedCSR.Extensions {
+        // Check for critical extensions that we don't support
+        if ext.Critical {
+            if !isSupportedCriticalExtension(ext.Id) {
+                return nil, fmt.Errorf("unsupported critical extension: %v", ext.Id)
+            }
+        }
+    }
     // ... rest of the code ...
 }

+func isSupportedCriticalExtension(oid []int) bool {
+    // Add OIDs of supported critical extensions
+    supportedOIDs := [][]int{
+        {2, 5, 29, 15}, // Key Usage
+        {2, 5, 29, 19}, // Basic Constraints
+        // Add other supported critical extensions
+    }
+    for _, supported := range supportedOIDs {
+        if slices.Equal(oid, supported) {
+            return true
+        }
+    }
+    return false
+}
certificate-authority/service/grpc/signer.go (1)

49-55: Consider using a stronger hash algorithm for UUID generation.

The function uses SHA1 for UUID generation which is cryptographically weak. While this might be acceptable for generating unique identifiers, consider using a stronger algorithm like SHA256 for better security.

Let's check if SHA1 is used elsewhere in the codebase for similar purposes:

certificate-authority/service/http/revocationList.go (7)

69-70: ⚠️ Potential issue

Return a BadRequest error for invalid UUIDs.

When uuid.Parse(issuerID) fails, returning the parsing error directly may result in an internal server error response. Instead, return a BadRequest error to inform the client that the input was invalid.

Apply this diff to improve error handling:

 	issuerID := vars[uri.IssuerIDKey]
 	if _, err := uuid.Parse(issuerID); err != nil {
-		return err
+		return pkgHttp.BadRequest("invalid issuer ID: %v", err)
 	}

Likely invalid or redundant comment.


74-75: 🛠️ Refactor suggestion

Make retry count configurable via application settings.

The retry count tries is currently hardcoded to 3. For better flexibility and maintainability, consider making it configurable through application configuration.

Apply this diff to use a configurable retry count:

-	// TODO: make configurable
-	const tries = 3
+	tries := requestHandler.config.RetryCount // Assume RetryCount is defined in the configuration

Ensure that RetryCount is added to your configuration struct and properly initialized.

Likely invalid or redundant comment.


66-67: ⚠️ Potential issue

Validate HTTP method to enhance security and correctness.

The writeRevocationList function should validate that the request uses the GET method. This ensures that clients cannot use unintended HTTP methods, which could lead to improper use of the endpoint.

Apply this diff to add method validation:

 func (requestHandler *requestHandler) writeRevocationList(w http.ResponseWriter, r *http.Request) error {
+	if r.Method != http.MethodGet {
+		return pkgHttp.BadRequest("method not allowed")
+	}
 	vars := mux.Vars(r)

Likely invalid or redundant comment.


84-85: 🛠️ Refactor suggestion

Add security and caching headers to the HTTP response.

Including security headers like X-Content-Type-Options and X-Frame-Options improves the security posture of your application. Additionally, setting caching headers can optimize client performance.

Apply this diff to set the headers:

 w.Header().Set(pkgHttp.ContentTypeHeaderKey, "application/pkix-crl")
+// Set security headers
+w.Header().Set("X-Content-Type-Options", "nosniff")
+w.Header().Set("X-Frame-Options", "DENY")
+// Set caching headers
+w.Header().Set("Cache-Control", "public, max-age=3600")
+// Optionally, set ETag for caching
+crlHash := sha256.Sum256(crl)
+w.Header().Set("ETag", fmt.Sprintf(`"%x"`, crlHash))
 _, err = w.Write(crl)

Don't forget to import necessary packages:

 import (
 	"context"
+	"crypto/sha256"
+	"fmt"
 )

Likely invalid or redundant comment.


23-25: 🛠️ Refactor suggestion

Consider using more specific gRPC error codes.

Currently, errCannotGetRevocationList returns a generic codes.Internal error for all cases. To provide better error handling and clarity to the client, map specific errors to more appropriate gRPC codes. For example:

  • store.ErrNotFoundcodes.NotFound
  • Validation errors (e.g., invalid input) → codes.InvalidArgument

Apply this diff to improve error specificity:

 func errCannotGetRevocationList(err error) error {
-	return pkgGrpc.ForwardErrorf(codes.Internal, "cannot get revocation list: %v", err)
+	if errors.Is(err, store.ErrNotFound) {
+		return pkgGrpc.ForwardErrorf(codes.NotFound, "revocation list not found: %v", err)
+	}
+	// Handle other specific errors here (e.g., validation errors)
+	return pkgGrpc.ForwardErrorf(codes.Internal, "cannot get revocation list: %v", err)
 }

Likely invalid or redundant comment.


27-50: ⚠️ Potential issue

Add input validation to prevent potential nil pointer dereferences.

The createCRL function does not check if rl, issuer, or priv are nil. This could lead to nil pointer dereferences and runtime panics. Adding input validation ensures the function handles invalid inputs gracefully.

Apply this diff to add input validation:

 func createCRL(rl *store.RevocationList, issuer *x509.Certificate, priv crypto.Signer) ([]byte, error) {
+	if rl == nil || issuer == nil || priv == nil {
+		return nil, errors.New("invalid input: revocation list, issuer certificate, and private key must not be nil")
+	}
 	number, err := store.ParseBigInt(rl.Number)
 	if err != nil {
 		return nil, err
 	}

Likely invalid or redundant comment.


52-64: 🛠️ Refactor suggestion

Enhance retry mechanism with context cancellation and exponential backoff.

The current retry loop in tryGetRevocationList does not respect context cancellation and lacks delay between retries. Implementing context checks and exponential backoff improves responsiveness and avoids unnecessary load.

Apply this diff to enhance the retry mechanism:

 func (requestHandler *requestHandler) tryGetRevocationList(ctx context.Context, issuerID string, validFor time.Duration, tries int) (*store.RevocationList, error) {
+	if ctx.Err() != nil {
+		return nil, ctx.Err()
+	}
+	baseDelay := 100 * time.Millisecond
 	for i := 0; i < tries; i++ {
+		if ctx.Err() != nil {
+			return nil, ctx.Err()
+		}
 		rl, err := requestHandler.store.GetLatestIssuedOrIssueRevocationList(ctx, issuerID, validFor)
 		if err == nil {
 			return rl, nil
 		}
 		if errors.Is(err, store.ErrNotFound) {
+			// Exponential backoff with jitter
+			delay := time.Duration(float64(baseDelay) * math.Pow(2, float64(i)))
+			timer := time.NewTimer(delay + time.Duration(rand.Int63n(int64(delay/2))))
+			select {
+			case <-ctx.Done():
+				timer.Stop()
+				return nil, ctx.Err()
+			case <-timer.C:
+			}
 			continue
 		}
 		return nil, err
 	}
 	return nil, store.ErrNotFound
 }

Don't forget to include necessary imports:

 import (
 	"context"
+	"math"
+	"math/rand"
 )

Likely invalid or redundant comment.

pkg/security/certificateSigner/certificateSigner.go Outdated Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Outdated Show resolved Hide resolved
test/sdk/client.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (8)
certificate-authority/store/cqldb/revocationList.go (2)

10-28: Add documentation explaining unsupported functionality.

While the implementation is consistent in indicating that revocation list operations are not supported in the CQL database store, it would be beneficial to add documentation explaining this design decision. This helps other developers understand whether this is a temporary limitation or a permanent architectural choice.

Consider adding a package-level comment like:

 package cqldb

+// RevocationList operations are not supported in the CQL database implementation.
+// For revocation list functionality, please use the MongoDB implementation instead.
+
 import (

10-12: Consider implementing feature detection at service initialization.

Since different storage implementations have varying levels of feature support (MongoDB supports revocation lists while CQL doesn't), consider implementing a feature detection mechanism at service initialization. This would allow early detection of missing required features and prevent runtime surprises.

Example approach:

  1. Define required features at service configuration
  2. Validate storage implementation support during initialization
  3. Fail fast if required features are not supported by the chosen storage implementation
pkg/security/certificateSigner/certificateSigner.go (1)

Line range hint 101-145: Consider validating CRLDistributionPoints before use.

While the implementation is solid, consider adding a validation check for empty CRL distribution points before adding them to the template. This could prevent creating certificates with empty CRL distribution points if that's not intended.

 func (s *CertificateSigner) Sign(_ context.Context, csr []byte) ([]byte, error) {
     // ... existing code ...
+    if len(s.cfg.CRLDistributionPoints) == 0 {
+        return nil, errors.New("CRL distribution points cannot be empty")
+    }
     template := x509.Certificate{
         // ... existing fields ...
         CRLDistributionPoints: s.cfg.CRLDistributionPoints,
     }
certificate-authority/service/grpc/server.go (2)

34-46: Add validation for crlServerAddress parameter

While the changes look good, consider adding validation for the crlServerAddress parameter to ensure it's not empty and follows a valid URL format. This will prevent potential runtime issues.

 func NewCertificateAuthorityServer(ownerClaim, hubID, crlServerAddress string, signerConfig SignerConfig, store store.Store, fileWatcher *fsnotify.Watcher, logger log.Logger) (*CertificateAuthorityServer, error) {
+	if crlServerAddress == "" {
+		return nil, fmt.Errorf("crlServerAddress cannot be empty")
+	}
+	if _, err := url.Parse(crlServerAddress); err != nil {
+		return nil, fmt.Errorf("invalid crlServerAddress format: %w", err)
+	}
 	if err := signerConfig.Validate(); err != nil {
 		return nil, err
 	}

Line range hint 34-106: Consider additional security measures for CRL implementation

While the basic CRL infrastructure is in place, consider these security enhancements:

  1. Implement rate limiting for CRL operations
  2. Add logging for CRL-related operations for audit purposes
  3. Consider implementing a health check for the CRL server
  4. Add metrics for monitoring CRL operations

Would you like me to provide implementation details for any of these suggestions?

certificate-authority/service/grpc/signer.go (1)

170-197: Add trace logging for better observability.

The sign method performs several critical operations that would benefit from trace logging for debugging and monitoring purposes.

Consider adding trace logging at key points:

 func (s *Signer) sign(ctx context.Context, isIdentityCertificate bool, csr []byte) ([]byte, *pb.SigningRecord, error) {
+    logger := log.FromContext(ctx)
+    logger.Debug("starting certificate signing process",
+        "identity_certificate", isIdentityCertificate,
+        "csr_size", len(csr))
     notBefore := s.validFrom()
     notAfter := notBefore.Add(s.validFor)
     var signingRecord *pb.SigningRecord
     opts := []certificateSigner.Opt{
         certificateSigner.WithNotBefore(notBefore),
         certificateSigner.WithNotAfter(notAfter),
         certificateSigner.WithOverrideCertTemplate(func(template *x509.Certificate) error {
             var err error
             signingRecord, err = s.prepareSigningRecord(ctx, template)
+            if err != nil {
+                logger.Error("failed to prepare signing record", "error", err)
+            }
             return err
         }),
     }
     if s.IsCRLEnabled() {
+        logger.Debug("adding CRL distribution points to certificate")
         opts = append(opts, certificateSigner.WithCRLDistributionPoints(
             []string{path.Join(s.crl.serverAddress, uri.SigningRevocationListBase, s.issuerID)},
         ))
     }
     signer, err := s.newCertificateSigner(isIdentityCertificate, opts...)
     if err != nil {
+        logger.Error("failed to create certificate signer", "error", err)
         return nil, nil, err
     }
     cert, err := signer.Sign(ctx, csr)
     if err != nil {
+        logger.Error("failed to sign certificate", "error", err)
         return nil, nil, err
     }
+    logger.Debug("certificate signed successfully",
+        "cert_size", len(cert))
     return cert, signingRecord, nil
 }
certificate-authority/service/http/revocationList.go (2)

86-90: Add logging for error handling

In the revocationList handler, errors are written to the client, but there is no logging of the error details. Adding logging helps with debugging and monitoring.

Apply this diff to log errors:

 func (requestHandler *requestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
     if err := requestHandler.writeRevocationList(w, r); err != nil {
+        requestHandler.logger.Errorf("Failed to write revocation list: %v", err)
         serverMux.WriteError(w, errCannotGetRevocationList(err))
     }
 }

Ensure that the requestHandler has access to a logger.


86-90: Rename handler method for clarity and consistency

The method name revocationList may be confusing, as it doesn't clearly indicate that it's an HTTP handler. For better readability and consistency, consider renaming it to handleRevocationList.

Apply this diff to rename the method:

-func (requestHandler *requestHandler) revocationList(w http.ResponseWriter, r *http.Request) {
+func (requestHandler *requestHandler) handleRevocationList(w http.ResponseWriter, r *http.Request) {
     if err := requestHandler.writeRevocationList(w, r); err != nil {
         serverMux.WriteError(w, errCannotGetRevocationList(err))
     }
 }

Ensure all references to this method are updated accordingly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d2afb59 and e89a1a4.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (13)
  • certificate-authority/service/grpc/server.go (5 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (1 hunks)
  • test/sdk/client.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • certificate-authority/service/grpc/signCertificate.go
  • certificate-authority/service/http/revocationList_test.go
  • certificate-authority/store/store.go
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🔇 Additional comments (16)
certificate-authority/store/cqldb/revocationList.go (1)

1-9: LGTM! Clean package structure and imports.

The package organization follows Go best practices with appropriate imports.

certificate-authority/store/revocationList.go (1)

69-85: ⚠️ Potential issue

Add nil check for Certificates slice.

The Validate method should ensure the Certificates slice is initialized before iterating over it to prevent potential panic.

 func (rl *RevocationList) Validate() error {
     if _, err := uuid.Parse(rl.Id); err != nil {
         return fmt.Errorf("invalid ID(%v): %w", rl.Id, err)
     }
     if (rl.IssuedAt == 0 && rl.ValidUntil != 0) || (rl.ValidUntil < rl.IssuedAt) {
         return fmt.Errorf("invalid validity period timestamps(from %v to %v)", rl.IssuedAt, rl.ValidUntil)
     }
     if _, err := ParseBigInt(rl.Number); err != nil {
         return err
     }
+    if rl.Certificates == nil {
+        rl.Certificates = make([]*RevocationListCertificate, 0)
+    }
     for _, c := range rl.Certificates {
         if err := c.Validate(); err != nil {
             return err
         }
     }
     return nil
 }

Likely invalid or redundant comment.

pkg/security/certificateSigner/certificateSigner.go (5)

11-24: LGTM! Well-structured configuration type.

The SignerConfig struct is well-organized with appropriate field types for managing certificate validity periods, CRL distribution points, and template customization.


26-35: LGTM! Comprehensive validation implementation.

The validation method properly checks both temporal constraints and CRL distribution points, with clear error messages.


52-56: LGTM! Secure implementation with proper defensive copying.

The implementation correctly uses slices.Clone to prevent external modifications to the internal state.


70-80: LGTM! Robust constructor with proper validation.

The constructor now includes config validation and appropriate error handling, with sensible defaults.


Line range hint 83-99: LGTM! Well-structured CSR parsing with proper validation.

The helper function properly handles PEM decoding, CSR parsing, and signature validation with appropriate error handling.

certificate-authority/service/grpc/server.go (2)

5-8: LGTM: Clean addition of CRL server address field

The new field and imports are appropriate for implementing CRL functionality.

Also applies to: 29-29


Line range hint 130-141: Verify error handling in NewSigner implementation

The changes look good, but let's verify that the NewSigner implementation properly handles the crlServerAddress parameter.

✅ Verification successful

Let me check the newSigner function to ensure proper handling of crlServerAddress.


Let me try a different pattern to find the newSigner implementation.


Error handling for crlServerAddress is properly implemented

The verification shows that crlServerAddress is properly validated:

  • In NewSigner, the parameter is correctly passed through to newSigner
  • In newSigner, there's explicit validation of the CRL server address when CRL is enabled using pkgX509.ValidateCRLDistributionPointAddress
  • The validation error is properly propagated back to the caller
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check NewSigner implementation for proper error handling of crlServerAddress
ast-grep --pattern 'func NewSigner($_, $_, crlServerAddress string, $_) ($_, error) {
  $$$
}'

Length of output: 3709


Script:

#!/bin/bash
# Check newSigner implementation for proper handling of crlServerAddress
ast-grep --pattern 'func newSigner($_, $_, crlServerAddress string, $_) ($_, error) {
  $$$
}'

Length of output: 96


Script:

#!/bin/bash
# Search for newSigner function with ripgrep for better pattern matching
rg "func newSigner" -A 20

Length of output: 1670

test/sdk/client.go (1)

173-175: LGTM! Error handling has been improved.

The changes properly address error propagation from NewIdentityCertificateSigner and align with the interface requirements. The unused parameter []string is correctly marked with _ to indicate it's intentionally ignored.

Let's verify the interface alignment:

✅ Verification successful

Based on the search results, I can now generate the final response:

The CreateSignerFunc implementation correctly aligns with its usage and interface requirements.

The implementation properly:

  • Returns the expected core.CertificateSigner interface and error types
  • Uses the certificateSigner.NewIdentityCertificateSigner with appropriate parameters
  • Correctly ignores the unused []string parameter with _
  • Properly propagates any potential errors from NewIdentityCertificateSigner
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the CreateSignerFunc signature matches the interface definition
# and find any other implementations for reference

# Search for the interface definition and other implementations
rg "type.*CreateSignerFunc" -B 2 -A 2
rg "CreateSignerFunc.*func.*CertificateSigner" -A 3

Length of output: 543


Script:

#!/bin/bash
# Let's search for the interface definition and type declarations
ast-grep --pattern 'type $_ interface {
  $$$
}'

# Also search for any CreateSigner related function signatures
rg "func.*CreateSigner" -A 2

Length of output: 75290


Script:

#!/bin/bash
# Let's search for CreateSigner related code and interfaces
rg "type.*CreateSigner" -A 3
rg "CreateSigner.*interface" -A 3

Length of output: 66


Script:

#!/bin/bash
# Let's search for the core.CertificateSigner type and any related interfaces
rg "CertificateSigner" -A 3 -B 3

# Also search for any files containing CreateSigner in their name
fd "CreateSigner"

Length of output: 11800

certificate-authority/service/http/revocationList.go (6)

68-69: ⚠️ Potential issue

Return a BadRequest error for invalid issuer IDs

Currently, when the issuerID fails to parse as a UUID, the function returns the parsing error directly. This may result in a generic internal server error response to the client. Instead, return a BadRequest error to indicate that the client provided an invalid issuer ID.

Apply this diff to return a more appropriate error:

 issuerID := vars[uri.IssuerIDKey]
 if _, err := uuid.Parse(issuerID); err != nil {
-    return err
+    return pkgHttp.BadRequest("invalid issuer ID: %v", err)
 }

Likely invalid or redundant comment.


65-66: ⚠️ Potential issue

Add HTTP method validation for enhanced security

The writeRevocationList function does not validate the HTTP method. To ensure that only GET requests are accepted, add a check for the request method.

Apply this diff to validate the HTTP method:

 func (requestHandler *requestHandler) writeRevocationList(w http.ResponseWriter, r *http.Request) error {
+    if r.Method != http.MethodGet {
+        return pkgHttp.BadRequest("method not allowed")
+    }
     vars := mux.Vars(r)

Likely invalid or redundant comment.


77-80: ⚠️ Potential issue

Handle potential nil values returned from createCRL

After calling createCRL, check if crl is nil before writing it to the response. This prevents potential nil pointer dereferences.

Apply this diff to add a nil check:

 crl, err := createCRL(rl, signer.GetCertificate(), signer.GetPrivateKey())
 if err != nil {
     return err
 }
+if crl == nil {
+    return errors.New("generated CRL is nil")
+}

Likely invalid or redundant comment.


23-25: ⚠️ Potential issue

Consider using more specific gRPC error codes

The errCannotGetRevocationList function currently maps all errors to codes.Internal. For better error handling and client feedback, map different error scenarios to more appropriate gRPC error codes:

  • Return codes.NotFound when the revocation list is not found.
  • Return codes.InvalidArgument for validation or parsing errors.
  • Keep codes.Internal for unexpected internal errors.

Apply this diff to enhance error code specificity:

 func errCannotGetRevocationList(err error) error {
+    if errors.Is(err, store.ErrNotFound) {
+        return pkgGrpc.ForwardErrorf(codes.NotFound, "revocation list not found: %v", err)
+    }
+    if _, ok := err.(*uuid.ParseError); ok {
+        return pkgGrpc.ForwardErrorf(codes.InvalidArgument, "invalid issuer ID: %v", err)
+    }
     return pkgGrpc.ForwardErrorf(codes.Internal, "cannot get revocation list: %v", err)
 }

Likely invalid or redundant comment.


81-82: ⚠️ Potential issue

Set security and caching headers in the HTTP response

Currently, the response lacks security headers and caching directives, which are important for security and performance best practices. Add appropriate headers to the response.

Apply this diff to set the headers:

 w.Header().Set(pkgHttp.ContentTypeHeaderKey, "application/pkix-crl")
+// Set security headers
+w.Header().Set("X-Content-Type-Options", "nosniff")
+w.Header().Set("X-Frame-Options", "DENY")
+// Set caching headers
+w.Header().Set("Cache-Control", "public, max-age=3600")
+// Optionally, set ETag for caching
+crlHash := sha256.Sum256(crl)
+w.Header().Set("ETag", fmt.Sprintf(`"%x"`, crlHash))
 _, err = w.Write(crl)

Ensure you import the necessary packages:

 import (
     "context"
+    "crypto/sha256"
+    "fmt"
 )

Likely invalid or redundant comment.


27-50: ⚠️ Potential issue

Add input validation to prevent potential nil pointer dereferences

In the createCRL function, the input parameters rl, issuer, and priv are not checked for nil values. This could lead to nil pointer dereferences if any of these parameters are nil. Adding input validation at the beginning of the function ensures robustness.

Apply this diff to add input validation:

 func createCRL(rl *store.RevocationList, issuer *x509.Certificate, priv crypto.Signer) ([]byte, error) {
+    if rl == nil || issuer == nil || priv == nil {
+        return nil, errors.New("invalid input: revocation list, issuer certificate, and private key must not be nil")
+    }
     number, err := store.ParseBigInt(rl.Number)
     if err != nil {
         return nil, err

Likely invalid or redundant comment.

certificate-authority/store/revocationList.go Outdated Show resolved Hide resolved
certificate-authority/store/revocationList.go Show resolved Hide resolved
certificate-authority/service/grpc/server.go Show resolved Hide resolved
certificate-authority/service/grpc/signer.go Show resolved Hide resolved
certificate-authority/service/http/revocationList.go Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (7)
pkg/security/certificateSigner/certificateSigner.go (1)

Line range hint 83-99: Consider additional CSR validation checks.

While the current implementation handles basic CSR validation, consider adding checks for key usage and extended key usage to ensure the certificate request aligns with its intended purpose.

 func parseCertificateRequest(csr []byte) (*x509.CertificateRequest, error) {
     // ... existing code ...
     
     err = certificateRequest.CheckSignature()
     if err != nil {
         return nil, err
     }
+    
+    // Validate requested key usage
+    if len(certificateRequest.Extensions) > 0 {
+        for _, ext := range certificateRequest.Extensions {
+            if ext.Id.Equal(oidExtKeyUsage) {
+                if err := validateKeyUsage(ext.Value); err != nil {
+                    return nil, fmt.Errorf("invalid key usage: %w", err)
+                }
+            }
+        }
+    }
     
     return certificateRequest, nil
 }
certificate-authority/service/grpc/server.go (2)

90-106: Improve error handling specificity.

While the error handling covers the basic cases, it could be more specific about what failed during the revocation list insertion.

Consider enhancing the error message:

 		if err != nil {
-			return fmt.Errorf("failed to create revocation list: %w", err)
+			return fmt.Errorf("failed to create revocation list for issuer %s: %w", issuerID, err)
 		}

Line range hint 130-141: Consider resource cleanup and initialization order.

The current implementation has two potential issues:

  1. If initStore fails, the created signer isn't properly cleaned up
  2. The store initialization happens after signer creation, which might not be the optimal order

Consider this refactoring:

 func (s *CertificateAuthorityServer) load() (bool, error) {
+	if err := s.initStore(s.hubID); err != nil {
+		return false, fmt.Errorf("failed to initialize store: %w", err)
+	}
+
 	signer, err := NewSigner(s.ownerClaim, s.hubID, s.crlServerAddress, s.signerConfig)
 	if err != nil {
 		return false, fmt.Errorf("cannot create signer: %w", err)
 	}
+	defer func() {
+		if err != nil {
+			// Clean up signer if we fail after creation
+			signer.Close()
+		}
+	}()

 	oldSigner := s.signer.Load()
 	if oldSigner != nil && len(signer.certificate) == len(oldSigner.certificate) && bytes.Equal(signer.certificate[0].Raw, oldSigner.certificate[0].Raw) {
 		return false, nil
 	}
-	if err = s.initStore(signer.GetIssuerID()); err != nil {
-		return false, err
-	}
 	return s.signer.CompareAndSwap(oldSigner, signer), nil
 }
certificate-authority/service/grpc/signCertificate.go (1)

Line range hint 29-60: LGTM! Consider using time.UTC() for consistency.

The function implementation looks good with proper handling of the new issuerID parameter. However, consider using time.Now().UTC().UnixNano() to ensure consistent timestamp handling across different timezones.

- now := time.Now().UnixNano()
+ now := time.Now().UTC().UnixNano()
certificate-authority/service/grpc/signer.go (2)

Line range hint 84-127: Enhance error messages for certificate chain verification.

The error messages from certificate verification could be more descriptive to help diagnose issues in production.

 chains, err := pkgX509.Verify(certificate, certificateAuthorities, false, verifyOpts)
 if err != nil {
-    return nil, err
+    return nil, fmt.Errorf("failed to verify certificate chain: %w", err)
 }

170-197: Improve error handling in the signing process.

Consider adding context to errors returned from the signing process to help with debugging.

 cert, err := signer.Sign(ctx, csr)
 if err != nil {
-    return nil, nil, err
+    return nil, nil, fmt.Errorf("failed to sign certificate: %w", err)
 }
certificate-authority/service/http/revocationList_test.go (1)

95-98: Add explanation for CqlDB incompatibility.

The test is skipped for CqlDB without explaining why. Consider adding a comment explaining the limitation or technical reason for the incompatibility.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e89a1a4 and 9874eae.

⛔ Files ignored due to path filters (2)
  • go.mod is excluded by !**/*.mod
  • go.sum is excluded by !**/*.sum, !**/*.sum
📒 Files selected for processing (13)
  • certificate-authority/service/grpc/server.go (5 hunks)
  • certificate-authority/service/grpc/signCertificate.go (3 hunks)
  • certificate-authority/service/grpc/signer.go (6 hunks)
  • certificate-authority/service/http/revocationList.go (1 hunks)
  • certificate-authority/service/http/revocationList_test.go (1 hunks)
  • certificate-authority/store/cqldb/revocationList.go (1 hunks)
  • certificate-authority/store/revocationList.go (1 hunks)
  • certificate-authority/store/store.go (2 hunks)
  • pkg/security/certificateSigner/certificateSigner.go (5 hunks)
  • pkg/security/certificateSigner/certificateSigner_test.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner.go (1 hunks)
  • pkg/security/certificateSigner/identityCertificateSigner_test.go (1 hunks)
  • test/sdk/client.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • certificate-authority/store/cqldb/revocationList.go
  • certificate-authority/store/revocationList.go
  • certificate-authority/store/store.go
  • pkg/security/certificateSigner/certificateSigner_test.go
  • pkg/security/certificateSigner/identityCertificateSigner.go
  • pkg/security/certificateSigner/identityCertificateSigner_test.go
🔇 Additional comments (18)
pkg/security/certificateSigner/certificateSigner.go (5)

19-24: LGTM! Well-structured SignerConfig.

The new fields are appropriately typed and organized in a logical order.


26-35: LGTM! Comprehensive validation implementation.

The validation method properly checks both temporal constraints and CRL distribution points with clear error messages.


52-56: LGTM! Safe implementation of CRL distribution points.

The use of slices.Clone provides proper defensive copying.


70-80: LGTM! Robust constructor implementation.

The constructor properly initializes defaults, applies options, and validates the configuration.


Line range hint 101-145: LGTM! Well-implemented signing logic.

The Sign method properly validates inputs, constructs the certificate template with CRL distribution points, and handles errors appropriately.

Let's verify the CRL distribution points are properly propagated:

✅ Verification successful

Let me check one more thing to ensure the URL validation is properly implemented.


CRL distribution points implementation verified successfully

The CRL distribution points feature is properly implemented with:

  • Correct configuration in SignerConfig with validation
  • URL validation through ValidateCRLDistributionPointAddress ensuring absolute URLs
  • Consistent usage across certificate authority service and signer
  • Proper propagation to the certificate template during signing
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify CRL distribution points are used consistently
# Look for other places where CRL distribution points are used
rg -l "CRLDistributionPoints" --type go

Length of output: 136


Script:

#!/bin/bash
# Let's check how CRLDistributionPoints are used in both files
rg -A 5 -B 5 "CRLDistributionPoints" --type go

Length of output: 4510


Script:

#!/bin/bash
# Check the URL validation implementation
rg -A 5 "ValidateCRLDistributionPointAddress" --type go

Length of output: 1814

certificate-authority/service/grpc/server.go (1)

90-106: Verify thread safety of store operations.

The store operations need to be thread-safe as they might be called concurrently from different gRPC handlers.

✅ Verification successful

Let me analyze the store implementation further to verify thread safety.


Based on the analysis of the codebase, I can now provide a final response:

Thread safety is properly handled - no additional checks needed.

The store operations are thread-safe because:

  1. The MongoDB and CQL database drivers used by the store implementations handle concurrent access internally
  2. The store interface methods are stateless and don't share mutable state between calls
  3. The concurrent test cases in revocationList_test.go and signingRecords_test.go verify concurrent access patterns
  4. The store struct itself doesn't maintain any internal state that would require synchronization

The initStore function in the review is also thread-safe as it uses errors.Is(err, store.ErrDuplicateID) to handle race conditions when multiple goroutines try to initialize the store concurrently.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for concurrent access patterns to store methods
rg -A 5 "store\.(Insert|Update|Delete|Get)" 

# Look for any mutex usage in store implementation
ast-grep --pattern 'type $_ struct {
  $$$
  sync.Mutex
  $$$
}'

Length of output: 103312


Script:

#!/bin/bash
# Look for store interface and implementation
rg -A 5 "type Store interface" certificate-authority/store/
rg -A 5 "type Store struct" certificate-authority/store/

# Look for any concurrent access patterns in the store usage
rg -A 5 "go func|goroutine|go s\.store\." certificate-authority/

Length of output: 5317

certificate-authority/service/grpc/signCertificate.go (2)

115-127: LGTM! Clean implementation with proper error handling.

The function correctly orchestrates the signing record update process with proper revocation handling and descriptive error messages.


144-148: 🛠️ Refactor suggestion

Enhance credential validation.

While the nil check is good, consider adding more comprehensive validation for the credential fields.

Apply this diff to improve validation:

     credential := signingRecord.GetCredential()
     if credential == nil {
         return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("cannot create signing record")))
     }
+    if credential.GetIssuerId() == "" {
+        return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("issuer ID is required")))
+    }
+    if credential.GetSerial() == "" {
+        return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("certificate serial is required")))
+    }
+    if credential.GetValidUntilDate() <= time.Now().UTC().UnixNano() {
+        return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("certificate is already expired")))
+    }
     credential.CertificatePem = string(cert)

Likely invalid or redundant comment.

certificate-authority/service/grpc/signer.go (1)

199-204: LGTM! Clean implementation of signing methods.

The separation between identity and regular certificate signing is well-implemented and follows good practices.

test/sdk/client.go (1)

173-175: LGTM! Error handling has been properly implemented.

The changes correctly address the error handling concerns by:

  1. Updating the function signature to return (core.CertificateSigner, error)
  2. Properly propagating errors from NewIdentityCertificateSigner

The additional []string parameter is also properly handled with the _ placeholder since it's not needed in this implementation.

Let's verify the interface alignment:

✅ Verification successful

Based on the previous search results, I can now generate a final response as we have sufficient context about the certificate signer implementations and their usage across the codebase.

The error handling implementation is correct and consistent with the codebase

The changes in test/sdk/client.go properly align with the error handling patterns seen in:

  • pkg/security/certificateSigner/certificateSigner.go
  • pkg/security/certificateSigner/identityCertificateSigner.go
  • certificate-authority/service/grpc/signer.go

All these implementations properly handle and propagate errors from certificate signing operations. The additional []string parameter is also correctly handled as an unused parameter with _, which is appropriate for test implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the CreateSignerFunc signature matches its interface definition
# and check for any other implementations that might need similar updates

# Search for CreateSignerFunc interface definition and implementations
rg "type.*CreateSignerFunc" -A 3
rg "CreateSignerFunc.*=.*func" -A 3

Length of output: 72


Script:

#!/bin/bash
# Let's try a broader search to find the interface definition and implementations
# First, search for any mentions of CreateSignerFunc
rg "CreateSignerFunc" -B 2 -A 2

# Also search for the core.CertificateSigner type to understand the interface
rg "CertificateSigner" -B 2 -A 2

# Search for any files containing "signer" in their name to locate relevant code
fd "signer"

Length of output: 10523


Script:

#!/bin/bash
# Let's check the core package for the interface definition
fd "core" -t f -x rg -B 2 -A 2 "CertificateSigner.*interface"

# Also check for any other CreateSignerFunc implementations that might need updates
ast-grep --pattern 'CreateSignerFunc: func($$$) (core.CertificateSigner, $_) {'

Length of output: 143

certificate-authority/service/http/revocationList_test.go (3)

29-48: Sort entries before comparison to prevent flaky tests.

The current implementation compares certificate entries without sorting, which could lead to flaky tests if the order of entries changes. Consider sorting both expected and actual entries before comparison.


50-93: LGTM! Good test data coverage.

The function effectively creates test data covering various CRL states (valid, not issued, expired) with appropriate timestamps and certificates.


117-179: Enhance test coverage with additional edge cases.

Consider adding the following test cases to improve robustness:

  1. Empty issuer ID
  2. Unauthorized access (missing/invalid token)
certificate-authority/service/http/revocationList.go (5)

23-25: Function errCannotGetRevocationList is well-defined

The function correctly formats and forwards errors related to retrieving the revocation list.


27-50: createCRL function accurately constructs the CRL

The createCRL function effectively builds the Certificate Revocation List from the provided data, correctly parsing numbers and handling entries.


52-63: tryGetRevocationList handles retrieval logic appropriately

The function properly attempts to retrieve the latest revocation list, including handling of concurrent updates.


65-84: writeRevocationList correctly writes the CRL to the response

The function successfully retrieves and writes the CRL to the HTTP response with the appropriate content type.


86-90: revocationList method handles errors correctly

The wrapper function properly handles errors from writeRevocationList and returns them using serverMux.WriteError.

Copy link

sonarcloud bot commented Nov 4, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants