Product license verification in Console (#518)

Operator UI - Provide and store License key
- New License section in Operator UI will allow user to provide the
  license key via input form
- New License section in Operator UI will allow the user to fetch the
  license key using subnet credentials
-  Console backend has to verify provided license is valid -
   https://godoc.org/github.com/minio/minio/pkg/licverifier#example-package
-  Console backend has to store the license key in k8s secrets

Operator UI - Set license to tenant during provisioning
- Check if license key exists in k8s secret during tenant creation
- If License is present attach the license-key jwt to the new console
tenant via an environment variable

Operator UI - Set license for an existing tenant
- Tenant view will display information about the current status of the
  Tenant License
- If Tenant doesn't have a License then Operator-UI will allow to attach
new license by clicking the Add License button
- Console backend will extract the license from the k8s secret and save
the license-key jwt in the tenant console environment variable and
redeploy
This commit is contained in:
Lenin Alevski
2021-01-12 15:55:07 -06:00
committed by GitHub
parent fd779c2ffa
commit f3bcfc327d
69 changed files with 4293 additions and 221 deletions

View File

@@ -335,7 +335,6 @@ func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInf
// 5 seconds timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
opClientClientSet, err := cluster.OperatorClient(session.STSSessionToken)
if err != nil {
return nil, prepareError(err)
@@ -351,6 +350,29 @@ func getTenantInfoResponse(session *models.Principal, params admin_api.TenantInf
}
info := getTenantInfo(minTenant)
if minTenant.Spec.Console != nil {
clientSet, err := cluster.K8sClient(session.STSSessionToken)
k8sClient := k8sClient{
client: clientSet,
}
if err != nil {
return nil, prepareError(err)
}
// obtain current subnet license for tenant (if exists)
license, _ := getSubscriptionLicense(context.Background(), &k8sClient, params.Namespace, minTenant.Spec.Console.ConsoleSecret.Name)
if license != "" {
client := &cluster.HTTPClient{
Client: GetConsoleSTSClient(),
}
licenseInfo, _, _ := subscriptionValidate(client, license, "", "")
// if licenseInfo is present attach it to the tenantInfo response
if licenseInfo != nil {
info.SubnetLicense = licenseInfo
}
}
}
return info, nil
}
@@ -511,13 +533,13 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
}
}()
var envrionmentVariables []corev1.EnvVar
var environmentVariables []corev1.EnvVar
// Check the Erasure Coding Parity for validity and pass it to Tenant
if tenantReq.ErasureCodingParity > 0 {
if tenantReq.ErasureCodingParity < 2 || tenantReq.ErasureCodingParity > 8 {
return nil, prepareError(errorInvalidErasureCodingValue)
}
envrionmentVariables = append(envrionmentVariables, corev1.EnvVar{
environmentVariables = append(environmentVariables, corev1.EnvVar{
Name: "MINIO_STORAGE_CLASS_STANDARD",
Value: fmt.Sprintf("EC:%d", tenantReq.ErasureCodingParity),
})
@@ -535,7 +557,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
CredsSecret: &corev1.LocalObjectReference{
Name: secretName,
},
Env: envrionmentVariables,
Env: environmentVariables,
},
}
idpEnabled := false
@@ -653,6 +675,19 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
consoleSecretName := fmt.Sprintf("%s-secret", consoleSelector)
consoleAccess = RandomCharString(16)
consoleSecret = RandomCharString(32)
consoleSecretData := map[string][]byte{
"CONSOLE_PBKDF_PASSPHRASE": []byte(RandomCharString(16)),
"CONSOLE_PBKDF_SALT": []byte(RandomCharString(8)),
"CONSOLE_ACCESS_KEY": []byte(consoleAccess),
"CONSOLE_SECRET_KEY": []byte(consoleSecret),
}
// If Subnet License is present in k8s secrets, copy that to the CONSOLE_SUBNET_LICENSE env variable
// of the console tenant
license, _ := getSubscriptionLicense(ctx, &k8sClient, cluster.Namespace, OperatorSubnetLicenseSecretName)
if license != "" {
consoleSecretData[ConsoleSubnetLicense] = []byte(license)
}
imm := true
instanceSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
@@ -662,10 +697,7 @@ func getTenantCreatedResponse(session *models.Principal, params admin_api.Create
},
},
Immutable: &imm,
Data: map[string][]byte{
"CONSOLE_PBKDF_PASSPHRASE": []byte(RandomCharString(16)),
"CONSOLE_PBKDF_SALT": []byte(RandomCharString(8)),
},
Data: consoleSecretData,
}
minInst.Spec.Console = &operator.ConsoleConfiguration{