keygen

package module
v1.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2022 License: MIT Imports: 19 Imported by: 1

README

Keygen Go SDK godoc reference

Package keygen allows Go programs to license and remotely update themselves using the keygen.sh service.

Config

keygen.Account

Account is your Keygen account ID used globally in the binding. All requests will be made to this account. This should be hard-coded into your app.

keygen.Account = "1fddcec8-8dd3-4d8d-9b16-215cac0f9b52"
keygen.Product

Product is your Keygen product ID used globally in the binding. All license validations and upgrade requests will be scoped to this product. This should be hard-coded into your app.

keygen.Product = "1f086ec9-a943-46ea-9da4-e62c2180c2f4"
keygen.LicenseKey

LicenseKey a license key belonging to the end-user (licensee). This will be used for license validations, activations, deactivations and upgrade requests. You will need to prompt the end-user for this value.

You will need to set the license policy's authentication strategy to LICENSE or MIXED.

Setting LicenseKey will take precedence over Token.

keygen.LicenseKey = "C1B6DE-39A6E3-DE1529-8559A0-4AF593-V3"
keygen.Token

Token is an activation token belonging to the licensee. This will be used for license validations, activations, deactivations and upgrade requests. You will need to prompt the end-user for this.

You will need to set the license policy's authentication strategy to TOKEN or MIXED.

keygen.Token = "activ-d66e044ddd7dcc4169ca9492888435d3v3"
keygen.PublicKey

PublicKey is your Keygen account's hex-encoded Ed25519 public key, used for verifying signed license keys and API response signatures. When set, API response signatures will automatically be verified. You may leave it blank to skip verifying response signatures. This should be hard-coded into your app.

keygen.PublicKey = "e8601e48b69383ba520245fd07971e983d06d22c4257cfd82304601479cee788"
keygen.Channel

Channel is the release channel used when checking for upgrades. Defaults to stable. You may provide a different channel, one of: stable, rc, beta, alpha or dev.

keygen.Channel = "dev"
keygen.Platform

Platform is the release platform used when checking for upgrades and when activating machines. Defaults to runtime.GOOS + "/" + runtime.GOARCH. You may provide a custom platform.

keygen.Platform = "win32"
keygen.UpgradeKey

UpgradeKey is your personal hex-encoded Ed25519ph public key, used for verifying that an upgrade was signed by yourself or your team using your private publishing key. This should not be equal to keygen.PublicKey — they are different keys for different purposes. When set, a release's signature will be verified before an upgrade is installed. This should be hard-coded into your app.

You can generate a publishing key pair using Keygen's CLI.

keygen.UpgradeKey = "5ec69b78d4b5d4b624699cef5faf3347dc4b06bb807ed4a2c6740129f1db7159"
keygen.Logger

Logger is a leveled logger implementation used for printing debug, informational, warning, and error messages. The default log level is LogLevelError. You may provide your own logger which implements LoggerInterface.

keygen.Logger = &CustomLogger{Level: LogLevelDebug}

Usage

keygen.Validate(fingerprint)

To validate a license, configure keygen.Account and keygen.Product with your Keygen account details. Then prompt the user for their license token and set keygen.Token.

The Validate method accepts zero or more fingerprints, which can be used to scope a license validation to a particular fingerprint. It will return a License object as well as any validation errors that occur. The License object can be used to perform additional actions, such as license.Activate(fingerprint).

license, err := keygen.Validate(fingerprint)
switch {
case err == keygen.ErrLicenseNotActivated:
  fmt.Println("License is not activated!")

  return
case err == keygen.ErrLicenseExpired:
  fmt.Println("License is expired!")

  return
case err != nil:
  fmt.Println("License is invalid!")

  return
}

fmt.Println("License is valid!")
keygen.Upgrade(currentVersion)

Check for an upgrade. When an upgrade is available, a Release will be returned which will allow the update to be installed, replacing the currently running binary. When an upgrade is not available, an ErrUpgradeNotAvailable error will be returned indicating the current version is up-to-date.

release, err := keygen.Upgrade(currentVersion)
switch {
case err == keygen.ErrUpgradeNotAvailable:
  fmt.Println("No upgrade available, already at the latest version!")

  return
case err != nil:
  fmt.Println("Upgrade check failed!")

  return
}

if err := release.Install(); err != nil {
  fmt.Println("Upgrade install failed!")

  return
}

fmt.Println("Upgrade complete! Please restart.")
keygen.Genuine(licenseKey, schemeCode)

Cryptographically verify and decode a signed license key. This is useful for checking if a license key is genuine in offline or air-gapped environments. Returns the key's decoded dataset and any errors that occurred during cryptographic verification, e.g. ErrLicenseNotGenuine.

Requires that keygen.PublicKey is set.

dataset, err := keygen.Genuine(licenseKey, keygen.SchemeCodeEd25519)
switch {
case err == keygen.ErrLicenseNotGenuine:
  fmt.Println("License key is not genuine!")

  return
case err != nil:
  fmt.Println("Genuine check failed!")

  return
}

fmt.Println("License is genuine!")
fmt.Printf("Decoded dataset: %s\n", dataset)

Examples

License activation example
package main

import "github.com/keygen-sh/keygen-go"

func main() {
  keygen.Account = os.Getenv("KEYGEN_ACCOUNT")
  keygen.Product = os.Getenv("KEYGEN_PRODUCT")
  keygen.Token = os.Getenv("KEYGEN_TOKEN")

  // The current device's fingerprint (could be e.g. MAC, mobo ID, GUID, etc.)
  fingerprint := uuid.New().String()

  // Validate the license for the current fingerprint
  license, err := keygen.Validate(fingerprint)
  switch {
  case err == keygen.ErrLicenseNotActivated:
    // Activate the current fingerprint
    machine, err := license.Activate(fingerprint)
    switch {
    case err == keygen.ErrMachineLimitExceeded:
      fmt.Println("Machine limit has been exceeded!")

      return
    case err != nil:
      fmt.Println("Machine activation failed!")

      return
    }
  case err == keygen.ErrLicenseExpired:
    fmt.Println("License is expired!")

    return
  case err != nil:
    fmt.Println("License is invalid!")

    return
  }

  fmt.Println("License is activated!")
}
Automatic upgrade example
package main

import "github.com/keygen-sh/keygen-go"

// The current version of the program
const currentVersion = "1.0.0"

func main() {
  keygen.Account = os.Getenv("KEYGEN_ACCOUNT")
  keygen.Product = os.Getenv("KEYGEN_PRODUCT")
  keygen.Token = os.Getenv("KEYGEN_TOKEN")

  fmt.Printf("Current version: %s\n", currentVersion)
  fmt.Println("Checking for upgrades...")

  // Check for upgrade
  release, err := keygen.Upgrade(currentVersion)
  switch {
  case err == keygen.ErrUpgradeNotAvailable:
    fmt.Println("No upgrade available, already at the latest version!")

    return
  case err != nil:
    fmt.Println("Upgrade check failed!")

    return
  }

  // Download the upgrade and install it
  err = release.Install()
  if err != nil {
    fmt.Println("Upgrade install failed!")

    return
  }

  fmt.Printf("Upgrade complete! Installed version: %s\n", release.Version)
  fmt.Println("Restart to finish installation...")
}
Machine heartbeats example
package main

import "github.com/keygen-sh/keygen-go"

func main() {
  keygen.Account = os.Getenv("KEYGEN_ACCOUNT")
  keygen.Product = os.Getenv("KEYGEN_PRODUCT")
  keygen.Token = os.Getenv("KEYGEN_TOKEN")

  // The current device's fingerprint (could be e.g. MAC, mobo ID, GUID, etc.)
  fingerprint := uuid.New().String()

  // Keep our example process alive
  done := make(chan bool, 1)

  // Validate the license for the current fingerprint
  license, err := keygen.Validate(fingerprint)
  switch {
  case err == keygen.ErrLicenseNotActivated:
    // Activate the current fingerprint
    machine, err := license.Activate(fingerprint)
    if err != nil {
      fmt.Println("Machine activation failed!")

      panic(err)
    }

    // Handle SIGINT and gracefully deactivate the machine
    sigs := make(chan os.Signal, 1)

    signal.Notify(sigs, os.Interrupt)

    go func() {
      for sig := range sigs {
        fmt.Printf("Caught %v, deactivating machine and gracefully exiting...\n", sig)

        if err := machine.Deactivate(); err != nil {
          fmt.Println("Machine deactivation failed!")

          panic(err)
        }

        fmt.Println("Machine was deactivated!")
        fmt.Println("Exiting...")

        done <- true
      }
    }()

    // Start a heartbeat monitor for the current machine
    errs := machine.Monitor()

    go func() {
      err := <-errs

      // We want to kill the current process if our heartbeat ping fails
      panic(err)
    }()

    fmt.Println("Machine is activated and monitored!")
  case err != nil:
    fmt.Println("License is invalid!")

    panic(err)
  }

  fmt.Println("License is valid!")

  <-done
}

Documentation

Overview

Package keygen allows programs to license and remotely update themselves using the keygen.sh service.

Index

Constants

View Source
const (
	// The current version of the SDK.
	SDKVersion = "1.13.0"
)

Variables

View Source
var (
	ErrLicenseTokenInvalid      = errors.New("token authentication is invalid")
	ErrLicenseKeyInvalid        = errors.New("license key authentication is invalid")
	ErrMachineAlreadyActivated  = errors.New("machine is already activated")
	ErrMachineLimitExceeded     = errors.New("machine limit has been exceeded")
	ErrMachineHeartbeatRequired = errors.New("machine heartbeat is required")
	ErrMachineHeartbeatDead     = errors.New("machine heartbeat is dead")
	ErrNotAuthorized            = errors.New("token is not authorized to perform the request")
	ErrNotFound                 = errors.New("resource does not exist")
)
View Source
var (
	// APIURL is the URL of the API service backend.
	APIURL = "https://api.keygen.sh"

	// APIVersion is the currently supported API version.
	APIVersion = "v1"

	// Account is the Keygen account ID used globally in the binding.
	Account string

	// Product is the Keygen product ID used globally in the binding.
	Product string

	// LicenseKey is the end-user's license key used in the binding.
	LicenseKey string

	// Token is the end-user's API token used in the binding.
	Token string

	// PublicKey is the Keygen public key used for verifying license keys
	// and API response signatures.
	PublicKey string

	// UpgradeKey is a developer's public key used for verifying that an
	// upgrade was signed by the developer. You can generate an upgrade
	// key using Keygen's CLI.
	UpgradeKey string

	// Channel is the release channel used when checking for upgrades.
	Channel = "stable"

	// Platform is the release platform used when checking for upgrades
	// and when activating machines.
	Platform = runtime.GOOS + "/" + runtime.GOARCH

	// UserAgent defines the user-agent string sent to the API backend,
	// uniquely identifying an integration.
	UserAgent string

	// Logger is a leveled logger implementation used for printing debug,
	// informational, warning, and error messages.
	Logger LoggerInterface = &LeveledLogger{Level: LogLevelError}
)
View Source
var (
	ErrLicenseNotActivated    = errors.New("license is not activated")
	ErrLicenseExpired         = errors.New("license is expired")
	ErrLicenseSuspended       = errors.New("license is suspended")
	ErrLicenseTooManyMachines = errors.New("license has too many machines")
	ErrLicenseTooManyCores    = errors.New("license has too many cores")
	ErrLicenseNotSigned       = errors.New("license is not signed")
	ErrLicenseInvalid         = errors.New("license is invalid")
	ErrFingerprintMissing     = errors.New("fingerprint scope is missing")
	ErrProductMissing         = errors.New("product scope is missing")
)
View Source
var (
	ErrHeartbeatPingFailed = errors.New("machine heartbeat ping failed")
	ErrMachineNotFound     = errors.New("machine no longer exists")
)
View Source
var (
	ErrLicenseSchemeNotSupported = errors.New("license scheme is not supported")
	ErrLicenseSchemeMissing      = errors.New("license scheme is missing")
	ErrLicenseKeyMissing         = errors.New("license key is missing")
	ErrLicenseNotGenuine         = errors.New("license key is not genuine")
	ErrResponseSignatureMissing  = errors.New("response signature is missing")
	ErrResponseSignatureInvalid  = errors.New("response signature is invalid")
	ErrResponseDigestMissing     = errors.New("response digest is missing")
	ErrResponseDigestInvalid     = errors.New("response digest is invalid")
	ErrResponseDateInvalid       = errors.New("response date is invalid")
	ErrResponseDateTooOld        = errors.New("response date is too old")
	ErrPublicKeyMissing          = errors.New("public key is missing")
	ErrPublicKeyInvalid          = errors.New("public key is invalid")
)
View Source
var (
	ErrReleaseLocationMissing = errors.New("release has no download URL")
)
View Source
var (
	ErrUpgradeNotAvailable = errors.New("no upgrades available (already up-to-date)")
)
View Source
var (
	// Filetype is the release filetype used when checking for upgrades.
	Filetype = "bin"
)

Functions

func Genuine

func Genuine(licenseKey string, signingScheme SchemeCode) ([]byte, error)

Genuine checks if a license key is genuine by cryptographically verifying the key using your PublicKey. If the key is genuine, the decoded dataset from the key will be returned. An error will be returned if the key is not genuine or otherwise invalid, e.g. ErrLicenseNotGenuine.

Types

type Artifact

type Artifact struct {
	ID        string    `json:"-"`
	Type      string    `json:"-"`
	Key       string    `json:"key"`
	Created   time.Time `json:"created"`
	Updated   time.Time `json:"updated"`
	ReleaseId string    `json:"-"`
}

Artifact represents a Keygen artifact object.

func (*Artifact) SetData

func (a *Artifact) SetData(to func(target interface{}) error) error

func (*Artifact) SetID

func (a *Artifact) SetID(id string) error

Implement jsonapi.UnmarshalData interface

func (*Artifact) SetRelationships

func (a *Artifact) SetRelationships(relationships map[string]interface{}) error

func (*Artifact) SetType

func (a *Artifact) SetType(t string) error

type Client

type Client struct {
	Account    string
	LicenseKey string
	Token      string
	PublicKey  string
	UserAgent  string
}

func (*Client) Delete

func (c *Client) Delete(path string, params interface{}, model interface{}) (*Response, error)

func (*Client) Get

func (c *Client) Get(path string, params interface{}, model interface{}) (*Response, error)

func (*Client) Patch

func (c *Client) Patch(path string, params interface{}, model interface{}) (*Response, error)

func (*Client) Post

func (c *Client) Post(path string, params interface{}, model interface{}) (*Response, error)

func (*Client) Put

func (c *Client) Put(path string, params interface{}, model interface{}) (*Response, error)

type Entitlement

type Entitlement struct {
	ID       string                 `json:"-"`
	Type     string                 `json:"-"`
	Code     EntitlementCode        `json:"code"`
	Created  time.Time              `json:"created"`
	Updated  time.Time              `json:"updated"`
	Metadata map[string]interface{} `json:"metadata"`
}

Entitlement represents a Keygen entitlement object.

func (*Entitlement) SetData

func (e *Entitlement) SetData(to func(target interface{}) error) error

func (*Entitlement) SetID

func (e *Entitlement) SetID(id string) error

Implement jsonapi.UnmarshalData interface

func (*Entitlement) SetType

func (e *Entitlement) SetType(t string) error

type EntitlementCode added in v1.2.0

type EntitlementCode string

type Entitlements

type Entitlements []Entitlement

Entitlements represents an array of entitlement objects.

func (*Entitlements) SetData

func (e *Entitlements) SetData(to func(target interface{}) error) error

Implement jsonapi.UnmarshalData interface

type ErrorCode

type ErrorCode string
const (
	ErrorCodeTokenInvalid         ErrorCode = "TOKEN_INVALID"
	ErrorCodeLicenseInvalid       ErrorCode = "LICENSE_INVALID"
	ErrorCodeFingerprintTaken     ErrorCode = "FINGERPRINT_TAKEN"
	ErrorCodeMachineLimitExceeded ErrorCode = "MACHINE_LIMIT_EXCEEDED"
	ErrorCodeMachineHeartbeatDead ErrorCode = "MACHINE_HEARTBEAT_DEAD"
	ErrorCodeNotFound             ErrorCode = "NOT_FOUND"
)

type HeartbeatStatusCode added in v1.0.1

type HeartbeatStatusCode string
const (
	HeartbeatStatusCodeNotStarted  HeartbeatStatusCode = "NOT_STARTED"
	HeartbeatStatusCodeAlive       HeartbeatStatusCode = "ALIVE"
	HeartbeatStatusCodeDead        HeartbeatStatusCode = "DEAD"
	HeartbeatStatusCodeResurrected HeartbeatStatusCode = "RESURRECTED"
)

type LeveledLogger added in v1.7.0

type LeveledLogger struct {
	Level LogLevel
}

func (*LeveledLogger) Debugf added in v1.7.0

func (l *LeveledLogger) Debugf(format string, v ...interface{})

func (*LeveledLogger) Errorf added in v1.7.0

func (l *LeveledLogger) Errorf(format string, v ...interface{})

func (*LeveledLogger) Infof added in v1.7.0

func (l *LeveledLogger) Infof(format string, v ...interface{})

func (*LeveledLogger) Warnf added in v1.7.0

func (l *LeveledLogger) Warnf(format string, v ...interface{})

type License

type License struct {
	ID            string                 `json:"-"`
	Type          string                 `json:"-"`
	Name          string                 `json:"name"`
	Key           string                 `json:"key"`
	Expiry        *time.Time             `json:"expiry"`
	Scheme        SchemeCode             `json:"scheme"`
	LastValidated *time.Time             `json:"lastValidated"`
	Created       time.Time              `json:"created"`
	Updated       time.Time              `json:"updated"`
	Metadata      map[string]interface{} `json:"metadata"`
	PolicyId      string                 `json:"-"`
}

License represents a Keygen license object.

func Validate

func Validate(fingerprints ...string) (*License, error)

Validate performs a license validation using the current Token, scoped to any provided fingerprints. It returns a License, and an error if the license is invalid, e.g. ErrLicenseNotActivated or ErrLicenseExpired.

func (*License) Activate

func (l *License) Activate(fingerprint string) (*Machine, error)

Activate performs a machine activation for the license, identified by the provided fingerprint. If the activation is successful, the new machine will be returned. An error will be returned if the activation fails, e.g. ErrMachineLimitExceeded or ErrMachineAlreadyActivated.

func (*License) Deactivate

func (l *License) Deactivate(id string) error

Deactivate performs a machine deactivation, identified by the provided ID. The ID can be the machine's UUID or the machine's fingerprint. An error will be returned if the machine deactivation fails.

func (*License) Entitlements

func (l *License) Entitlements() (Entitlements, error)

Machines lists up to 100 entitlements for the license.

func (*License) Genuine

func (l *License) Genuine() ([]byte, error)

Genuine checks if the license's key is genuine by cryptographically verifying the key using your PublicKey. If the license is genuine, the decoded dataset from the key will be returned. An error will be returned if the license is not genuine, or if the key is not signed, e.g. ErrLicenseNotGenuine or ErrLicenseNotSigned.

func (*License) Machine added in v1.5.0

func (l *License) Machine(id string) (*Machine, error)

Machine retreives a machine, identified by the provided ID. The ID can be the machine's UUID or the machine's fingerprint. An error will be returned if it does not exist.

func (*License) Machines

func (l *License) Machines() (Machines, error)

Machines lists up to 100 machines for the license.

func (*License) SetData

func (l *License) SetData(to func(target interface{}) error) error

func (*License) SetID

func (l *License) SetID(id string) error

Implement jsonapi.UnmarshalData interface

func (*License) SetRelationships

func (l *License) SetRelationships(relationships map[string]interface{}) error

func (*License) SetType

func (l *License) SetType(t string) error

func (*License) Validate

func (l *License) Validate(fingerprints ...string) error

Validate performs a license validation, scoped to any provided fingerprints. It returns an error if the license is invalid, e.g. ErrLicenseNotActivated, ErrLicenseExpired or ErrLicenseTooManyMachines.

type LogLevel added in v1.7.0

type LogLevel uint32
const (
	LogLevelNone LogLevel = iota
	LogLevelError
	LogLevelWarn
	LogLevelInfo
	LogLevelDebug
)

type LoggerInterface added in v1.7.0

type LoggerInterface interface {
	// Debugf logs a debug message using Printf conventions.
	Debugf(format string, v ...interface{})

	// Errorf logs a warning message using Printf conventions.
	Errorf(format string, v ...interface{})

	// Infof logs an informational message using Printf conventions.
	Infof(format string, v ...interface{})

	// Warnf logs a warning message using Printf conventions.
	Warnf(format string, v ...interface{})
}

LoggerInterface provides a basic leveled logging interface for printing debug, informational, warning, and error messages.

type Machine

type Machine struct {
	ID                string                 `json:"-"`
	Type              string                 `json:"-"`
	Name              string                 `json:"name"`
	Fingerprint       string                 `json:"fingerprint"`
	Hostname          string                 `json:"hostname"`
	Platform          string                 `json:"platform"`
	Cores             int                    `json:"cores"`
	HeartbeatStatus   HeartbeatStatusCode    `json:"heartbeatStatus"`
	HeartbeatDuration int                    `json:"heartbeatDuration"`
	Created           time.Time              `json:"created"`
	Updated           time.Time              `json:"updated"`
	Metadata          map[string]interface{} `json:"metadata"`
	LicenseID         string                 `json:"-"`
}

Machine represents a Keygen machine object.

func (*Machine) Deactivate

func (m *Machine) Deactivate() error

Deactivate performs a machine deactivation for the current Machine. An error will be returned if the machine deactivation fails.

func (Machine) GetData

func (m Machine) GetData() interface{}

func (Machine) GetID

func (m Machine) GetID() string

Implement jsonapi.MarshalData interface

func (Machine) GetType

func (m Machine) GetType() string

func (*Machine) Monitor

func (m *Machine) Monitor() chan error

Monitor performs, on a loop, a machine hearbeat ping for the current Machine. An error channel will be returned, where any ping errors will be emitted. Pings are sent according to the machine's required heartbeat window, minus 30 seconds to account for any network lag.

func (*Machine) SetData

func (m *Machine) SetData(to func(target interface{}) error) error

func (*Machine) SetID

func (m *Machine) SetID(id string) error

Implement jsonapi.UnmarshalData interface

func (*Machine) SetType

func (m *Machine) SetType(t string) error

type Machines

type Machines []Machine

Machines represents an array of machine objects.

func (*Machines) SetData

func (m *Machines) SetData(to func(target interface{}) error) error

Implement jsonapi.UnmarshalData interface

type Release

type Release struct {
	ID          string                 `json:"-"`
	Type        string                 `json:"-"`
	Name        string                 `json:"name"`
	Description string                 `json:"description"`
	Version     string                 `json:"version"`
	Filename    string                 `json:"filename"`
	Filetype    string                 `json:"filetype"`
	Filesize    int64                  `json:"filesize"`
	Platform    string                 `json:"platform"`
	Channel     string                 `json:"channel"`
	Signature   string                 `json:"signature"`
	Checksum    string                 `json:"checksum"`
	Created     time.Time              `json:"created"`
	Updated     time.Time              `json:"updated"`
	Metadata    map[string]interface{} `json:"metadata"`
	Location    string                 `json:"-"`
}

Release represents a Keygen release object.

func Upgrade

func Upgrade(currentVersion string) (*Release, error)

func (*Release) Install

func (r *Release) Install() error

Install performs an update of the current executable to the new Release.

func (*Release) SetData

func (r *Release) SetData(to func(target interface{}) error) error

func (*Release) SetID

func (r *Release) SetID(id string) error

Implement jsonapi.UnmarshalData interface

func (*Release) SetType

func (r *Release) SetType(t string) error

type Response

type Response struct {
	ID       string
	Method   string
	URL      string
	Headers  http.Header
	Document *jsonapi.Document
	Size     int
	Body     []byte
	Status   int
}

type SchemeCode added in v1.1.0

type SchemeCode string
const (
	SchemeCodeEd25519 SchemeCode = "ED25519_SIGN"
)

type ValidationCode

type ValidationCode string
const (
	ValidationCodeValid                    ValidationCode = "VALID"
	ValidationCodeNotFound                 ValidationCode = "NOT_FOUND"
	ValidationCodeSuspended                ValidationCode = "SUSPENDED"
	ValidationCodeExpired                  ValidationCode = "EXPIRED"
	ValidationCodeOverdue                  ValidationCode = "OVERDUE"
	ValidationCodeNoMachine                ValidationCode = "NO_MACHINE"
	ValidationCodeNoMachines               ValidationCode = "NO_MACHINES"
	ValidationCodeTooManyMachines          ValidationCode = "TOO_MANY_MACHINES"
	ValidationCodeTooManyCores             ValidationCode = "TOO_MANY_CORES"
	ValidationCodeFingerprintScopeRequired ValidationCode = "FINGERPRINT_SCOPE_REQUIRED"
	ValidationCodeFingerprintScopeMismatch ValidationCode = "FINGERPRINT_SCOPE_MISMATCH"
	ValidationCodeFingerprintScopeEmpty    ValidationCode = "FINGERPRINT_SCOPE_EMPTY"
	ValidationCodeHeartbeatNotStarted      ValidationCode = "HEARTBEAT_NOT_STARTED"
	ValidationCodeHeartbeatDead            ValidationCode = "HEARTBEAT_DEAD"
	ValidationCodeProductScopeRequired     ValidationCode = "PRODUCT_SCOPE_REQUIRED"
	ValidationCodeProductScopeEmpty        ValidationCode = "PRODUCT_SCOPE_MISMATCH"
	ValidationCodePolicyScopeRequired      ValidationCode = "POLICY_SCOPE_REQUIRED"
	ValidationCodePolicyScopeMismatch      ValidationCode = "POLICY_SCOPE_MISMATCH"
	ValidationCodeMachineScopeRequired     ValidationCode = "MACHINE_SCOPE_REQUIRED"
	ValidationCodeMachineScopeMismatch     ValidationCode = "MACHINE_SCOPE_MISMATCH"
	ValidationCodeEntitlementsMissing      ValidationCode = "ENTITLEMENTS_MISSING"
	ValidationCodeEntitlementsEmpty        ValidationCode = "ENTITLEMENTS_SCOPE_EMPTY"
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL