-
Notifications
You must be signed in to change notification settings - Fork 93
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
Add Agent license inspect command #4813
Conversation
WalkthroughThis pull request introduces a comprehensive license management feature for the Bacalhau project, focusing on agent license inspection and configuration. The changes span multiple components, including CLI commands, API endpoints, configuration types, and integration tests. The new functionality allows users to retrieve and inspect license details for the orchestrator, with support for various output formats and error handling scenarios. Changes
Sequence DiagramsequenceDiagram
participant CLI as Agent License CLI
participant Endpoint as License Endpoint
participant Config as Configuration
participant Validator as License Validator
CLI->>Endpoint: GET /api/v1/agent/license
Endpoint->>Config: Check License Path
Config-->>Endpoint: Return License Path
Endpoint->>Endpoint: Read License File
Endpoint->>Validator: Validate License Token
Validator-->>Endpoint: Validation Result
Endpoint-->>CLI: Return License Claims
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
pkg/swagger/swagger.json (1)
Line range hint
1-3
: Eliminate duplicate Swagger files.The same Swagger definition exists in both:
webui/lib/api/schema/swagger.json
pkg/swagger/swagger.json
This duplication can lead to maintenance issues and inconsistencies. Consider:
- Keeping a single source of truth
- Generating the second file if needed
- Using symbolic links if both locations are required
🧹 Nitpick comments (15)
pkg/publicapi/apimodels/agent.go (1)
43-46
: LGTM! Consider adding documentation.The
GetAgentLicenseResponse
type follows the established pattern and correctly embeds the necessary types. Consider adding documentation comments to describe the purpose and fields of this type, similar to other response types in this file.Add documentation like this:
+// GetAgentLicenseResponse is the response to the License request. type GetAgentLicenseResponse struct { BaseGetResponse *license.LicenseClaims }
cmd/cli/agent/license/root.go (2)
9-11
: Consider enhancing the command description.While the description is clear, it could be more detailed to help users understand the available subcommands and their purposes.
- Short: "Commands to interact with the orchestrator license", + Short: "Commands to interact with the orchestrator license", + Long: `Commands to interact with the orchestrator license. + +Available Commands: + inspect Inspect the orchestrator license information without revealing the license file`,
7-15
: Consider adding PreRun and PostRun hooks.For consistency with the parent command, consider adding the same hooks that are defined in the agent root command.
func NewAgentLicenseRootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "license", Short: "Commands to interact with the orchestrator license", + PersistentPreRunE: hook.AfterParentPreRunHook(hook.RemoteCmdPreRunHooks), + PersistentPostRunE: hook.AfterParentPostRunHook(hook.RemoteCmdPostRunHooks), }test_integration/15_agent_license_inspect_with_no_license_suite_test.go (1)
41-49
: Enhance error handling test coverage.Consider improving the test coverage by:
- Verifying the specific error type in addition to the error message.
- Testing different output formats (JSON, YAML) to ensure consistent error handling.
func (s *AgentLicenseInspectWithNoLicenseSuite) TestValidateRemoteLicenseWithNoLicense() { - _, err := s.executeCommandInDefaultJumpbox( + // Test default output format + _, err := s.executeCommandInDefaultJumpbox( []string{ "bacalhau", "agent", "license", "inspect", }, ) - s.Require().ErrorContains(err, "Node license not configured") + + // Test JSON output format + _, err = s.executeCommandInDefaultJumpbox( + []string{ + "bacalhau", "agent", "license", "inspect", + "--output=json", + }, + ) + s.Require().ErrorContains(err, "Node license not configured") + + // Test YAML output format + _, err = s.executeCommandInDefaultJumpbox( + []string{ + "bacalhau", "agent", "license", "inspect", + "--output=yaml", + }, + ) + s.Require().ErrorContains(err, "Node license not configured") }test_integration/13_agent_license_inspect_suite_test.go (2)
49-57
: Consider using relative dates for test data.The test uses a hardcoded far-future date (2045-07-28). Consider using a relative date calculation to make the test more maintainable.
+ // Calculate a date 20 years in the future for testing + futureDate := time.Now().AddDate(20, 0, 0).Format("2006-01-02") expectedOutput := `Product = Bacalhau License ID = e66d1f3a-a8d8-4d57-8f14-00722844afe2 Customer ID = test-customer-id-123 -Valid Until = 2045-07-28 +Valid Until = ` + futureDate + ` Version = v1 Capabilities = max_nodes=1 Metadata = {}`
72-94
: Consider using structured JSON parsing for more robust tests.Instead of using string queries which can be fragile, consider parsing the JSON response into a struct for more reliable validation.
+ type LicenseResponse struct { + Product string `json:"product"` + LicenseID string `json:"license_id"` + CustomerID string `json:"customer_id"` + LicenseVersion string `json:"license_version"` + Capabilities map[string]string `json:"capabilities"` + } + - output, err := s.convertStringToDynamicJSON(agentLicenseInspectionOutput) + var response LicenseResponse + err = json.Unmarshal([]byte(agentLicenseInspectionOutput), &response) s.Require().NoError(err) - productName, err := output.Query("$.product") - s.Require().NoError(err) - s.Require().Equal("Bacalhau", productName.String()) + s.Require().Equal("Bacalhau", response.Product) + s.Require().Equal("e66d1f3a-a8d8-4d57-8f14-00722844afe2", response.LicenseID) + s.Require().Equal("test-customer-id-123", response.CustomerID) + s.Require().Equal("v1", response.LicenseVersion) + s.Require().Equal("1", response.Capabilities["max_nodes"])cmd/cli/agent/license/inspect.go (2)
31-46
: Add usage examples to command help text.The command would benefit from usage examples in the help text to improve user experience.
licenseCmd := &cobra.Command{ Use: "inspect", Short: "Get the agent license information", + Long: `Get the agent license information. + +Examples: + # Get license information in default format + bacalhau agent license inspect + + # Get license information in JSON format + bacalhau agent license inspect --output=json + + # Get license information in YAML format + bacalhau agent license inspect --output=yaml`, Args: cobra.NoArgs,
73-99
: Reduce code duplication in map formatting logic.The code duplicates the map iteration logic for capabilities and metadata. Consider extracting this into a helper function.
+ // Helper function to format map as string + formatMapAsString := func(m map[string]string) string { + if len(m) == 0 { + return "{}" + } + var items []string + for k, v := range m { + items = append(items, fmt.Sprintf("%s=%s", k, v)) + } + return strings.Join(items, ", ") + } + - // Always show Capabilities - capabilitiesStr := "{}" - if len(response.Capabilities) > 0 { - var caps []string - for k, v := range response.Capabilities { - caps = append(caps, fmt.Sprintf("%s=%s", k, v)) - } - capabilitiesStr = strings.Join(caps, ", ") - } headerData = append(headerData, collections.Pair[string, any]{ Left: "Capabilities", - Right: capabilitiesStr, + Right: formatMapAsString(response.Capabilities), }) - // Always show Metadata - metadataStr := "{}" - if len(response.Metadata) > 0 { - var meta []string - for k, v := range response.Metadata { - meta = append(meta, fmt.Sprintf("%s=%s", k, v)) - } - metadataStr = strings.Join(meta, ", ") - } headerData = append(headerData, collections.Pair[string, any]{ Left: "Metadata", - Right: metadataStr, + Right: formatMapAsString(response.Metadata), })test_integration/14_agent_license_inspect_with_metadata_suite_test.go (1)
60-84
: Use structured YAML parsing for more robust tests.Instead of using multiple string contains assertions which can be fragile, consider parsing the YAML response into a struct for more reliable validation.
+ type LicenseResponse struct { + Metadata map[string]string `yaml:"metadata"` + JTI string `yaml:"jti"` + Issuer string `yaml:"iss"` + IssuedAt int64 `yaml:"iat"` + ExpiresAt int64 `yaml:"exp"` + CustomerID string `yaml:"customer_id"` + LicenseID string `yaml:"license_id"` + LicenseType string `yaml:"license_type"` + Subject string `yaml:"sub"` + Product string `yaml:"product"` + LicenseVersion string `yaml:"license_version"` + Capabilities map[string]string `yaml:"capabilities"` + } + agentLicenseInspectionOutput, err := s.executeCommandInDefaultJumpbox( []string{ "bacalhau", @@ -69,16 +83,21 @@ ) s.Require().NoErrorf(err, "Error inspecting license: %q", err) - s.Require().Contains(agentLicenseInspectionOutput, "someMetadata: valueOfSomeMetadata") - s.Require().Contains(agentLicenseInspectionOutput, "jti: 2d58c7c9-ec29-45a5-a5cd-cb8f7fee6678") - s.Require().Contains(agentLicenseInspectionOutput, "iss: https://expanso.io/") - s.Require().Contains(agentLicenseInspectionOutput, "iat: 1736889682") - s.Require().Contains(agentLicenseInspectionOutput, "exp: 2384889682") - s.Require().Contains(agentLicenseInspectionOutput, "customer_id: test-customer-id-123") - s.Require().Contains(agentLicenseInspectionOutput, "license_id: 2d58c7c9-ec29-45a5-a5cd-cb8f7fee6678") - s.Require().Contains(agentLicenseInspectionOutput, "license_type: standard") - s.Require().Contains(agentLicenseInspectionOutput, "sub: test-customer-id-123") - s.Require().Contains(agentLicenseInspectionOutput, "product: Bacalhau") - s.Require().Contains(agentLicenseInspectionOutput, "license_version: v1") - s.Require().Contains(agentLicenseInspectionOutput, "max_nodes: \"1\"") + var response LicenseResponse + err = yaml.Unmarshal([]byte(agentLicenseInspectionOutput), &response) + s.Require().NoError(err) + + s.Require().Equal("valueOfSomeMetadata", response.Metadata["someMetadata"]) + s.Require().Equal("2d58c7c9-ec29-45a5-a5cd-cb8f7fee6678", response.JTI) + s.Require().Equal("https://expanso.io/", response.Issuer) + s.Require().Equal(int64(1736889682), response.IssuedAt) + s.Require().Equal(int64(2384889682), response.ExpiresAt) + s.Require().Equal("test-customer-id-123", response.CustomerID) + s.Require().Equal("2d58c7c9-ec29-45a5-a5cd-cb8f7fee6678", response.LicenseID) + s.Require().Equal("standard", response.LicenseType) + s.Require().Equal("test-customer-id-123", response.Subject) + s.Require().Equal("Bacalhau", response.Product) + s.Require().Equal("v1", response.LicenseVersion) + s.Require().Equal("1", response.Capabilities["max_nodes"])pkg/publicapi/endpoint/agent/endpoint.go (2)
164-175
: Add file size limit and improve JSON handling.Consider these improvements for robustness:
- Add a size limit when reading the license file to prevent memory issues
- Use a more strict JSON decoder with DisallowUnknownFields()
// Read license file +const maxLicenseSize = 1 << 20 // 1MB limit +fi, err := os.Stat(licensePath) +if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to stat license file: %s", err)) +} +if fi.Size() > maxLicenseSize { + return echo.NewHTTPError(http.StatusInternalServerError, "license file too large") +} licenseData, err := os.ReadFile(licensePath) // Parse license JSON var licenseFile struct { License string `json:"license"` } -if err := json.Unmarshal(licenseData, &licenseFile); err != nil { +decoder := json.NewDecoder(bytes.NewReader(licenseData)) +decoder.DisallowUnknownFields() +if err := decoder.Decode(&licenseFile); err != nil {
156-191
: Improve error handling consistency.The error handling is good but could be more consistent. Consider wrapping all errors with a common error type that includes:
- Error code
- User-friendly message
- Internal error details (for logging)
+type licenseError struct { + Code int + Message string + Err error +} + +func (e *licenseError) Error() string { + return e.Message +} + func (e *Endpoint) license(c echo.Context) error { // Get license path from config licensePath := e.bacalhauConfig.Orchestrator.License.LocalPath if licensePath == "" { - return echo.NewHTTPError(http.StatusNotFound, "Node license not configured") + return &licenseError{ + Code: http.StatusNotFound, + Message: "Node license not configured", + } }pkg/publicapi/endpoint/agent/endpoint_test.go (1)
60-268
: LGTM! Comprehensive test coverage with room for enhancement.The test suite thoroughly covers the main scenarios. Consider adding these edge cases:
- License file with valid JSON but empty license string
- License file with permissions issues
- License file exceeding size limit (after implementing the size limit)
Would you like me to provide the additional test cases?
pkg/swagger/docs.go (1)
3178-3179
: Consider documenting the reason for template delimiter changes.While the changes to SwaggerInfo's template delimiters look correct, it would be helpful to document why these specific delimiters were chosen.
test_integration/common_assets/nodes_configs/14_orchestrator_config_with_license_with_metadata.yaml (1)
9-9
: Use relative paths in test configurations.Using absolute paths in test configurations can cause portability issues across different environments. Consider using a path relative to the repository root:
- LocalPath: "/bacalhau_integration_tests/common_assets/licenses/test-license-with-metadata.json" + LocalPath: "test_integration/common_assets/licenses/test-license-with-metadata.json"webui/lib/api/schema/swagger.json (1)
1223-1298
: Enhance license claims schema validation.Consider adding these validations to the
license.LicenseClaims
schema:
- Required fields
- String format validations
- Enum constraints for
license_type
Apply these schema enhancements:
"license.LicenseClaims": { "type": "object", + "required": [ + "license_id", + "customer_id", + "license_type", + "license_version", + "product" + ], "properties": { "license_type": { - "type": "string" + "type": "string", + "enum": ["standard", "enterprise", "trial"] }, "license_version": { - "type": "string" + "type": "string", + "pattern": "^v\\d+$" } } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (20)
cmd/cli/agent/license/inspect.go
(1 hunks)cmd/cli/agent/license/root.go
(1 hunks)cmd/cli/agent/root.go
(2 hunks)pkg/config/types/generated_constants.go
(1 hunks)pkg/config/types/generated_descriptions.go
(1 hunks)pkg/config/types/orchestrator.go
(2 hunks)pkg/publicapi/apimodels/agent.go
(2 hunks)pkg/publicapi/client/v2/api_agent.go
(1 hunks)pkg/publicapi/endpoint/agent/endpoint.go
(3 hunks)pkg/publicapi/endpoint/agent/endpoint_test.go
(3 hunks)pkg/swagger/docs.go
(6 hunks)pkg/swagger/swagger.json
(4 hunks)test_integration/13_agent_license_inspect_suite_test.go
(1 hunks)test_integration/14_agent_license_inspect_with_metadata_suite_test.go
(1 hunks)test_integration/15_agent_license_inspect_with_no_license_suite_test.go
(1 hunks)test_integration/common_assets/licenses/test-license-with-metadata.json
(1 hunks)test_integration/common_assets/nodes_configs/13_orchestrator_config_with_license.yaml
(1 hunks)test_integration/common_assets/nodes_configs/14_orchestrator_config_with_license_with_metadata.yaml
(1 hunks)test_integration/common_assets/nodes_configs/15_orchestrator_config_with_no_license.yaml
(1 hunks)webui/lib/api/schema/swagger.json
(4 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
test_integration/common_assets/licenses/test-license-with-metadata.json
2-2: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/publicapi/endpoint/agent/endpoint_test.go
23-23: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: testcontainers-suite / tests
🔇 Additional comments (15)
pkg/publicapi/client/v2/api_agent.go (1)
40-45
: LGTM! Implementation follows established patterns.The
License
method is well-implemented, following the same patterns as other methods in this file. The documentation and error handling are appropriate.cmd/cli/agent/root.go (1)
4-4
: LGTM! Command registration is correct.The license command is properly integrated into the agent CLI command structure, following the established pattern.
Also applies to: 21-21
pkg/config/types/orchestrator.go (2)
22-23
: LGTM! Well-structured configuration type.The License field is properly documented and follows the established patterns for configuration types.
82-85
: LGTM! Clean and extensible struct design.The License struct is minimal yet allows for future extension. The omitempty tags ensure backward compatibility.
pkg/publicapi/endpoint/agent/endpoint.go (2)
50-50
: LGTM! Clean route registration.The license endpoint is properly registered with the API group.
146-155
: LGTM! Well-documented endpoint.The Swagger documentation is comprehensive and accurately describes the endpoint's behavior, including success and error responses.
pkg/config/types/generated_constants.go (1)
89-89
: LGTM! Consistent constant definition.The new constant follows the established naming pattern and integrates well with existing constants.
pkg/publicapi/endpoint/agent/endpoint_test.go (1)
22-23
: Review the test license token.The hardcoded JWT token was flagged by security scanning. While it appears to be a test token, please verify that:
- It's not a real production license
- The expiration date (2384881638 = Jan 19, 2045) is intentionally far in the future
Consider moving test tokens to a separate test data file or using a helper function to generate test tokens.
🧰 Tools
🪛 Gitleaks (8.21.2)
23-23: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/config/types/generated_descriptions.go (1)
91-91
: LGTM! Description follows the established pattern.The description for
OrchestratorLicenseLocalPathKey
is clear, concise, and follows the same style as other configuration descriptions in the map.pkg/swagger/docs.go (2)
116-147
: LGTM! Well-defined API endpoint with appropriate response codes.The endpoint is properly documented with:
- Clear summary and operationId
- Appropriate response codes (200, 404, 500)
- Proper schema references
1227-1302
: LGTM! Comprehensive license claims schema.The schema includes all essential JWT fields with proper descriptions and references to RFC 7519, plus custom license-specific fields:
- Standard JWT claims (aud, exp, iat, iss, jti, nbf, sub)
- License-specific claims (capabilities, customer_id, license_id, license_type, license_version, metadata, product)
test_integration/common_assets/nodes_configs/15_orchestrator_config_with_no_license.yaml (1)
1-10
: LGTM! Valid test configuration for no-license scenario.The configuration provides all necessary fields for testing the orchestrator without a license:
- Unique node identification (uuid)
- API configuration
- Authentication token
- Test labels
test_integration/common_assets/nodes_configs/13_orchestrator_config_with_license.yaml (2)
1-12
: LGTM! Valid test configuration for license scenario.The configuration includes all necessary fields including the license configuration.
8-9
: Verify the license file path in the test environment.The license file path is hardcoded to
/bacalhau_integration_tests/common_assets/licenses/test-license.json
. Ensure this path is correctly set up in the test environment.✅ Verification successful
License file path is correctly configured ✅
The path follows the established pattern where
test_integration
is mounted as/bacalhau_integration_tests
in the test environment, and the license file exists at the expected location.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify the existence of the test license file # Test: Check if the license file exists in the test assets fd -t f "test-license.json" test_integration/common_assets/licenses/Length of output: 126
Script:
#!/bin/bash # Search for similar path patterns in yaml files rg -g "*.yaml" -g "*.yml" "/bacalhau_integration_tests" test_integration/Length of output: 2980
test_integration/common_assets/licenses/test-license-with-metadata.json (1)
1-3
: Verify test JWT token validity and expiration.The file contains a JWT token that could pose a security risk if valid. Please ensure:
- This is a test-only token with no production credentials
- The token is expired or invalidated
- Consider using a shorter token or placeholder in test files
Run the following script to check the token's validity and expiration:
✅ Verification successful
Confirmed: Test-only license token verified
This is a valid test license file based on:
- Located in test assets directory
- Contains test-specific identifiers (bacalhau-integration-tests, test-customer-id-123)
- Properly isolated in test fixtures
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify if the JWT token is expired and test-only # Note: This script only checks the token structure and claims, not its cryptographic validity echo "Decoding JWT token to verify claims..." TOKEN=$(cat test_integration/common_assets/licenses/test-license-with-metadata.json | jq -r .license) echo $TOKEN | awk -F. '{print $2}' | base64 -d 2>/dev/null | jq .Length of output: 2274
Script:
#!/bin/bash # Description: Verify JWT token with proper base64 padding echo "Decoding JWT token to verify claims..." TOKEN=$(cat test_integration/common_assets/licenses/test-license-with-metadata.json | jq -r .license) echo $TOKEN | awk -F. '{print $2}' | base64 -d 2>/dev/null | python3 -m json.tool 2>/dev/null || \ (echo $TOKEN | awk -F. '{print $2 "=="}' | base64 -d 2>/dev/null | python3 -m json.tool)Length of output: 3475
Script:
#!/bin/bash # Description: Simple JWT token decode using only base64 echo "Decoding JWT token to verify claims..." TOKEN=$(cat test_integration/common_assets/licenses/test-license-with-metadata.json | jq -r .license) echo "JWT Payload:" echo $TOKEN | cut -d"." -f2 | { base64 -d 2>/dev/null || base64 -D 2>/dev/null; }Length of output: 2305
Script:
#!/bin/bash # Description: Decode URL-safe base64 JWT token echo "Decoding JWT token to verify claims..." TOKEN=$(cat test_integration/common_assets/licenses/test-license-with-metadata.json | jq -r .license) echo "JWT Payload:" echo $TOKEN | cut -d"." -f2 | tr '_-' '/+' | tr -d '\n' | fold -w 4 | sed '$ s/$/==/' | head -c -4 | base64 -dLength of output: 2552
🧰 Tools
🪛 Gitleaks (8.21.2)
2-2: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one comment. The rest looks great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (1)
pkg/publicapi/endpoint/agent/endpoint.go (1)
147-172
: 🛠️ Refactor suggestionAdd authentication and rate limiting to the license endpoint.
The license endpoint exposes sensitive information and should be protected. Consider:
- Adding authentication requirement
- Implementing rate limiting
- Adding appropriate security headers
Additionally, as suggested in a previous review, consider moving the license validation logic to a dedicated license provider that can be used by both the API and other components.
🧹 Nitpick comments (3)
pkg/licensing/license_manager.go (1)
65-72
: Ensure sensitive error information is not exposedWhen validating the license token in
ValidateLicense
, consider whether the wrapped error froml.licenseValidator.ValidateToken
might expose sensitive information. It's important to sanitize error messages to prevent leakage of internal details.Consider returning a more generic error message or sanitizing the wrapped error to avoid revealing sensitive information.
test_integration/15_agent_license_inspect_with_no_license_suite_test.go (1)
41-49
: Consider adding more test cases.The test suite currently only verifies the error message when no license is configured. Consider adding test cases for:
- Invalid license file path
- Empty license file
- Malformed license file
🧰 Tools
🪛 GitHub Actions: Main Pipeline
[error] Test suite failed with exit code 1. One test suite (TestLocalLicenseInspectSuite) failed while others passed.
pkg/swagger/swagger.json (1)
1285-1292
: Add validation constraints for NumericDate.Consider adding validation constraints to ensure the time value is within acceptable bounds for JWT timestamps (e.g., not before Unix epoch, not too far in the future).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
pkg/licensing/license_manager.go
(1 hunks)pkg/licensing/license_manager_test.go
(1 hunks)pkg/node/node.go
(5 hunks)pkg/publicapi/endpoint/agent/endpoint.go
(5 hunks)pkg/publicapi/endpoint/agent/endpoint_test.go
(2 hunks)pkg/swagger/docs.go
(7 hunks)pkg/swagger/swagger.json
(5 hunks)test_integration/15_agent_license_inspect_with_no_license_suite_test.go
(1 hunks)webui/lib/api/schema/swagger.json
(5 hunks)
🧰 Additional context used
🪛 Gitleaks (8.21.2)
pkg/licensing/license_manager_test.go
14-14: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/publicapi/endpoint/agent/endpoint_test.go
24-24: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
25-25: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
229-229: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
🪛 GitHub Actions: Main Pipeline
test_integration/15_agent_license_inspect_with_no_license_suite_test.go
[error] Test suite failed with exit code 1. One test suite (TestLocalLicenseInspectSuite) failed while others passed.
🔇 Additional comments (15)
pkg/licensing/license_manager.go (4)
24-26
: Good nil configuration checkThe code correctly checks for a nil configuration and returns an appropriate error message.
28-31
: Proper error handling when initializing LicenseValidatorThe initialization of the
licenseValidator
handles errors appropriately by wrapping them with context, enhancing debuggability.
36-53
: Robust license file reading and JSON parsingThe code correctly reads the license file and validates its JSON structure, ensuring that the required
"license"
field is present. Error handling is comprehensive at each step.
78-100
: Comprehensive validation inValidateLicenseWithNodeCount
The method correctly validates the license and checks the
nodeCount
against themax_nodes
capability. Error handling covers scenarios where the capability is missing or invalid.pkg/licensing/license_manager_test.go (2)
16-270
: Comprehensive test coverage forLicenseManager
The unit tests provide thorough coverage of the
LicenseManager
functionality, testing various scenarios including valid and invalid tokens, missing licenses, invalid JSON structures, file not found errors, and node count validations.
14-14
:⚠️ Potential issueAvoid hardcoding JWT tokens in test code
Line 14 contains a hardcoded JWT token. Even in test code, including real tokens can pose security risks.
Replace the hardcoded token with a mock or dummy token generated during test execution to ensure it doesn't contain any sensitive information. Verify that the token is not valid and cannot be used to access any systems.
🧰 Tools
🪛 Gitleaks (8.21.2)
14-14: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/node/node.go (3)
89-89
: Addition ofLicenseManager
toNode
structIntegrating
LicenseManager
into theNode
struct enables centralized management of licensing within the node, enhancing maintainability and modularity.
118-123
: Proper initialization ofLicenseManager
inNewNode
The
LicenseManager
is initialized correctly within theNewNode
function, and errors during initialization are handled appropriately by returning the error to the caller.
205-205
: Integration ofLicenseManager
with agent endpointPassing the
LicenseManager
to the agent endpoint ensures that licensing checks are performed when handling agent-related API requests, which is essential for enforcing license restrictions.pkg/publicapi/endpoint/agent/endpoint_test.go (1)
62-116
: LGTM! Comprehensive test coverage.The test case thoroughly validates the license endpoint's success scenario by checking all relevant fields in the response.
webui/lib/api/schema/swagger.json (2)
980-1055
: LGTM! Well-documented response schema.The GetAgentLicenseResponse schema is thoroughly documented with clear descriptions for each field.
112-137
: 🛠️ Refactor suggestionAdd security definitions to the API schema.
The license endpoint's OpenAPI specification should include:
- Security scheme definitions (e.g., ApiKeyAuth)
- Security requirements for the endpoint
- Rate limiting headers in the response schema
Apply this diff to add security definitions:
+ "securityDefinitions": { + "ApiKeyAuth": { + "type": "apiKey", + "in": "header", + "name": "X-API-Key" + } + }, "paths": { "/api/v1/agent/license": { "get": { + "security": [ + { + "ApiKeyAuth": [] + } + ],Likely invalid or redundant comment.
pkg/swagger/swagger.json (2)
112-137
: LGTM! Well-structured API endpoint definition.The new endpoint follows REST API best practices with proper content types, status codes, and error handling.
980-1055
: Consider security implications of exposing JWT claims.While the response structure is well-defined, consider if exposing all JWT claims is necessary. Some claims might contain sensitive information that should be filtered out before returning to the client.
Run this script to check for any sensitive information in the JWT claims:
pkg/swagger/docs.go (1)
3172-3173
: LGTM! Template delimiters properly configured.The addition of explicit template delimiters (
LeftDelim
andRightDelim
) helps prevent conflicts with other template processors.
pkg/licensing/license_manager.go
Outdated
// Verify the JSON structure | ||
var licenseFile struct { | ||
License string `json:"license"` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like having inline structs for such behaviour. First, why can't we have license content at the root of the json object instead of having a license
field? If it is a must, then lets introduce a LicenseWrapper
type and not make it inline
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, why can't we have license content at the root of the json object instead of having a license field?
Not sure what you meant here, but the license content is already at the root of the json object. The Json file structure of the license:
{
"license": "the-license-jwt-token"
}
If it is a must, then lets introduce a LicenseWrapper type and not make it inline
Hmm, It is not used anywhere else, do you think it is still worth it ?
The unit tests already cover all the edge cases for the format.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the file only contains the license jwt token and nothing else, why do you need a json wrapping the token?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wdbaruni I would rather have a JSON object as the structure of a license even if it has one item in it. It will easily allow for any future additions or migrations, compared to just an opaque string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🔭 Outside diff range comments (2)
cmd/cli/license/inspect.go (1)
Line range hint
101-101
: Handle potential nilExpiresAt
when formatting dateAccessing
claims.ExpiresAt
without checking fornil
may cause a panic ifExpiresAt
isnil
. Ensure thatExpiresAt
is notnil
before callingFormat
, or handle thenil
case appropriately.Apply this diff to handle
nil
ExpiresAt
:- {Left: "Valid Until", Right: claims.ExpiresAt.Format(time.DateOnly)}, + {Left: "Valid Until", Right: func() string { + if claims.ExpiresAt != nil { + return claims.ExpiresAt.Format(time.DateOnly) + } + return "N/A" + }()},cmd/cli/license/inspect_test.go (1)
Line range hint
231-231
: Security: Consider removing or obfuscating test tokens.The test file contains exposed JWT tokens that could potentially be misused. Consider:
- Using shorter, obviously fake tokens for basic validation tests
- Moving sensitive test data to a separate test fixtures file
- Adding a clear comment that these are test-only tokens
Also applies to: 238-238
🧹 Nitpick comments (10)
pkg/lib/license/license_validator.go (1)
40-52
: Consider logging conversion errors inMaxNumberOfNodes
In the
MaxNumberOfNodes
method, if the "max_nodes" capability value is not a valid integer, the function silently returns 0. Logging a warning or returning an error could help identify misconfigurations or data issues.test_integration/16_agent_license_inspect_expired_suite_test.go (1)
41-59
: Enhance test robustness by parsing outputThe test compares the entire output string to verify license details. This approach can be brittle if the output format changes. Consider parsing the command output and asserting individual fields to make the test more resilient and maintainable.
pkg/licensing/license_manager.go (2)
48-54
: Consider extracting the license file structure to a named type.The inline struct for the license file format could be moved to a named type for better reusability and documentation.
+// LicenseFile represents the structure of the license file +type LicenseFile struct { + License string `json:"license"` +} // Verify the JSON structure of the license file -var licenseFile struct { - License string `json:"license"` -} +var licenseFile LicenseFile
70-73
: Consider adding documentation for the License method.The method would benefit from godoc explaining that it returns nil when no license is configured.
+// License returns the current license claims. +// Returns nil if no license is configured. func (l *LicenseManager) License() *license.LicenseClaims { return l.licenseClaims }test_integration/13_agent_license_inspect_suite_test.go (2)
49-56
: Consider using constants for expected values.The hardcoded expected values could be moved to constants or test data structures for better maintainability.
+const ( + expectedProduct = "Bacalhau" + expectedLicenseID = "e66d1f3a-a8d8-4d57-8f14-00722844afe2" + expectedCustomerID = "test-customer-id-123" + expectedVersion = "v1" + expectedMaxNodes = "1" +) -expectedOutput := `Product = Bacalhau -License ID = e66d1f3a-a8d8-4d57-8f14-00722844afe2 -Customer ID = test-customer-id-123 -Valid Until = 2045-07-28 -Version = v1 -Expired = false -Capabilities = max_nodes=1 -Metadata = {}` +expectedOutput := fmt.Sprintf( + "Product = %s\n"+ + "License ID = %s\n"+ + "Customer ID = %s\n"+ + "Valid Until = 2045-07-28\n"+ + "Version = %s\n"+ + "Expired = false\n"+ + "Capabilities = max_nodes=%s\n"+ + "Metadata = {}", + expectedProduct, + expectedLicenseID, + expectedCustomerID, + expectedVersion, + expectedMaxNodes, +)
76-94
: Consider using table-driven tests for JSON field validation.The JSON field validation could be simplified using a table-driven test approach.
+type jsonFieldTest struct { + path string + expected string +} + +tests := []jsonFieldTest{ + {path: "$.product", expected: expectedProduct}, + {path: "$.license_id", expected: expectedLicenseID}, + {path: "$.customer_id", expected: expectedCustomerID}, + {path: "$.license_version", expected: expectedVersion}, + {path: "$.capabilities.max_nodes", expected: expectedMaxNodes}, +} + +for _, test := range tests { + value, err := output.Query(test.path) + s.Require().NoError(err) + s.Require().Equal(test.expected, value.String()) +}pkg/publicapi/endpoint/agent/endpoint.go (1)
152-173
: Consider adding more detailed error information.The error message could provide more context about why the license might not be configured and potential remediation steps.
- return echo.NewHTTPError( - http.StatusNotFound, - "Error inspecting orchestrator license: No license configured for orchestrator.", - ) + return echo.NewHTTPError( + http.StatusNotFound, + "Error inspecting orchestrator license: No license configured for orchestrator. "+ + "Please ensure a valid license file is specified in the orchestrator configuration.", + )pkg/lib/license/license_validator_test.go (3)
Line range hint
15-157
: Consider moving sensitive test data to separate test fixture files.The test data contains sensitive information like JWKs and tokens. Moving this data to separate test fixture files would:
- Improve maintainability by separating test data from test logic
- Enhance security by making it easier to manage sensitive test data
- Allow for better version control of test fixtures
500-514
: Consider adding more assertions for expired token validation.While the test verifies basic functionality, consider adding assertions for:
- The exact expiration time
- Other time-related claims (IssuedAt, NotBefore)
- Error scenarios with malformed expiration dates
516-559
: Add edge cases for MaxNumberOfNodes testing.Consider adding test cases for:
- Negative numbers
- Very large numbers
- Floating-point numbers
- Special characters in the number string
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (17)
cmd/cli/agent/license/inspect.go
(1 hunks)cmd/cli/license/inspect.go
(2 hunks)cmd/cli/license/inspect_test.go
(6 hunks)pkg/lib/license/license_validator.go
(3 hunks)pkg/lib/license/license_validator_test.go
(8 hunks)pkg/licensing/license_manager.go
(1 hunks)pkg/licensing/license_manager_test.go
(1 hunks)pkg/node/node.go
(3 hunks)pkg/publicapi/endpoint/agent/endpoint.go
(4 hunks)pkg/publicapi/endpoint/agent/endpoint_test.go
(3 hunks)test_integration/12_local_license_inspect_suite_test.go
(2 hunks)test_integration/13_agent_license_inspect_suite_test.go
(1 hunks)test_integration/14_agent_license_inspect_with_metadata_suite_test.go
(1 hunks)test_integration/15_agent_license_inspect_with_no_license_suite_test.go
(1 hunks)test_integration/16_agent_license_inspect_expired_suite_test.go
(1 hunks)test_integration/common_assets/licenses/test-license-valid-but-expired.json
(1 hunks)test_integration/common_assets/nodes_configs/16_orchestrator_config_with_expired_license.yaml
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- cmd/cli/agent/license/inspect.go
- test_integration/14_agent_license_inspect_with_metadata_suite_test.go
- test_integration/15_agent_license_inspect_with_no_license_suite_test.go
🧰 Additional context used
🪛 Gitleaks (8.21.2)
test_integration/common_assets/licenses/test-license-valid-but-expired.json
2-2: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/lib/license/license_validator_test.go
231-231: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
238-238: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/publicapi/endpoint/agent/endpoint_test.go
24-24: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
25-25: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/licensing/license_manager_test.go
14-14: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
🔇 Additional comments (23)
pkg/lib/license/license_validator.go (1)
146-165
: Ensure safe usage when parsing unverified tokensThe method
validateToken
parses JWT tokens without verification when the token is expired, andverifyExpiry
is false. Parsing unverified tokens can be risky as it might expose the application to security vulnerabilities if the token is tampered with. Please review to ensure that no sensitive operations depend on unverified data and that this approach aligns with security best practices.test_integration/12_local_license_inspect_suite_test.go (2)
63-83
: LGTM! Well-structured test for expired license inspection.The test case is well-implemented with:
- Clear setup and execution
- Comprehensive assertions
- Proper error handling
132-132
: LGTM! Error message update maintains consistency.The error message update aligns with the new error handling structure across the codebase.
cmd/cli/license/inspect_test.go (7)
Line range hint
197-241
: LGTM! Comprehensive test coverage for license validation.The test cases thoroughly cover:
- Valid and invalid scenarios
- Expiration handling
- Error message verification
Also applies to: 433-443
Line range hint
500-514
: LGTM! Good test for expired but valid token handling.The test ensures that expired licenses can still be inspected for their contents while correctly reporting their expired status.
Line range hint
516-559
: LGTM! Thorough testing of MaxNumberOfNodes capability.The test cases cover all relevant scenarios for the max_nodes capability:
- Valid numeric values
- Empty values
- Missing capability
- Invalid formats
Line range hint
561-596
: LGTM! Well-structured expiration testing.The test cases properly verify the expiration logic using time-based scenarios:
- Nil expiration
- Future expiration
- Past expiration
Line range hint
598-637
: LGTM! Good coverage for strict validation.The test cases verify that strict validation properly handles both valid and expired tokens.
Line range hint
639-674
: LGTM! Comprehensive JWKS malformation testing.The test cases cover various JWKS error scenarios:
- Missing required fields
- Invalid key types
- Missing key types
Line range hint
676-700
: LGTM! Good test for invalid capabilities format.The test ensures proper error handling for malformed capability values.
test_integration/common_assets/licenses/test-license-valid-but-expired.json (1)
1-3
: LGTM!The test license file is properly structured and serves its purpose for testing expired license scenarios.
🧰 Tools
🪛 Gitleaks (8.21.2)
2-2: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
pkg/licensing/license_manager.go (1)
13-18
: LGTM!The
LicenseManager
struct is well-designed with clear responsibilities and minimal dependencies.pkg/licensing/license_manager_test.go (2)
13-14
: LGTM!The test token is properly documented and used only for testing purposes.
🧰 Tools
🪛 Gitleaks (8.21.2)
14-14: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
16-149
: LGTM!The test suite is comprehensive and well-structured, covering all important scenarios including:
- Invalid token handling
- Valid token verification
- No license configuration
- Invalid JSON handling
- File not found scenarios
- Nil configuration handling
pkg/publicapi/endpoint/agent/endpoint_test.go (5)
31-34
: LGTM!The LicenseManager initialization is correctly added to support the new license functionality while maintaining the original test's purpose.
23-25
: Consider moving test tokens to fixtures.While these are test-specific tokens, it's a good practice to:
- Move tokens to a dedicated test fixtures file
- Add a comment explaining their test-specific nature
- Document the claims encoded in these tokens
🧰 Tools
🪛 Gitleaks (8.21.2)
24-24: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
25-25: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
69-126
: LGTM! Comprehensive test coverage.The test thoroughly validates the license endpoint:
- Safe handling of temporary files
- Comprehensive verification of license claims
- Proper cleanup of test resources
128-161
: LGTM! Good error handling test.The test properly validates the error scenario when no license is configured.
163-235
: LGTM! Good edge case coverage.The tests thoroughly validate important edge cases:
- License manager configuration errors
- Expired license handling
pkg/node/node.go (2)
117-121
: LGTM! Clean initialization of license manager.The license manager is properly initialized with appropriate error handling.
199-208
: LGTM! Clean integration with agent endpoint.The license manager is correctly passed to the agent endpoint, following the feedback about not storing it in the node struct.
pkg/lib/license/license_validator_test.go (2)
Line range hint
197-257
: Well-structured test cases with good coverage.The addition of the
wantExpired
field and corresponding assertions improves the test coverage by explicitly verifying token expiration behavior. The test cases cover various scenarios including valid tokens, invalid formats, and error conditions.🧰 Tools
🪛 Gitleaks (8.21.2)
231-231: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
238-238: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
231-241
: Review security implications of embedded test tokens.While these are test tokens, consider:
- Adding clear comments indicating these are test-only tokens
- Using shorter token examples where possible
- Documenting the token generation process for maintainers
Run this script to verify these are indeed test tokens:
✅ Verification successful
JWT tokens are properly confined to test files ✓
All JWT tokens are correctly isolated to test files, test fixtures, and integration test assets. The tokens contain test-specific identifiers and are not used in production code.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify if the tokens are used only in tests # Test: Search for token usage outside of test files rg -g '!*_test.go' "eyJhbGciOiJSUzI1NiI"Length of output: 4827
🧰 Tools
🪛 Gitleaks (8.21.2)
231-231: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
238-238: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
test_integration/common_assets/nodes_configs/16_orchestrator_config_with_expired_license.yaml
Show resolved
Hide resolved
test_integration/common_assets/nodes_configs/16_orchestrator_config_with_expired_license.yaml
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
webui/lib/api/schema/swagger.json (1)
2781-2789
: Add validation constraints to License type.The License type should include:
- Required field marker for LocalPath
- Pattern for valid file paths
- Example value
Apply this diff:
"types.License": { "type": "object", "properties": { "LocalPath": { "description": "LocalPath specifies the local license file path", - "type": "string" + "type": "string", + "pattern": "^[\\w\\-./]+$", + "example": "/etc/bacalhau/license.json" } - } + }, + "required": ["LocalPath"] },pkg/swagger/docs.go (1)
2785-2793
: Consider enhancing the license configuration type.While the
types.License
type is well-structured, consider adding:
- Path validation to ensure the license file exists and is readable
- Default path configuration for easier setup
Example enhancement:
type License struct { // LocalPath specifies the local license file path LocalPath string + // DefaultPath specifies the default path to look for license file if LocalPath is empty + DefaultPath string `default:"/etc/bacalhau/license.json"` }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
pkg/publicapi/endpoint/agent/endpoint.go
(4 hunks)pkg/swagger/docs.go
(7 hunks)pkg/swagger/swagger.json
(5 hunks)webui/lib/api/schema/swagger.json
(5 hunks)
🔇 Additional comments (8)
pkg/publicapi/endpoint/agent/endpoint.go (2)
11-11
: Clean dependency injection of the license manager!Good use of dependency injection pattern to make the license manager available to the endpoint.
Also applies to: 23-23, 31-31
Line range hint
34-57
: Well-structured constructor with proper validation!Good practices observed:
- Early validation of required dependencies
- Clear error message
- Proper initialization of the license manager field
webui/lib/api/schema/swagger.json (2)
980-1055
: Well-structured and documented license response schema!The schema:
- Follows JWT standards with proper RFC references
- Includes all necessary license claims
- Has clear field descriptions
112-137
: 🛠️ Refactor suggestionAdd security scheme to the API definition.
The API definition should include:
- Security scheme definition (e.g., ApiKeyAuth)
- Authentication requirement for the endpoint
- 401 response for unauthorized access
Apply this diff:
{ + "securityDefinitions": { + "ApiKeyAuth": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, "paths": { "/api/v1/agent/license": { "get": { "produces": [ "application/json" ], + "security": [ + { + "ApiKeyAuth": [] + } + ], "tags": [ "Ops" ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/apimodels.GetAgentLicenseResponse" } }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + }, "404": { "description": "Not Found", "schema": { "type": "string" } } } } } } }Likely invalid or redundant comment.
pkg/swagger/swagger.json (1)
Line range hint
1-3500
: Verify swagger files stay in sync.This file appears to be a duplicate of webui/lib/api/schema/swagger.json. Ensure both files stay synchronized.
Run this script to verify the files are identical:
✅ Verification successful
Swagger files are properly synchronized
The swagger.json files in
webui/lib/api/schema/
andpkg/swagger/
are identical, confirming they are properly maintained in sync.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if swagger files are in sync # Expected: Files should be identical diff webui/lib/api/schema/swagger.json pkg/swagger/swagger.json if [ $? -eq 0 ]; then echo "Swagger files are in sync" else echo "Warning: Swagger files are out of sync" fiLength of output: 144
pkg/swagger/docs.go (3)
116-141
: Well-structured API endpoint definition!The
/api/v1/agent/license
endpoint follows REST API best practices with clear path structure, appropriate HTTP method, well-defined response codes, and proper documentation.
984-1059
: Comprehensive license response model!The
GetAgentLicenseResponse
type:
- Properly implements JWT standard claims
- Includes essential license information
- Supports extensibility through metadata
- Has clear field descriptions
3172-3173
: Appropriate template delimiter configuration!The addition of explicit template delimiters helps avoid conflicts between Go templates and JSON syntax.
New Command:
bacalhau agent license inspect
This PR introduces a new command that allows users to inspect the license information of a Bacalhau orchestrator node without exposing the license itself. The command provides a secure way to verify license status, capabilities, and metadata while maintaining the confidentiality of the underlying license file.
Features
bacalhau agent license inspect
Add License Manager for Node Orchestration
Introduce a LicenseManager component that handles license validation for orchestrator nodes. Key features:
Usage example:
Security Considerations
License File Structure
The license file, fed to the orchestrator node config, uses a JSON format to support future extensibility and dynamic configuration. The structure is intentionally simple:
We chose JSON format for the license file because:
Configuration
To add a license to an orchestrator, you need to configure your orchestrator node. Here's a sample configuration example:
Key configuration points:
Orchestrator.License.LocalPath
field specifies the path to your license fileExample Usage
Example Output
For
bacalhau agent license inspect
:Product = Bacalhau License ID = 2d58c7c9-ec29-45a5-a5cd-cb8f7fee6678 Customer ID = test-customer-id-123 Valid Until = 2045-07-28 Version = v1 Expired = false Capabilities = max_nodes=1 Metadata = someMetadata=valueOfSomeMetadata
For
bacalhau agent license inspect --output=yaml
:Documentation
Linear: https://linear.app/expanso/issue/ENG-498/license-path-configuration
Summary by CodeRabbit
New Features
Configuration
API Enhancements
Testing