Skip to content

Conversation

@stefanhipfel
Copy link
Contributor

Proposed Changes

Implement User controller which handles the creation of user accounts in a bmc

@afritzler afritzler added this to the v0.1 milestone Jun 25, 2025
@stefanhipfel stefanhipfel marked this pull request as ready for review July 9, 2025 08:55
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jul 10, 2025
@afritzler afritzler removed this from the v0.1.0 milestone Jul 22, 2025
Comment on lines 75 to 79
// Add this check once we use the user CRD also for BMC admin users
/*if bmcObj.Spec.AdminUserRef == nil {
return ctrl.Result{}, fmt.Errorf("BMC %s does not have an admin user reference set", bmcObj.Name)
}
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be removed?

}, nil
}
log.Info("Rotating BMC user password", "User", user.Name)
newPassword, err := GenerateRandomPassword(16)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vendors have very complicated requirement for the password generation, ideally we would like to expose it as a spec....
length, special char, and numbers etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a vendor specific password generation


invalidCredentials, err := r.bmcConnectionTest(secret, bmcObj)
if err != nil {
return fmt.Errorf("failed to test BMC connection with BMCSecret %s: %w", secret.Name, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should enter a failed state at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not have this state yet defined for the User CRD in our architecture.
Maybe we should think about adding an error state

log.V(1).Info("Deleting User", "User", user.Name)
if user.Status.EffectiveBMCSecretRef != nil {
log.V(1).Info("Removing effective BMCSecret reference from User", "User", user.Name)
if err := r.removeEffectiveSecret(ctx, log, user); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this necessary? wont it get deleted as the resource creating it is anyway deleted?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we want to delete it, we should delete the BMC Secret ref from Spec which we created, along with the Ref in status

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to comment out the delete function call, since we did not decide if the controller should also remove users on CRD deletion.
It kind of makes sense to do it, but what if that user was the metal-operators admin user?! maybe an immutable flag is needed for those kind of users

return nil
}

func (r *UserReconciler) handleRotatingPassword(ctx context.Context, log logr.Logger, user *metalv1alpha1.User, bmcClient bmc.BMC) (ctrl.Result, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a proposal
Why dont we off load the password rotation to the bmcSecret?
something in line of:
if bmcSecretRef is provided in Spec. password rotation is enabled.
EffectiveBMCSecretRef is a seperate BMCSecretRef object ( so we will have two secret) (we copy the content when we call updateEffectiveSecret, instead patching with of local obj ref)
if someone patches bmcSecretRef with new password....
we check if password is changed....
it has not changed if status effectiveBMCSecretRef password matches with BMCSpecRef and the name of both the secret are same.

if spec bmcSecretRef password is changed, we issue a update of password to BMC and then sync the status and spec..
that way user resource does not have to worry about the password rotation directly... someone else will patch the BMCSecret Ref with new password ( in our case, we will sync with vault)...and password will be rotated automatically..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm the rotation can also be triggered by the BMC password policy or an annotation via User CRD.

Currently someone else just sets a new bmcSecretRef on the user and password will be rotated. Only if the rotation on BMC was successful the EffectiveSecretRef will be updated. I think that should stay with the user CRD.

…ccounts

- Implemented GetAccountService method in the BMC interface.
- Updated user controller to utilize the new GetAccountService method for password generation.
- Added secure password generation logic with vendor-specific constraints.
- Updated tests to verify password length against the maximum allowed length.
Copy link
Contributor

@Nuckal777 Nuckal777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, PR still needs some cleanup though.

bmc/redfish.go Outdated
for _, a := range accounts {
// make sure we delete the correct account
if a.UserName == userName && a.ID == id {
service.PostWithResponse(a.ODataID, nil) // nolint: errcheck
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we ignore the return values? Besides the err being silently dropped, the docs of the PostWithResponse function suggest that the response body needs to be closed by us.

@@ -0,0 +1,130 @@
{{- if .Values.crd.enable }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file a leftover?

…ated references; remove unused RBAC roles and sample configurations
@stefanhipfel stefanhipfel requested a review from a team as a code owner December 19, 2025 13:46
}

// Vendor-specific constraints map.
var manufacturerPasswordConfigs = map[Manufacturer]ManufacturerPasswordConfig{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for future improvement. this needs to be changeable (in config map, or a user input spec) as this changes based on some settings and preference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

improvement for next PR: we need to move these to our mock server setup.

RotationPeriod *metav1.Duration `json:"rotationPeriod,omitempty"`
// if not set, the operator will generate a secure password based on BMC manufacturer requirements.
BMCSecretRef *v1.LocalObjectReference `json:"bmcSecretRef,omitempty"`
BMCRef *v1.LocalObjectReference `json:"bmcRef,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can add kubebuilder validation to be not nil?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-change area/metal-automation documentation Improvements or additions to documentation size/XXL

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

6 participants