-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
270 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
260 changes: 260 additions & 0 deletions
260
pkg/comp-functions/functions/vshnmariadb/user_management.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
package vshnmariadb | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" | ||
xfnproto "github.com/crossplane/function-sdk-go/proto/v1beta1" | ||
my1alpha1 "github.com/vshn/appcat/v4/apis/sql/mysql/v1alpha1" | ||
vshnv1 "github.com/vshn/appcat/v4/apis/vshn/v1" | ||
"github.com/vshn/appcat/v4/pkg/comp-functions/functions/common" | ||
"github.com/vshn/appcat/v4/pkg/comp-functions/runtime" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
func UserManagement(ctx context.Context, comp *vshnv1.VSHNMariaDB, svc *runtime.ServiceRuntime) *xfnproto.Result { | ||
|
||
// Nothing defined, let's return early | ||
if len(comp.Spec.Parameters.Service.Access) == 0 { | ||
return nil | ||
} | ||
|
||
addProviderConfig(comp, svc) | ||
|
||
for _, access := range comp.Spec.Parameters.Service.Access { | ||
|
||
userPasswordRef := addUser(comp, svc, *access.User) | ||
|
||
dbname := *access.User | ||
if access.Database != nil { | ||
dbname = *access.Database | ||
} | ||
|
||
addDatabase(comp, svc, dbname) | ||
|
||
addGrants(comp, svc, *access.User, dbname, access.Privileges) | ||
|
||
addConnectionDetail(comp, svc, userPasswordRef, *access.User, dbname, access.WriteConnectionSecretToReference) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func addUser(comp common.Composite, svc *runtime.ServiceRuntime, username string) string { | ||
secretName, err := common.AddGenericSecret(comp, svc, "userpass-"+username, []string{"userpass"}) | ||
if err != nil { | ||
svc.Log.Error(err, "cannot deploy user password secret") | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot deploy user password secret: %s", err))) | ||
} | ||
|
||
role := &my1alpha1.User{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: fmt.Sprintf("%s-%s-role", comp.GetName(), username), | ||
Annotations: map[string]string{ | ||
"crossplane.io/external-name": username, | ||
}, | ||
Labels: map[string]string{ | ||
runtime.ProviderConfigIgnoreLabel: "true", | ||
}, | ||
}, | ||
Spec: my1alpha1.UserSpec{ | ||
ForProvider: my1alpha1.UserParameters{}, | ||
ResourceSpec: xpv1.ResourceSpec{ | ||
ProviderConfigReference: &xpv1.Reference{ | ||
Name: comp.GetName(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
err = svc.SetDesiredComposedResource(role, runtime.ComposedOptionProtects(comp.GetName()+"-provider-conf-credentials"), runtime.ComposedOptionProtects(secretName)) | ||
if err != nil { | ||
svc.Log.Error(err, "cannot apply user") | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot apply user: %s", err))) | ||
} | ||
|
||
return secretName | ||
} | ||
|
||
func addConnectionDetail(comp common.Composite, svc *runtime.ServiceRuntime, secretName, username, dbname string, connectionDetailRef *xpv1.SecretReference) { | ||
userpassCD, err := svc.GetObservedComposedResourceConnectionDetails(secretName) | ||
if err != nil { | ||
svc.Log.Error(err, "cannot get userpassword from secret") | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot get userpassword from secret: %s", err))) | ||
} | ||
|
||
compositeCD := svc.GetConnectionDetails() | ||
|
||
// url := getPostgresURLCustomUser(compositeCD, string(compositeCD["MARIADB_HOST"]), username) | ||
|
||
om := metav1.ObjectMeta{ | ||
Name: comp.GetLabels()["crossplane.io/claim-name"] + "-" + username, | ||
Namespace: comp.GetClaimNamespace(), | ||
} | ||
if connectionDetailRef != nil { | ||
om.Name = connectionDetailRef.Name | ||
om.Namespace = connectionDetailRef.Namespace | ||
} | ||
|
||
userpassSecret := &corev1.Secret{ | ||
ObjectMeta: om, | ||
Type: corev1.SecretType("connection.crossplane.io/v1alpha1"), | ||
Data: map[string][]byte{ | ||
"MARIADB_USER": []byte(username), | ||
"MARIADB_PASSWORD": userpassCD["userpass"], | ||
"MARIADB_DB": []byte(dbname), | ||
"MARIADB_HOST": compositeCD["MARIADB_HOST"], | ||
"MARIADB_PORT": compositeCD["MARIADB_PORT"], | ||
// "MARIADB_URL": []byte(url), | ||
"ca.crt": compositeCD["ca.crt"], | ||
"tls.crt": compositeCD["tls.crt"], | ||
"tls.key": compositeCD["tls.key"], | ||
}, | ||
} | ||
|
||
err = svc.SetDesiredKubeObject(userpassSecret, fmt.Sprintf("%s-user-%s", comp.GetName(), username)) | ||
if err != nil { | ||
svc.Log.Error(err, "cannot get userpassword from secret") | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot get userpassword from secret: %s", err))) | ||
} | ||
} | ||
|
||
func addProviderConfig(comp *vshnv1.VSHNMariaDB, svc *runtime.ServiceRuntime) { | ||
cd := svc.GetConnectionDetails() | ||
|
||
secret := &corev1.Secret{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: "provider-conf-credentials", | ||
Namespace: comp.GetInstanceNamespace(), | ||
}, | ||
Data: map[string][]byte{ | ||
"username": cd["MARIADB_USER"], | ||
"password": cd["MARIADB_PASSWORD"], | ||
"endpoint": cd["MARIADB_HOST"], | ||
"port": cd["MARIADB_PORT"], | ||
}, | ||
} | ||
|
||
err := svc.SetDesiredKubeObject(secret, comp.GetName()+"-provider-conf-credentials", | ||
runtime.KubeOptionProtects("namespace-conditions"), | ||
runtime.KubeOptionProtects("cluster"), | ||
runtime.KubeOptionProtects(comp.GetName()+"-netpol")) | ||
if err != nil { | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot set credential secret for provider-sql: %s", err))) | ||
svc.Log.Error(err, "cannot set credential secret for provider-sql") | ||
} | ||
|
||
tls := "preferred" | ||
if comp.Spec.Parameters.TLS.TLSEnabled { | ||
tls = "skip-verify" | ||
} | ||
|
||
config := &my1alpha1.ProviderConfig{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: comp.GetName(), | ||
}, | ||
Spec: my1alpha1.ProviderConfigSpec{ | ||
TLS: &tls, | ||
Credentials: my1alpha1.ProviderCredentials{ | ||
Source: "MySQLConnectionSecret", | ||
ConnectionSecretRef: &xpv1.SecretReference{ | ||
Name: "provider-conf-credentials", | ||
Namespace: comp.GetInstanceNamespace(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
err = svc.SetDesiredKubeObject(config, comp.GetName()+"-providerconfig") | ||
if err != nil { | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot apply the provider config for provider sql: %s", err))) | ||
svc.Log.Error(err, "cannot apply the provider config for provider sql") | ||
} | ||
} | ||
|
||
// We check if the database is already specified. | ||
// If not it will be added. | ||
// This should handle cases where there are mutliple users pointing to the same | ||
// database, and one is deleted, that the database is not dropped. | ||
func addDatabase(comp common.Composite, svc *runtime.ServiceRuntime, name string) { | ||
resname := fmt.Sprintf("%s-%s-database", comp.GetName(), name) | ||
|
||
xdb := &my1alpha1.Database{} | ||
|
||
// If there's a database with the same name we will just return | ||
err := svc.GetDesiredComposedResourceByName(xdb, resname) | ||
if err == nil { | ||
return | ||
} | ||
if err != runtime.ErrNotFound { | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot check if database exists: %s", err))) | ||
svc.Log.Error(err, "cannot check if database exists") | ||
} | ||
|
||
xdb = &my1alpha1.Database{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: resname, | ||
Annotations: map[string]string{ | ||
"crossplane.io/external-name": name, | ||
}, | ||
Labels: map[string]string{ | ||
runtime.ProviderConfigIgnoreLabel: "true", | ||
}, | ||
}, | ||
Spec: my1alpha1.DatabaseSpec{ | ||
ForProvider: my1alpha1.DatabaseParameters{}, | ||
ResourceSpec: xpv1.ResourceSpec{ | ||
ProviderConfigReference: &xpv1.Reference{ | ||
Name: comp.GetName(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
err = svc.SetDesiredComposedResource(xdb, runtime.ComposedOptionProtects(comp.GetName()+"-provider-conf-credentials")) | ||
if err != nil { | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot apply database: %s", err))) | ||
svc.Log.Error(err, "cannot apply database") | ||
} | ||
} | ||
|
||
func addGrants(comp common.Composite, svc *runtime.ServiceRuntime, username, dbname string, privileges []string) { | ||
privs := []my1alpha1.GrantPrivilege{} | ||
|
||
if len(privileges) == 0 { | ||
privs = append(privs, "ALL") | ||
} | ||
|
||
for _, priv := range privileges { | ||
privs = append(privs, my1alpha1.GrantPrivilege(priv)) | ||
} | ||
|
||
grant := &my1alpha1.Grant{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: fmt.Sprintf("%s-%s-%s-grants", comp.GetName(), username, dbname), | ||
Labels: map[string]string{ | ||
runtime.ProviderConfigIgnoreLabel: "true", | ||
}, | ||
}, | ||
Spec: my1alpha1.GrantSpec{ | ||
ForProvider: my1alpha1.GrantParameters{ | ||
Privileges: privs, | ||
User: &username, | ||
Database: &dbname, | ||
}, | ||
ResourceSpec: xpv1.ResourceSpec{ | ||
ProviderConfigReference: &xpv1.Reference{ | ||
Name: comp.GetName(), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
err := svc.SetDesiredComposedResource(grant, runtime.ComposedOptionProtects(comp.GetName()+"-provider-conf-credentials")) | ||
if err != nil { | ||
svc.AddResult(runtime.NewWarningResult(fmt.Sprintf("cannot apply database: %s", err))) | ||
svc.Log.Error(err, "cannot apply database") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters