-
Notifications
You must be signed in to change notification settings - Fork 90
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
base: main
Are you sure you want to change the base?
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)
"/api/v1/agent/license": { | ||
"get": { | ||
"produces": [ | ||
"application/json" | ||
], | ||
"tags": [ | ||
"Ops" | ||
], | ||
"summary": "Returns the details of the current configured orchestrator license.", | ||
"operationId": "agent/license", | ||
"responses": { | ||
"200": { | ||
"description": "OK", | ||
"schema": { | ||
"$ref": "#/definitions/license.LicenseClaims" | ||
} | ||
}, | ||
"404": { | ||
"description": "Node license not configured", | ||
"schema": { | ||
"type": "string" | ||
} | ||
}, | ||
"500": { | ||
"description": "Internal Server Error", | ||
"schema": { | ||
"type": "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.
🛠️ Refactor suggestion
Add authentication requirement to license endpoint.
The license endpoint may expose sensitive information. Consider:
- Adding authentication requirement
- Implementing rate limiting
- Adding appropriate security headers
Apply this diff to add authentication:
"/api/v1/agent/license": {
"get": {
"produces": [
"application/json"
],
+ "security": [
+ {
+ "ApiKeyAuth": []
+ }
+ ],
"tags": [
"Ops"
],
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
"/api/v1/agent/license": { | |
"get": { | |
"produces": [ | |
"application/json" | |
], | |
"tags": [ | |
"Ops" | |
], | |
"summary": "Returns the details of the current configured orchestrator license.", | |
"operationId": "agent/license", | |
"responses": { | |
"200": { | |
"description": "OK", | |
"schema": { | |
"$ref": "#/definitions/license.LicenseClaims" | |
} | |
}, | |
"404": { | |
"description": "Node license not configured", | |
"schema": { | |
"type": "string" | |
} | |
}, | |
"500": { | |
"description": "Internal Server Error", | |
"schema": { | |
"type": "string" | |
} | |
} | |
} | |
} | |
}, | |
"/api/v1/agent/license": { | |
"get": { | |
"produces": [ | |
"application/json" | |
], | |
"security": [ | |
{ | |
"ApiKeyAuth": [] | |
} | |
], | |
"tags": [ | |
"Ops" | |
], | |
"summary": "Returns the details of the current configured orchestrator license.", | |
"operationId": "agent/license", | |
"responses": { | |
"200": { | |
"description": "OK", | |
"schema": { | |
"$ref": "#/definitions/license.LicenseClaims" | |
} | |
}, | |
"404": { | |
"description": "Node license not configured", | |
"schema": { | |
"type": "string" | |
} | |
}, | |
"500": { | |
"description": "Internal Server Error", | |
"schema": { | |
"type": "string" | |
} | |
} | |
} | |
} | |
}, |
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
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
: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