Documentation
¶
Index ¶
Constants ¶
const ( // LicensePayloadAnnotation is the annotation key under which a signed license's payload // bytes (base64-encoded) can be relayed onto another object (e.g. SveltosCluster), for // components that cannot reach the sveltos-license Secret directly. LicensePayloadAnnotation = "license.projectsveltos.io/payload" // LicenseSignatureAnnotation is the annotation key under which a signed license's // signature bytes (base64-encoded) can be relayed alongside LicensePayloadAnnotation. LicenseSignatureAnnotation = "license.projectsveltos.io/signature" )
const ( // FeaturePullMode is the ability to manage cluster behing firewalls FeaturePullMode = Features("PullMode") // FeatureMCP is the ability to use Sveltos MCP Server FeatureMCP = Features("MCP") // FeaturePromotion is the ability to use Sveltos ClusterPromotion FeaturePromotion = Features("Promotion") // FeatureJobHealthCheck is the ability to use a Job as a ValidateHealth check FeatureJobHealthCheck = Features("JobHealthCheck") // FeatureNamespaceScopedAgents is the ability to run drift-detection-manager and // sveltos-agent (agentless mode) restricted to watching a configured set of namespaces, // instead of cluster-wide. FeatureNamespaceScopedAgents = Features("NamespaceScopedAgents") )
const ( PlanEnterprise = Plan("Enterprise") PlanEnterprisePlus = Plan("EnterprisePlus") )
Variables ¶
This section is empty.
Functions ¶
func GetPublicKey ¶
func MigrateLicenseSecretType ¶ added in v1.15.0
func MigrateLicenseSecretType(ctx context.Context, c client.Client, sveltosNamespace string, logger logr.Logger) error
MigrateLicenseSecretType is a one-time, idempotent migration: addon-controller v1.14.0 scopes its Secret cache to ClusterProfileSecretType, so any Secret of a different type is invisible to that cache and every read of it returns a false NotFound. Installs that created the sveltos-license Secret before that change have it as Opaque, which silently breaks every license check (JobCheck, ClusterPromotion) after upgrading. type is immutable on a Secret, so this fixes it by recreating: read the existing data, delete, recreate with the corrected type. No-op if the Secret doesn't exist yet (no license installed) or already has the correct type. Requires get/delete/create permission on Secrets in sveltosNamespace.
Types ¶
type Features ¶
type Features string
Features is all features requiring a license +kubebuilder:validation:Enum:=PullMode;MCP;Promotion;JobHealthCheck;NamespaceScopedAgents
type LicensePayload ¶
type LicensePayload struct {
// ID is a unique identifier for this specific license.
ID string `json:"id"`
// CustomerName is the name of the customer the license is issued to.
CustomerName string `json:"customerName"`
// Features is a list of feature strings enabled by this license.
Features []Features `json:"features"`
// Specify the type of plan
// +optional
Plan Plan `json:"plan,omitempty"`
// ExpirationDate is the exact time when the license expires.
ExpirationDate time.Time `json:"expirationDate"`
// GracePeriodDays specifies the number of days the license remains functional
// after its expiration date, during which warnings are issued.
// +optional
GracePeriodDays int `json:"gracePeriodDays,omitempty"`
// MaxClusters is the maximum number of clusters allowed for this license (optional).
// +optional
MaxClusters int `json:"maxClusters,omitempty"`
// IssuedAt is the timestamp when the license was generated and signed.
IssuedAt time.Time `json:"issuedAt"`
// ClusterFingerprint is a unique identifier derived from the target Kubernetes cluster.
// +optional
ClusterFingerprint string `json:"clusterFingerprint,omitempty"`
}
LicensePayload defines the internal structure of the data that gets signed and embedded within the Kubernetes Secret.
func (*LicensePayload) HasFeature ¶ added in v1.13.0
func (lp *LicensePayload) HasFeature(feature Features) bool
HasFeature reports whether feature is allowed by this license.
An empty Features list means the license predates (or was issued without) per-feature restriction: every feature is allowed, and callers should fall back to their own Plan/ MaxClusters-based checks. A non-empty Features list is an explicit allowlist — it must contain feature — and this takes precedence over any other bypass (e.g. MaxClusters == 0 for unlimited clusters, or Plan tier): a license scoped to specific features stays scoped to them regardless of what other entitlements it grants.
type LicenseVerificationResult ¶
type LicenseVerificationResult struct {
Payload *LicensePayload // The decoded license payload if found and unmarshaled
PayloadData []byte // The exact signed payload bytes, set once the signature has verified
SignatureData []byte // The signature bytes matching PayloadData
IsValid bool // True if license is fully valid
IsExpired bool // True if license is expired (either grace or enforced)
IsInGracePeriod bool // True if license is expired but within grace period
IsEnforced bool // True if license is expired and fully enforced
Message string // A human-readable message about the license status
RawError error // The underlying error (e.g., secret not found, unmarshal error, signature error)
// Unknown is true when the license state could not be determined at all -- e.g. the
// Secret couldn't be read because the apiserver was unreachable, not because it's
// genuinely absent (that case is IsExpired/IsEnforced with RawError satisfying
// apierrors.IsNotFound, not this). IsExpired/IsEnforced are still set true alongside it,
// for existing callers that don't check Unknown and should keep today's conservative
// "treat anything but a clean read as not entitled" behavior. Callers that can afford to
// be more precise -- e.g. ones that cache a previous verdict across periodic re-checks --
// should check Unknown first and, when true, leave that previous verdict alone rather
// than treating "couldn't check" as "checked and denied".
Unknown bool
}
LicenseVerificationResult encapsulates the outcome of the license verification.
func VerifyLicensePayload ¶ added in v1.14.0
func VerifyLicensePayload(payloadData, signatureData []byte, publicKey *rsa.PublicKey, logger logr.Logger) LicenseVerificationResult
VerifyLicensePayload verifies a license's digital signature against publicKey and, if valid, unmarshals and checks its expiration. Unlike VerifyLicenseSecret, it does not read a Secret and does not check the cluster fingerprint (that check needs a client into the specific cluster the license is meant for) — callers that need fingerprint validation should use VerifyLicenseSecret, or call verifyClusterFingerprint-equivalent logic themselves. This is meant for components that receive the payload/signature bytes relayed from elsewhere (e.g. via LicensePayloadAnnotation/LicenseSignatureAnnotation) rather than reading the sveltos-license Secret directly.
func VerifyLicenseSecret ¶
func VerifyLicenseSecret(ctx context.Context, c client.Client, sveltosNamespace string, publicKey *rsa.PublicKey, logger logr.Logger) LicenseVerificationResult
VerifyLicenseSecret attempts to decode and verify the license secret. It returns a LicenseVerificationResult struct containing the license payload (if found) and various booleans indicating its validity status, along with a human-readable message. The RawError field will contain any technical errors encountered during the process. Requires permission to read Secret in projectsveltos namespace.