Replicated Ship: How does licensing work?

I’m familiar with licensing in Replicated Platform, including features like

  • Expiration Dates
  • Custom license fields

How do these features work when I’m packaging a proprietary (non-OSS) app in Replicated Ship?

Trust Models

To start, its important to understand the different trust models that Ship can enforce.

High Trust

You’ve enforced licensing with a contract, and/or you trust your customer not to reverse-engineer your product to change license fields like Number of user seats or Expiration Date.

This is the simplest trust model to implement. In this case, your customer’s license key gives them access to pull assets like YAML and Docker images, and from that point they will deploy those assets to their cluster. Minimal effort is required to inspect the YAML and change environment variables or config files.

An example might look like

assets: # assets declares zip bundles, k8s yaml, docker images, etc.
  v1:
    - inline:
        when: ‘{{repl eq (EntitlementValue “ordered_app_k8s”) “true”}}’
        contents: |
              apiVersion: apps/v1

              ...

              env:
                  # inject individual values
                  name: NUM_SEATS
                  value: ‘{{repl EntitlementValue “num_seats”}}’

Low Trust

In the low-trust model, Entitlements should be served at runtime, and will be cryptographically signed with a unique private key during application configuration.

This is more effort to implement when packaging your application, as you need to add logic to your application code to query an embedded licensing API at runtime, and verify the payload signature.

If you embed the public signing certificate in your source code, the effort required (at a minimum) to reverse-engineer this would involve a customer decompiling source, modifying one or more string values, and then recompiling to something executable.

You can query the full signed payload with the Entitlements template function:

assets: # assets declares zip bundles, k8s yaml, docker images, etc.
  v1:
    - inline:
            when: ‘{{repl eq (EntitlementValue “ordered_app_k8s”) “true”}}’
            contents: |
              apiVersion: apps/v1

              ...

                env: 
                  # inject the whole payload with all the values,
                  # verify the signature in your app at runtime
                  name: SIGNED_LICENSE_PAYLOAD
                  value: ‘{{repl Entitlements | Base64Encode}}’

There is also a guide for running the embedded licensing server.