Skip to content
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 Replicated as a Gitpod license evaluator #8211

Merged
merged 3 commits into from
Feb 25, 2022
Merged

Conversation

mrsimonemms
Copy link
Contributor

@mrsimonemms mrsimonemms commented Feb 15, 2022

Description

For the purpose of this, "enterprise" means any user that has a paid-for license

Replicated is how we will now distribute Gitpod to enterprise teams. This adds Replicated as a licensor and is used if the secret has type = replicated (which sets the envvar GITPOD_LICENSE_TYPE=replicated in the server).

This PR also renames the Evaluator as GitpodEvaluator and introduces an Evaluator interface, which the GitpodEvaluator and ReplicatedEvaluator implements. The GitpodEvaluator will remain in-place for existing customers (eventually, will migrate to Replicated) and also for SaaS.

Like the Gitpod license, the Replicated license is only validated at runtime. If the user wishes to update their license, they would have to click "sync license" in their Kots portal which would tell them to redeploy the application - this would create a new server pod which would verify the new license at runtime.

Unlike the Gitpod license, the Replicated license is retrieved from a local service and has no (obvious) way of verifying the data is from a legitimate source, rather than a mocked service. For that reason, the URL is hardcoded as per the docs and offers no way of configuring this.

The license has three custom entitlements - domain, levelId and seats. An entitlement is custom data that's attached to the license. These are used to provide the data that we use for validation.

Future improvements

Talk with Replicated and establish a way of verifying that the data is valid and from an approved source. Replicated provides a signature which has an innerSignature which has a public key and signature but this verification is entirely undocumented.

We may also want to verify community licenses slightly differently, eg without the domain so we can just have a single community license. NB it may be tricky for a user to go from community to paid if we have a single license - this will need raising with Replicated

Resources

Related Issue(s)

Fixes gitpod-io/replicated#1

How to test

Release Notes

Add Replicated as a Gitpod license evaluator

Documentation

@codecov
Copy link

codecov bot commented Feb 15, 2022

Codecov Report

Merging #8211 (fc318ea) into main (adf6a32) will increase coverage by 7.75%.
The diff coverage is 68.80%.

❗ Current head fc318ea differs from pull request most recent head 896fe39. Consider uploading reports for the commit 896fe39 to get more accurate results

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #8211      +/-   ##
==========================================
+ Coverage   12.31%   20.06%   +7.75%     
==========================================
  Files          20       22       +2     
  Lines        1161     1171      +10     
==========================================
+ Hits          143      235      +92     
+ Misses       1014      919      -95     
- Partials        4       17      +13     
Flag Coverage Δ
components-gitpod-cli-app 11.17% <ø> (ø)
components-licensor-lib 69.66% <68.80%> (?)
components-local-app-app-darwin-amd64 ?
components-local-app-app-darwin-arm64 ?
components-local-app-app-linux-amd64 ?
components-local-app-app-linux-arm64 ?
components-local-app-app-windows-386 ?
components-local-app-app-windows-amd64 ?
components-local-app-app-windows-arm64 ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
components/licensor/ee/pkg/licensor/licensor.go 78.04% <ø> (ø)
components/licensor/ee/pkg/licensor/replicated.go 62.12% <62.12%> (ø)
components/licensor/ee/pkg/licensor/gitpod.go 76.27% <76.27%> (ø)
components/local-app/pkg/auth/pkce.go
components/local-app/pkg/auth/auth.go
components/licensor/ee/pkg/licensor/keys.go 50.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update adf6a32...896fe39. Read the comment docs.

@mrsimonemms mrsimonemms force-pushed the sje/replicated-licence branch 3 times, most recently from 015ad0d to 30f98c9 Compare February 15, 2022 12:17
@roboquat roboquat added size/XL and removed size/M labels Feb 17, 2022
@mrsimonemms mrsimonemms force-pushed the sje/replicated-licence branch 9 times, most recently from f86182b to f7f38a9 Compare February 17, 2022 22:07
@mrsimonemms mrsimonemms changed the title Use Replicated license as the Gitpod license Add Replicated as a Gitpod licensor Feb 18, 2022
@mrsimonemms mrsimonemms force-pushed the sje/replicated-licence branch from f7f38a9 to 1b3d816 Compare February 18, 2022 16:36
@roboquat roboquat added size/XXL and removed size/XL labels Feb 18, 2022
@mrsimonemms mrsimonemms marked this pull request as ready for review February 18, 2022 17:09
@mrsimonemms mrsimonemms requested review from a team February 18, 2022 17:09
@github-actions github-actions bot added the team: delivery Issue belongs to the self-hosted team label Feb 18, 2022
@corneliusludmann
Copy link
Contributor

Quick test with a valid license looks good.

However, I'm pretty unhappy that an invalid license would prevent using Gitpod at all. In my opinion, with an invalid license, we should also fallback like there is no license (not only for the Replicated license but also for the Gitpod license but the latter is not so important at the moment), which means basically using the default built-in license when the license is invalid:

var defaultLicense = LicensePayload{
ID: "default-license",
Level: LevelTeam,
Seats: 10,
// Domain, ValidUntil are free for all
}

I think it's odd that an installation with an expired license or with a license for another domain is in a worse position than an installation with no license at all.

That means, in my opinion, a test like this one:

{"Replicated: invalid license within default seats", 50, 5, true, false, true, LicenseTypeReplicated, false},

added here should succeed and not fail (we don't have this test with a wrong domain but that should work as well).

And there is also an actual need for such a behavior: When we want to publish a generic community license, we need to ignore the domain at least. Because this license needs to work with all domains. However, for this use case, we should probably think about making the domain value optional.

@mrsimonemms
Copy link
Contributor Author

mrsimonemms commented Feb 21, 2022

So, from a Replicated point-of-view, we can't get through the license gate in their UI with an invalid/expired license. I am fully in agreement that this is a retrograde step and it's one of the things I've scheduled to discuss with them in our weekly meeting.

With regards to the community license, I'm forming the opinion that we're not going to be able to have a single license for all community members. See the "future improvements" section of this PR and #8329 for details. Again, this is scheduled for discussion with Replicated.

If we've gotten through the initial Replicated license gate in their UI, an expired/invalid license gives the default license. Ticket #8328 exists to make this default license match what we advertise (either free or community, dependent upon the number of seats in use)

I've added that test in you put in

One thing I'm not overly happy with is what happens if the newReplicatedEvaluator returns an error - I can't log the error AND return the default license as the interface doesn't support error and default license. I've maintained the error as-per the GitpodEvaluator but could be convinced the other way.

@mrsimonemms mrsimonemms force-pushed the sje/replicated-licence branch 3 times, most recently from 99ad50b to 82dd964 Compare February 22, 2022 11:36
Simon Emms added 2 commits February 23, 2022 10:14
If field(s) not found, it returns a warning rather than an error
Defaults to "gitpod" and allows "replicated". This is defined
by the secret
@mrsimonemms mrsimonemms force-pushed the sje/replicated-licence branch from 82dd964 to a31a39b Compare February 23, 2022 10:16
Copy link
Contributor

@corneliusludmann corneliusludmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this heavily and it works pretty well. I think that's a very good first iteration that we can ship. However, I would like to add a few issues for follow-up pull requests. Stay tuned … 😆

components/licensor/ee/cmd/validate.go Outdated Show resolved Hide resolved
@mrsimonemms
Copy link
Contributor Author

Thanks @corneliusludmann. I'm definitely seeing this as the first iteration of many in the licensing epic

@mrsimonemms
Copy link
Contributor Author

/hold

@mrsimonemms
Copy link
Contributor Author

mrsimonemms commented Feb 23, 2022

Have checked that this still works with the original license, which it does

/unhold

@corneliusludmann
Copy link
Contributor

corneliusludmann commented Feb 23, 2022

@mrsimonemms: You haven't touched the helm charts but changed the server deployment in the installer, right? Would that break SaaS deployment for team WebApp (as far as I know, they still use the helm charts)?

@mrsimonemms
Copy link
Contributor Author

@corneliusludmann I don't believe so. It defaults to the Gitpod evaluator and only uses the Replicated one if the secret tells it to

@geropl
Copy link
Member

geropl commented Feb 25, 2022

Starting to review now...

{"within default license seats", 0, 7, true, true, false},
{"within default license seats (edge)", 0, 10, true, true, false},
{"beyond default license seats", 0, 11, false, true, false},
{"Gitpod: unlimited seats", 0, 1000, true, false, false, LicenseTypeGitpod, false},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@@ -53,7 +54,6 @@ func deployment(ctx *common.RenderContext) ([]runtime.Object, error) {
Name: "gitpod-license-key",
MountPath: licenseFilePath,
SubPath: "license",
ReadOnly: true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? 🤔 Maybe it make sense to make that explicit here, and add a comment that states why that is required?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguably not, but it feels prudent to make readonly values explicitly readonly to me

Copy link
Member

@geropl geropl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LG - and nicely clean - TM, thx!

/hold

In case you might want to add a comment

@mrsimonemms
Copy link
Contributor Author

Thanks @geropl - much appreciated you checking it out

@mrsimonemms
Copy link
Contributor Author

/unhold

@roboquat roboquat merged commit 30fc465 into main Feb 25, 2022
@roboquat roboquat deleted the sje/replicated-licence branch February 25, 2022 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-note size/XXL team: delivery Issue belongs to the self-hosted team team: webapp Issue belongs to the WebApp team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorporate Gitpod licence into Replicated licence
5 participants