Fail provider-MSP proof when workspace entitlement leases cannot chain-verify

The install proof passed green this morning while every provisioned
workspace ran unlicensed; the entitlement gap survived because nothing
asserted lease health. The workspace proof now reads each workspace's
provisioned billing state and verifies the lease exactly the way a
release-build client runtime will: against the hosted entitlement trust
root, through the provider MSP license chain, requiring white_label.

A present license with an unverifiable lease fails the proof with the
specific reason; the environment-fallback plan (dev, no license) reports
entitlement_skipped_reason=no_provider_msp_license instead of asserting.
Proof and install-proof workspace output lines gain
entitlement_lease_checked/verified, entitlement_white_label, and the
skip reason.
This commit is contained in:
rcourtman 2026-06-10 14:32:14 +01:00
parent a17882458a
commit 87473aa49d
3 changed files with 132 additions and 2 deletions

View file

@ -605,7 +605,7 @@ func printProviderMSPInstallProofReport(report *providerMSPInstallProofReport) {
fmt.Printf("final_status_unhealthy_tenants=%d\n", report.FinalStatusUnhealthyTenants)
fmt.Printf("final_status_stuck_provisioning_tenants=%d\n", report.FinalStatusStuckProvisioningTenants)
for _, workspace := range report.Workspaces {
fmt.Printf("workspace=%s display_name=%q state=%s plan_version=%s container_id=%s public_url=%s install_type=%s install_token_id=%s install_command_generated=%t agent_token_auth_verified=%t setup_facts_token_use_visible=%t agent_report_ingest_verified=%t agent_report_agent_id=%s agent_report_hostname=%s token_rotation_verified=%t rotated_install_token_id=%s old_install_token_rejected=%t rotated_agent_report_verified=%t handoff_exchange_verified=%t handoff_target_path=%s\n",
fmt.Printf("workspace=%s display_name=%q state=%s plan_version=%s container_id=%s public_url=%s install_type=%s install_token_id=%s install_command_generated=%t agent_token_auth_verified=%t setup_facts_token_use_visible=%t agent_report_ingest_verified=%t agent_report_agent_id=%s agent_report_hostname=%s token_rotation_verified=%t rotated_install_token_id=%s old_install_token_rejected=%t rotated_agent_report_verified=%t handoff_exchange_verified=%t handoff_target_path=%s entitlement_lease_checked=%t entitlement_lease_verified=%t entitlement_white_label=%t entitlement_skipped_reason=%s\n",
workspace.TenantID,
workspace.DisplayName,
workspace.State,
@ -626,6 +626,10 @@ func printProviderMSPInstallProofReport(report *providerMSPInstallProofReport) {
workspace.RotatedAgentReportVerified,
workspace.HandoffExchangeVerified,
workspace.HandoffTargetPath,
workspace.EntitlementLeaseChecked,
workspace.EntitlementLeaseVerified,
workspace.EntitlementWhiteLabel,
workspace.EntitlementSkippedReason,
)
}
for _, failure := range report.Failures {

View file

@ -27,6 +27,7 @@ import (
"github.com/rcourtman/pulse-go-rewrite/internal/monitoring"
agentshost "github.com/rcourtman/pulse-go-rewrite/pkg/agents/host"
internalauth "github.com/rcourtman/pulse-go-rewrite/pkg/auth"
pkglicensing "github.com/rcourtman/pulse-go-rewrite/pkg/licensing"
"github.com/spf13/cobra"
)
@ -76,6 +77,10 @@ type providerMSPProofWorkspace struct {
RotatedAgentReportVerified bool
HandoffExchangeVerified bool
HandoffTargetPath string
EntitlementLeaseChecked bool
EntitlementLeaseVerified bool
EntitlementWhiteLabel bool
EntitlementSkippedReason string
}
type providerMSPProofReport struct {
@ -451,6 +456,11 @@ func (rt *providerMSPProofRuntime) proveProviderMSPWorkspace(ctx context.Context
return providerMSPProofWorkspace{}, err
}
entitlement, err := rt.verifyProviderMSPProofEntitlementLease(tenant, tenantDataDir)
if err != nil {
return providerMSPProofWorkspace{}, err
}
return providerMSPProofWorkspace{
TenantID: tenant.ID,
DisplayName: tenant.DisplayName,
@ -474,9 +484,72 @@ func (rt *providerMSPProofRuntime) proveProviderMSPWorkspace(ctx context.Context
RotatedAgentReportVerified: rotation.RotatedAgentReportVerified,
HandoffExchangeVerified: exchangedTargetPath == targetPath,
HandoffTargetPath: exchangedTargetPath,
EntitlementLeaseChecked: entitlement.Checked,
EntitlementLeaseVerified: entitlement.Verified,
EntitlementWhiteLabel: entitlement.WhiteLabel,
EntitlementSkippedReason: entitlement.SkippedReason,
}, nil
}
type providerMSPProofEntitlementLease struct {
Checked bool
Verified bool
WhiteLabel bool
SkippedReason string
}
// verifyProviderMSPProofEntitlementLease verifies the provisioned workspace's
// hosted entitlement lease exactly the way a release-build client runtime
// will: against the embedded entitlement trust root, through the provider
// MSP license chain. The proof previously passed while every workspace ran
// unlicensed; a present license with an unverifiable lease must fail here,
// not in the client's first branded report.
func (rt *providerMSPProofRuntime) verifyProviderMSPProofEntitlementLease(tenant *registry.Tenant, tenantDataDir string) (providerMSPProofEntitlementLease, error) {
result := providerMSPProofEntitlementLease{}
if tenant == nil {
return result, fmt.Errorf("tenant is required")
}
if !rt.cfg.IsProviderHostedMSP() || strings.TrimSpace(rt.cfg.ProviderMSPLicenseKey) == "" {
result.SkippedReason = "no_provider_msp_license"
return result, nil
}
result.Checked = true
state, err := runtimeconfig.NewFileBillingStore(tenantDataDir).GetBillingState("default")
if err != nil {
return result, fmt.Errorf("read provisioned billing state for workspace %s: %w", tenant.ID, err)
}
if state == nil || strings.TrimSpace(state.EntitlementJWT) == "" {
return result, fmt.Errorf("workspace %s was provisioned without a hosted entitlement lease", tenant.ID)
}
if strings.TrimSpace(state.EntitlementRefreshToken) == "" {
return result, fmt.Errorf("workspace %s was provisioned without an entitlement refresh token", tenant.ID)
}
root, err := pkglicensing.HostedEntitlementPublicKey()
if err != nil {
return result, fmt.Errorf("resolve the entitlement verification root a client runtime would use: %w", err)
}
claims, err := pkglicensing.VerifyEntitlementLeaseToken(state.EntitlementJWT, root, "", time.Now().UTC())
if err != nil {
return result, fmt.Errorf("workspace %s entitlement lease does not verify the way a client runtime would: %w", tenant.ID, err)
}
if strings.TrimSpace(claims.ProviderLicense) == "" {
return result, fmt.Errorf("workspace %s entitlement lease does not chain the provider MSP license; release-build client runtimes would reject it", tenant.ID)
}
result.Verified = true
for _, capability := range claims.Capabilities {
if capability == pkglicensing.FeatureWhiteLabel {
result.WhiteLabel = true
break
}
}
if !result.WhiteLabel {
return result, fmt.Errorf("workspace %s entitlement lease is missing white_label; branded client reports would be locked", tenant.ID)
}
return result, nil
}
type providerMSPProofAgentReportIngest struct {
Verified bool
AgentID string
@ -1030,7 +1103,7 @@ func printProviderMSPProofReport(report *providerMSPProofReport) {
fmt.Printf("token_rotation_verified=%t\n", report.TokenRotationVerified)
fmt.Printf("cleanup=%t\n", report.Cleanup)
for _, workspace := range report.Workspaces {
fmt.Printf("workspace=%s display_name=%q state=%s plan_version=%s container_id=%s public_url=%s install_type=%s install_token_id=%s install_command_generated=%t agent_token_auth_verified=%t setup_facts_token_use_visible=%t agent_report_ingest_verified=%t agent_report_agent_id=%s agent_report_hostname=%s token_rotation_verified=%t rotated_install_token_id=%s old_install_token_rejected=%t rotated_agent_report_verified=%t handoff_exchange_verified=%t handoff_target_path=%s\n",
fmt.Printf("workspace=%s display_name=%q state=%s plan_version=%s container_id=%s public_url=%s install_type=%s install_token_id=%s install_command_generated=%t agent_token_auth_verified=%t setup_facts_token_use_visible=%t agent_report_ingest_verified=%t agent_report_agent_id=%s agent_report_hostname=%s token_rotation_verified=%t rotated_install_token_id=%s old_install_token_rejected=%t rotated_agent_report_verified=%t handoff_exchange_verified=%t handoff_target_path=%s entitlement_lease_checked=%t entitlement_lease_verified=%t entitlement_white_label=%t entitlement_skipped_reason=%s\n",
workspace.TenantID,
workspace.DisplayName,
workspace.State,
@ -1051,6 +1124,10 @@ func printProviderMSPProofReport(report *providerMSPProofReport) {
workspace.RotatedAgentReportVerified,
workspace.HandoffExchangeVerified,
workspace.HandoffTargetPath,
workspace.EntitlementLeaseChecked,
workspace.EntitlementLeaseVerified,
workspace.EntitlementWhiteLabel,
workspace.EntitlementSkippedReason,
)
}
}

View file

@ -193,6 +193,15 @@ func TestProviderMSPProofExercisesWorkspaceInstallHandoffAndIsolation(t *testing
if !workspace.HandoffExchangeVerified || workspace.HandoffTargetPath != "/settings/infrastructure?add=linux-host" {
t.Fatalf("handoff exchange proof mismatch: %#v", workspace)
}
if !workspace.EntitlementLeaseChecked {
t.Fatalf("entitlement lease was not checked for %s despite a provider MSP license being configured", workspace.TenantID)
}
if !workspace.EntitlementLeaseVerified {
t.Fatalf("entitlement lease did not chain-verify for %s", workspace.TenantID)
}
if !workspace.EntitlementWhiteLabel {
t.Fatalf("entitlement lease for %s is missing white_label", workspace.TenantID)
}
}
}
@ -250,12 +259,47 @@ func TestProviderMSPProofLoadsSignedLicenseFilePlan(t *testing.T) {
}
}
// mintProviderMSPProofLicense installs a fresh license trust root via env
// (dev builds only) and returns a root-signed MSP license binding the given
// lease signing public key, mirroring what LoadConfig resolves from
// CP_PROVIDER_MSP_LICENSE_FILE in a real deployment.
func mintProviderMSPProofLicense(t *testing.T, planVersion string, leaseSigningPublicKey ed25519.PublicKey) string {
t.Helper()
rootPub, rootPriv, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatalf("GenerateKey root: %v", err)
}
t.Setenv("PULSE_LICENSE_PUBLIC_KEY", base64.StdEncoding.EncodeToString(rootPub))
t.Setenv("PULSE_TRIAL_ACTIVATION_PUBLIC_KEY", base64.StdEncoding.EncodeToString(rootPub))
t.Cleanup(func() { pkglicensing.SetPublicKey(nil) })
pkglicensing.InitEmbeddedPublicKey()
claims := pkglicensing.Claims{
LicenseID: "lic_provider_msp_test",
Email: "provider@example.com",
Tier: pkglicensing.TierMSP,
IssuedAt: time.Now().Add(-time.Minute).Unix(),
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
PlanVersion: planVersion,
EntitlementSigningPublicKey: base64.StdEncoding.EncodeToString(leaseSigningPublicKey),
}
payloadBytes, err := json.Marshal(claims)
if err != nil {
t.Fatalf("Marshal claims: %v", err)
}
header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"EdDSA","typ":"JWT"}`))
payload := base64.RawURLEncoding.EncodeToString(payloadBytes)
signature := base64.RawURLEncoding.EncodeToString(ed25519.Sign(rootPriv, []byte(header+"."+payload)))
return header + "." + payload + "." + signature
}
func testProviderMSPProofConfig(t *testing.T) *cloudcp.CPConfig {
t.Helper()
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
t.Fatalf("GenerateKey: %v", err)
}
licenseKey := mintProviderMSPProofLicense(t, "msp_growth", publicKey)
return &cloudcp.CPConfig{
DataDir: t.TempDir(),
Environment: "development",
@ -273,6 +317,7 @@ func testProviderMSPProofConfig(t *testing.T) *cloudcp.CPConfig {
ProviderMSPPlanSource: cloudcp.ProviderMSPPlanSourceLicenseFile,
ProviderMSPLicenseID: "lic_provider_msp_test",
ProviderMSPLicenseEmail: "provider@example.com",
ProviderMSPLicenseKey: licenseKey,
TrialActivationPrivateKey: base64.StdEncoding.EncodeToString(privateKey),
TrialActivationPublicKey: base64.StdEncoding.EncodeToString(publicKey),
EmailFrom: "noreply@example.com",
@ -309,6 +354,10 @@ func writeProviderMSPProofLicenseForTest(t *testing.T, licenseID, email, planVer
t.Fatalf("GenerateKey: %v", err)
}
t.Setenv("PULSE_LICENSE_PUBLIC_KEY", base64.StdEncoding.EncodeToString(publicKey))
// Release binaries embed one key as both the license root and the hosted
// entitlement verification root; mirror that so the proof's lease
// verification can resolve a root in dev test builds.
t.Setenv("PULSE_TRIAL_ACTIVATION_PUBLIC_KEY", base64.StdEncoding.EncodeToString(publicKey))
t.Setenv("PULSE_LICENSE_DEV_MODE", "false")
t.Cleanup(func() { pkglicensing.SetPublicKey(nil) })