Skip to content

Commit ad959a9

Browse files
authored
Merge pull request #3064 from redpanda-data/allow-trial-licenses
Allow trial licenses to be considered valid
2 parents 65763d9 + cac2c15 commit ad959a9

File tree

5 files changed

+38
-27
lines changed

5 files changed

+38
-27
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ Changelog
33

44
All notable changes to this project will be documented in this file.
55

6+
## 4.44.0 - TBD
7+
8+
### Fixed
9+
10+
- Trial Redpanda Enterprise licenses are now considered valid. (@Jeffail)
11+
612
## 4.43.0 - 2024-12-05
713

814
### Changed

internal/license/redpanda_license.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ type RedpandaLicense struct {
2727

2828
// AllowsEnterpriseFeatures returns true if license type allows enterprise features.
2929
func (r *RedpandaLicense) AllowsEnterpriseFeatures() bool {
30-
return r.Type == 1
30+
// Right now any enterprise or trial license that was valid when we started
31+
// is considered valid here.
32+
return r.Type == 1 || r.Type == 0
3133
}
3234

3335
func typeDisplayName(t int) string {

internal/license/service.go

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ var licensePublicKeyPem []byte
3333

3434
const defaultLicenseFilepath = "/etc/redpanda/redpanda.license"
3535

36+
var openSourceLicense = RedpandaLicense{
37+
Type: -1,
38+
Expiry: time.Now().Add(time.Hour * 24 * 365 * 10).Unix(),
39+
}
40+
3641
// Service is the license service.
3742
type Service struct {
3843
logger *service.Logger
@@ -101,30 +106,18 @@ func InjectTestService(res *service.Resources) {
101106
func (s *Service) readAndValidateLicense() (RedpandaLicense, error) {
102107
licenseBytes, err := s.readLicense()
103108
if err != nil {
104-
return RedpandaLicense{}, err
109+
return openSourceLicense, err
105110
}
106111

107-
var license RedpandaLicense
112+
license := openSourceLicense
108113
if len(licenseBytes) > 0 {
109114
if license, err = s.validateLicense(licenseBytes); err != nil {
110-
return RedpandaLicense{}, fmt.Errorf("failed to validate license: %w", err)
111-
}
112-
if license.Type == 0 {
113-
// If the license is a trial then we reject it because connect does
114-
// not support trials.
115-
return RedpandaLicense{}, errors.New("trial license detected, Redpanda Connect does not support enterprise license trials")
116-
}
117-
} else {
118-
// An open source license is the final fall back.
119-
year := time.Hour * 24 * 365
120-
license = RedpandaLicense{
121-
Expiry: time.Now().Add(10 * year).Unix(),
122-
Type: -1,
115+
return openSourceLicense, fmt.Errorf("failed to validate license: %w", err)
123116
}
124117
}
125118

126119
if err := license.CheckExpiry(); err != nil {
127-
return RedpandaLicense{}, err
120+
return openSourceLicense, err
128121
}
129122

130123
s.logger.With(
@@ -175,11 +168,11 @@ func (s *Service) validateLicense(license []byte) (RedpandaLicense, error) {
175168
block, _ := pem.Decode(publicKeyBytes)
176169
publicKey, err := x509.ParsePKIXPublicKey(block.Bytes)
177170
if err != nil {
178-
return RedpandaLicense{}, fmt.Errorf("failed to parse public key: %w", err)
171+
return openSourceLicense, fmt.Errorf("failed to parse public key: %w", err)
179172
}
180173
publicKeyRSA, ok := publicKey.(*rsa.PublicKey)
181174
if !ok {
182-
return RedpandaLicense{}, errors.New("failed to parse public key, expected dateFormat is not RSA")
175+
return openSourceLicense, errors.New("failed to parse public key, expected dateFormat is not RSA")
183176
}
184177

185178
// Trim Whitespace and Linebreaks for input license
@@ -188,32 +181,32 @@ func (s *Service) validateLicense(license []byte) (RedpandaLicense, error) {
188181
// 2. Split license contents by delimiter
189182
splitParts := bytes.Split(license, []byte("."))
190183
if len(splitParts) != 2 {
191-
return RedpandaLicense{}, errors.New("failed to split license contents by delimiter")
184+
return openSourceLicense, errors.New("failed to split license contents by delimiter")
192185
}
193186

194187
licenseDataEncoded := splitParts[0]
195188
signatureEncoded := splitParts[1]
196189

197190
licenseData, err := base64.StdEncoding.DecodeString(string(licenseDataEncoded))
198191
if err != nil {
199-
return RedpandaLicense{}, fmt.Errorf("failed to decode license data: %w", err)
192+
return openSourceLicense, fmt.Errorf("failed to decode license data: %w", err)
200193
}
201194

202195
signature, err := base64.StdEncoding.DecodeString(string(signatureEncoded))
203196
if err != nil {
204-
return RedpandaLicense{}, fmt.Errorf("failed to decode license signature: %w", err)
197+
return openSourceLicense, fmt.Errorf("failed to decode license signature: %w", err)
205198
}
206199
hash := sha256.Sum256(licenseDataEncoded)
207200

208201
// 3. Verify license contents with static public key
209202
if err := rsa.VerifyPKCS1v15(publicKeyRSA, crypto.SHA256, hash[:], signature); err != nil {
210-
return RedpandaLicense{}, fmt.Errorf("failed to verify license signature: %w", err)
203+
return openSourceLicense, fmt.Errorf("failed to verify license signature: %w", err)
211204
}
212205

213206
// 4. If license contents seem to be legit, we will continue unpacking the license
214207
var rpLicense RedpandaLicense
215208
if err := json.Unmarshal(licenseData, &rpLicense); err != nil {
216-
return RedpandaLicense{}, fmt.Errorf("failed to unmarshal license data: %w", err)
209+
return openSourceLicense, fmt.Errorf("failed to unmarshal license data: %w", err)
217210
}
218211

219212
return rpLicense, nil

internal/license/service_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ func TestLicenseEnterpriseValidation(t *testing.T) {
7171
},
7272
IsEnterprise: false,
7373
},
74+
{
75+
Name: "open source license",
76+
License: RedpandaLicense{
77+
Version: 3,
78+
Organization: "meow",
79+
Type: -1,
80+
Expiry: time.Now().Add(time.Hour).Unix(),
81+
},
82+
IsEnterprise: false,
83+
},
7484
{
7585
Name: "free trial license",
7686
License: RedpandaLicense{
@@ -79,7 +89,7 @@ func TestLicenseEnterpriseValidation(t *testing.T) {
7989
Type: 0,
8090
Expiry: time.Now().Add(time.Hour).Unix(),
8191
},
82-
IsEnterprise: false,
92+
IsEnterprise: true,
8393
},
8494
{
8595
Name: "enterprise license",
@@ -199,7 +209,7 @@ func TestLicenseEnterpriseExplicit(t *testing.T) {
199209
_, license = createLicense(t, RedpandaLicense{
200210
Version: 3,
201211
Organization: "meow",
202-
Type: 0,
212+
Type: -1,
203213
Expiry: time.Now().Add(time.Hour).Unix(),
204214
})
205215
require.NoError(t, os.WriteFile(tmpAlsoBadLicensePath, []byte(license), 0o777))

internal/license/shared_service.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func CheckRunningEnterprise(res *service.Resources) error {
4040
return err
4141
}
4242
if !l.AllowsEnterpriseFeatures() {
43-
return errors.New("this feature requires a valid Redpanda Enterprise Edition license from https://redpanda.com/try-enterprise?origin=rpcn. For more information check out: https://docs.redpanda.com/current/get-started/licenses/")
43+
return errors.New("this feature requires a valid Redpanda Enterprise Edition license from https://redpanda.com/try-enterprise?origin=rpcn. For more information check out: https://docs.redpanda.com/redpanda-connect/get-started/licensing/")
4444
}
4545
return nil
4646
}

0 commit comments

Comments
 (0)