Skip to content

Commit 1865300

Browse files
crdantclaudeemosbaugh
authored
Shifts license verification upstream (#5699)
* chore(deps): update kotskinds to support new entitlement API Updates kotskinds dependency to a version that includes wrapper methods for accessing entitlement values, which simplifies handling of both v1beta1 and v1beta2 license formats. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(license): delegate signature verification to kotskinds Removes ~320 lines of duplicate verification logic by delegating to the kotskinds library's built-in VerifySignature() method. This consolidates signature verification in a single location and reduces maintenance burden. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * refactor(license): adapt to kotskinds entitlement value API changes Updates code to use GetValue() method which returns interface{} instead of accessing internal Value struct fields. This change supports both v1beta1 and v1beta2 license formats through the unified wrapper interface. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * test: update tests for kotskinds API changes Removes tests that are now covered by kotskinds library's internal verification. Fixes import ordering and test formatting to align with the updated API. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: fix indentation and formatting Corrects whitespace and indentation to match project style guidelines. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Uses correct kotskinds * Update pkg/handlers/license.go Co-authored-by: Ethan Mosbaugh <ethan@replicated.com> * Update pkg/handlers/license.go Co-authored-by: Ethan Mosbaugh <ethan@replicated.com> * Update pkg/handlers/license.go Co-authored-by: Ethan Mosbaugh <ethan@replicated.com> * Quick syntax fix * Reformats --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ethan Mosbaugh <ethan@replicated.com>
1 parent ba9fe42 commit 1865300

12 files changed

Lines changed: 76 additions & 524 deletions

File tree

cmd/kots/cli/install.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ func InstallCmd() *cobra.Command {
205205
} else if !v.GetBool("airgap") {
206206
applicationMetadata, err = pull.PullApplicationMetadata(upstream, license, v.GetString("app-version-label"))
207207
if err != nil {
208-
log.Error(err)
208+
log.Error(err)
209209
// application metadata is required for embedded cluster installations
210210
if util.IsEmbeddedCluster() {
211211
return errors.Wrap(err, "failed to pull application metadata")

go.mod

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ require (
5252
github.com/pkg/errors v0.9.1
5353
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
5454
github.com/replicatedhq/embedded-cluster/kinds v1.15.1-0.20250729184643-f055e67a064d
55-
github.com/replicatedhq/kotskinds v0.0.0-20251106194120-8ae701787e22
55+
github.com/replicatedhq/kotskinds v0.0.0-20251202215158-294aceff2380
5656
github.com/replicatedhq/kurlkinds v1.5.0
5757
github.com/replicatedhq/troubleshoot v0.122.0
5858
github.com/robfig/cron v1.2.0
@@ -79,18 +79,18 @@ require (
7979
gopkg.in/ini.v1 v1.67.0
8080
gopkg.in/yaml.v2 v2.4.0
8181
helm.sh/helm/v3 v3.19.0
82-
k8s.io/api v0.34.1
83-
k8s.io/apimachinery v0.34.1
82+
k8s.io/api v0.34.2
83+
k8s.io/apimachinery v0.34.2
8484
k8s.io/cli-runtime v0.34.1
85-
k8s.io/client-go v0.34.1
85+
k8s.io/client-go v0.34.2
8686
k8s.io/cluster-bootstrap v0.34.1
8787
k8s.io/helm v2.17.0+incompatible
8888
k8s.io/kubelet v0.34.1
8989
k8s.io/metrics v0.34.1
9090
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
9191
oras.land/oras-go/v2 v2.6.0
9292
sigs.k8s.io/application v0.8.3
93-
sigs.k8s.io/controller-runtime v0.22.3
93+
sigs.k8s.io/controller-runtime v0.22.4
9494
sigs.k8s.io/kustomize/api v0.20.1
9595
sigs.k8s.io/kustomize/kyaml v0.20.1
9696
sigs.k8s.io/yaml v1.6.0
@@ -354,9 +354,9 @@ require (
354354
google.golang.org/protobuf v1.36.10 // indirect
355355
gopkg.in/inf.v0 v0.9.1 // indirect
356356
gopkg.in/warnings.v0 v0.1.2 // indirect
357-
k8s.io/apiextensions-apiserver v0.34.1 // indirect
358-
k8s.io/apiserver v0.34.1 // indirect
359-
k8s.io/component-base v0.34.1 // indirect
357+
k8s.io/apiextensions-apiserver v0.34.2 // indirect
358+
k8s.io/apiserver v0.34.2 // indirect
359+
k8s.io/component-base v0.34.2 // indirect
360360
k8s.io/klog/v2 v2.130.1 // indirect
361361
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
362362
k8s.io/kubectl v0.34.0

go.sum

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,8 +1189,8 @@ github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRl
11891189
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
11901190
github.com/replicatedhq/embedded-cluster/kinds v1.15.1-0.20250729184643-f055e67a064d h1:Wl0fHoWTcrveqbWmDVEPFoa/K3EzyROC8tjHZxzwg3Q=
11911191
github.com/replicatedhq/embedded-cluster/kinds v1.15.1-0.20250729184643-f055e67a064d/go.mod h1:gZdtXCAVJt0a5Ry64Jlaeph7qh+IGsAkq4P0PE6XiZI=
1192-
github.com/replicatedhq/kotskinds v0.0.0-20251106194120-8ae701787e22 h1:WXzSYpKmNtTHk7W1nQXYVYWIv6pRtjs2rarVVJZ9cfw=
1193-
github.com/replicatedhq/kotskinds v0.0.0-20251106194120-8ae701787e22/go.mod h1:+k4PHo2wukoU9kdiKrqqgi89Wmj+9AiwppYGVK11zig=
1192+
github.com/replicatedhq/kotskinds v0.0.0-20251202215158-294aceff2380 h1:c5hnM6zpxVYZk/wCzGKsbABiBVpFHqQ08T5RXP7wLHQ=
1193+
github.com/replicatedhq/kotskinds v0.0.0-20251202215158-294aceff2380/go.mod h1:hpR1pZ3mEtbMrl/tmuqNjK+cSBcmb8F7A1EPhXwssfI=
11941194
github.com/replicatedhq/kurlkinds v1.5.0 h1:zZ0PKNeh4kXvSzVGkn62DKTo314GxhXg1TSB3azURMc=
11951195
github.com/replicatedhq/kurlkinds v1.5.0/go.mod h1:rUpBMdC81IhmJNCWMU/uRsMETv9P0xFoMvdSP/TAr5A=
11961196
github.com/replicatedhq/termui/v3 v3.1.1-0.20200811145416-f40076d26851 h1:eRlNDHxGfVkPCRXbA4BfQJvt5DHjFiTtWy3R/t4djyY=
@@ -1922,34 +1922,34 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
19221922
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
19231923
k8s.io/api v0.0.0-20190918155943-95b840bb6a1f/go.mod h1:uWuOHnjmNrtQomJrvEBg0c0HRNyQ+8KTEERVsK0PW48=
19241924
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
1925-
k8s.io/api v0.34.1 h1:jC+153630BMdlFukegoEL8E/yT7aLyQkIVuwhmwDgJM=
1926-
k8s.io/api v0.34.1/go.mod h1:SB80FxFtXn5/gwzCoN6QCtPD7Vbu5w2n1S0J5gFfTYk=
1925+
k8s.io/api v0.34.2 h1:fsSUNZhV+bnL6Aqrp6O7lMTy6o5x2C4XLjnh//8SLYY=
1926+
k8s.io/api v0.34.2/go.mod h1:MMBPaWlED2a8w4RSeanD76f7opUoypY8TFYkSM+3XHw=
19271927
k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY=
19281928
k8s.io/apiextensions-apiserver v0.17.0/go.mod h1:XiIFUakZywkUl54fVXa7QTEHcqQz9HG55nHd1DCoHj8=
1929-
k8s.io/apiextensions-apiserver v0.34.1 h1:NNPBva8FNAPt1iSVwIE0FsdrVriRXMsaWFMqJbII2CI=
1930-
k8s.io/apiextensions-apiserver v0.34.1/go.mod h1:hP9Rld3zF5Ay2Of3BeEpLAToP+l4s5UlxiHfqRaRcMc=
1929+
k8s.io/apiextensions-apiserver v0.34.2 h1:WStKftnGeoKP4AZRz/BaAAEJvYp4mlZGN0UCv+uvsqo=
1930+
k8s.io/apiextensions-apiserver v0.34.2/go.mod h1:398CJrsgXF1wytdaanynDpJ67zG4Xq7yj91GrmYN2SE=
19311931
k8s.io/apimachinery v0.0.0-20190913080033-27d36303b655/go.mod h1:nL6pwRT8NgfF8TT68DBI8uEePRt89cSvoXUVqbkWHq4=
19321932
k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
1933-
k8s.io/apimachinery v0.34.1 h1:dTlxFls/eikpJxmAC7MVE8oOeP1zryV7iRyIjB0gky4=
1934-
k8s.io/apimachinery v0.34.1/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
1933+
k8s.io/apimachinery v0.34.2 h1:zQ12Uk3eMHPxrsbUJgNF8bTauTVR2WgqJsTmwTE/NW4=
1934+
k8s.io/apimachinery v0.34.2/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
19351935
k8s.io/apiserver v0.0.0-20190918160949-bfa5e2e684ad/go.mod h1:XPCXEwhjaFN29a8NldXA901ElnKeKLrLtREO9ZhFyhg=
19361936
k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg=
1937-
k8s.io/apiserver v0.34.1 h1:U3JBGdgANK3dfFcyknWde1G6X1F4bg7PXuvlqt8lITA=
1938-
k8s.io/apiserver v0.34.1/go.mod h1:eOOc9nrVqlBI1AFCvVzsob0OxtPZUCPiUJL45JOTBG0=
1937+
k8s.io/apiserver v0.34.2 h1:2/yu8suwkmES7IzwlehAovo8dDE07cFRC7KMDb1+MAE=
1938+
k8s.io/apiserver v0.34.2/go.mod h1:gqJQy2yDOB50R3JUReHSFr+cwJnL8G1dzTA0YLEqAPI=
19391939
k8s.io/cli-runtime v0.34.1 h1:btlgAgTrYd4sk8vJTRG6zVtqBKt9ZMDeQZo2PIzbL7M=
19401940
k8s.io/cli-runtime v0.34.1/go.mod h1:aVA65c+f0MZiMUPbseU/M9l1Wo2byeaGwUuQEQVVveE=
19411941
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
19421942
k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k=
1943-
k8s.io/client-go v0.34.1 h1:ZUPJKgXsnKwVwmKKdPfw4tB58+7/Ik3CrjOEhsiZ7mY=
1944-
k8s.io/client-go v0.34.1/go.mod h1:kA8v0FP+tk6sZA0yKLRG67LWjqufAoSHA2xVGKw9Of8=
1943+
k8s.io/client-go v0.34.2 h1:Co6XiknN+uUZqiddlfAjT68184/37PS4QAzYvQvDR8M=
1944+
k8s.io/client-go v0.34.2/go.mod h1:2VYDl1XXJsdcAxw7BenFslRQX28Dxz91U9MWKjX97fE=
19451945
k8s.io/cluster-bootstrap v0.34.1 h1:lyCwJKoeYzGI93vk5Sn/Gz2rzfTRXkRuZYOk2rUsHfA=
19461946
k8s.io/cluster-bootstrap v0.34.1/go.mod h1:9EJfkp7Fu4YBU0F6ysvrI5TndWLo8zufmDSjIWBNd94=
19471947
k8s.io/code-generator v0.0.0-20190912054826-cd179ad6a269/go.mod h1:V5BD6M4CyaN5m+VthcclXWsVcT1Hu+glwa1bi3MIsyE=
19481948
k8s.io/code-generator v0.17.0/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s=
19491949
k8s.io/component-base v0.0.0-20190918160511-547f6c5d7090/go.mod h1:933PBGtQFJky3TEwYx4aEPZ4IxqhWh3R6DCmzqIn1hA=
19501950
k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc=
1951-
k8s.io/component-base v0.34.1 h1:v7xFgG+ONhytZNFpIz5/kecwD+sUhVE6HU7qQUiRM4A=
1952-
k8s.io/component-base v0.34.1/go.mod h1:mknCpLlTSKHzAQJJnnHVKqjxR7gBeHRv0rPXA7gdtQ0=
1951+
k8s.io/component-base v0.34.2 h1:HQRqK9x2sSAsd8+R4xxRirlTjowsg6fWCPwWYeSvogQ=
1952+
k8s.io/component-base v0.34.2/go.mod h1:9xw2FHJavUHBFpiGkZoKuYZ5pdtLKe97DEByaA+hHbM=
19531953
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
19541954
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
19551955
k8s.io/helm v2.17.0+incompatible h1:Bpn6o1wKLYqKM3+Osh8e+1/K2g/GsQJ4F4yNF2+deao=
@@ -1997,8 +1997,8 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
19971997
sigs.k8s.io/application v0.8.3 h1:5UETobiVhxTkKn3pIESImXiMNmSg3VkM5+JvmYGDPko=
19981998
sigs.k8s.io/application v0.8.3/go.mod h1:Mv+ht9RE/QNtITYCzRbt3XTIN6t6so6cInmiyg6wOIg=
19991999
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
2000-
sigs.k8s.io/controller-runtime v0.22.3 h1:I7mfqz/a/WdmDCEnXmSPm8/b/yRTy6JsKKENTijTq8Y=
2001-
sigs.k8s.io/controller-runtime v0.22.3/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
2000+
sigs.k8s.io/controller-runtime v0.22.4 h1:GEjV7KV3TY8e+tJ2LCTxUTanW4z/FmNB7l327UfMq9A=
2001+
sigs.k8s.io/controller-runtime v0.22.4/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
20022002
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
20032003
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
20042004
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=

pkg/handlers/license.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,24 +224,24 @@ func getLicenseEntitlements(license *licensewrapper.LicenseWrapper) ([]Entitleme
224224
// Use wrapper method to get entitlements (works for both v1beta1 and v1beta2)
225225
for key, entitlement := range license.GetEntitlements() {
226226
if key == "expires_at" {
227-
if entitlement.GetValue().StrVal == "" {
227+
strVal, _ := entitlement.GetValue().(string)
228+
if strVal == "" {
228229
continue
229230
}
230231

231-
expiration, err := time.Parse(time.RFC3339, entitlement.GetValue().StrVal)
232+
expiration, err := time.Parse(time.RFC3339, strVal)
232233
if err != nil {
233234
return nil, time.Time{}, errors.Wrap(err, "failed to parse expiration date")
234235
}
235236
expiresAt = expiration
236237
} else if key == "gitops_enabled" {
237238
/* do nothing */
238239
} else if !entitlement.IsHidden() {
239-
val := entitlement.GetValue()
240240
entitlements = append(entitlements,
241241
EntitlementResponse{
242242
Title: entitlement.GetTitle(),
243243
Label: key,
244-
Value: (&val).Value(),
244+
Value: entitlement.GetValue(),
245245
ValueType: entitlement.GetValueType(),
246246
})
247247
}
@@ -597,18 +597,17 @@ func (h *Handler) GetPlatformLicenseCompatibility(w http.ResponseWriter, r *http
597597

598598
for k, e := range license.GetEntitlements() {
599599
if k == "expires_at" {
600-
if e.GetValue().StrVal != "" {
601-
platformLicense.ExpirationTime = e.GetValue().StrVal
600+
if v, _ := e.GetValue().(string); v != "" {
601+
platformLicense.ExpirationTime = v
602602
}
603603
continue
604604
}
605605

606-
val := e.GetValue()
607606
field := licenseFieldType{
608607
Field: k,
609608
Title: e.GetTitle(),
610609
Type: e.GetValueType(),
611-
Value: (&val).Value(),
610+
Value: e.GetValue(),
612611
HideFromCustomer: e.IsHidden(),
613612
}
614613

pkg/kotsadmlicense/serviceaccount_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55
"encoding/json"
66
"testing"
77

8-
"github.com/stretchr/testify/assert"
9-
"github.com/stretchr/testify/require"
108
kotsv1beta1 "github.com/replicatedhq/kotskinds/apis/kots/v1beta1"
119
"github.com/replicatedhq/kotskinds/pkg/licensewrapper"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
1212
)
1313

1414
func TestValidateServiceAccountToken(t *testing.T) {

pkg/license/license.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,15 @@ func LicenseIsExpired(license *licensewrapper.LicenseWrapper) (bool, error) {
2121
if val.GetValueType() != "" && val.GetValueType() != "String" {
2222
return false, errors.Errorf("expires_at must be type String: %s", val.GetValueType())
2323
}
24-
if val.GetValue().StrVal == "" {
24+
expiry, ok := val.GetValue().(string)
25+
if !ok {
26+
return false, errors.New("expires_at value is not a string")
27+
}
28+
if expiry == "" {
2529
return false, nil
2630
}
2731

28-
parsed, err := time.Parse(time.RFC3339, val.GetValue().StrVal)
32+
parsed, err := time.Parse(time.RFC3339, expiry)
2933
if err != nil {
3034
return false, errors.Wrap(err, "failed to parse expiration time")
3135
}

0 commit comments

Comments
 (0)