in pkg/controller/association/user.go [79:170]
func reconcileEsUserSecret(
ctx context.Context,
c k8s.Client,
association commonv1.Association,
labels map[string]string,
userRoles string,
userObjectSuffix string,
es esv1.Elasticsearch,
) error {
span, ctx := apm.StartSpan(ctx, "reconcile_es_user", tracing.SpanTypeApp)
defer span.End()
// Add the Elasticsearch name, this is only intended to help the user to filter on these resources
labels[eslabel.ClusterNameLabelName] = es.Name
secKey := secretKey(association, userObjectSuffix)
usrKey := UserKey(association, es.Namespace, userObjectSuffix)
expectedSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secKey.Name,
Namespace: secKey.Namespace,
Labels: commonlabels.AddCredentialsLabel(labels),
},
Data: map[string][]byte{},
}
var password []byte
// reuse the existing password if there's one
var existingSecret corev1.Secret
err := c.Get(ctx, k8s.ExtractNamespacedName(&expectedSecret), &existingSecret)
if err != nil && !apierrors.IsNotFound(err) {
return err
}
if existingPassword, exists := existingSecret.Data[usrKey.Name]; exists {
password = existingPassword
} else {
password = common.FixedLengthRandomPasswordBytes()
}
expectedSecret.Data[usrKey.Name] = password
if _, err := reconciler.ReconcileSecret(ctx, c, expectedSecret, association.Associated()); err != nil {
return err
}
// analogous to the association secret: a user Secret goes on the Elasticsearch side of the association
// we apply the ES cluster labels ("user belongs to that ES cluster")
// and the association label ("for that association object")
// merge the association labels provided by the controller with the one needed for a user
userLabels := esuser.AssociatedUserLabels(es)
for key, value := range labels {
userLabels[key] = value
}
expectedEsUser := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: usrKey.Name,
Namespace: usrKey.Namespace,
Labels: userLabels,
},
Data: map[string][]byte{
esuser.UserNameField: []byte(usrKey.Name),
esuser.UserRolesField: []byte(userRoles),
},
}
var existingUserSecret corev1.Secret
if err := c.Get(ctx, k8s.ExtractNamespacedName(&expectedEsUser), &existingUserSecret); err != nil && !apierrors.IsNotFound(err) {
return err
}
// reuse the existing hash if valid
var bcryptHash []byte
if existingHash, exists := existingUserSecret.Data[esuser.PasswordHashField]; exists {
if bcrypt.CompareHashAndPassword(existingHash, password) == nil {
bcryptHash = existingHash
}
}
if bcryptHash == nil {
bcryptHash, err = bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
if err != nil {
return err
}
}
expectedEsUser.Data[esuser.PasswordHashField] = bcryptHash
owner := es // user is owned by the es resource in es namespace
_, err = reconciler.ReconcileSecret(ctx, c, expectedEsUser, &owner)
return err
}