Skip to content

Commit

Permalink
Merge pull request #120 from joelrebel/redfish-useraccounts
Browse files Browse the repository at this point in the history
oob/bmc: redfish user account management
jacobweinstock authored Mar 7, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 9a09ef8 + c5e858b commit 276cf3e
Showing 4 changed files with 133 additions and 11 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ module github.com/tinkerbell/pbnj
go 1.16

require (
github.com/bmc-toolbox/bmclib v0.4.16-0.20220202200536-079d247f718c
github.com/bmc-toolbox/bmclib v0.4.16-0.20220224155224-80ddde802be7
github.com/cristalhq/jwt/v3 v3.1.0
github.com/equinix-labs/otel-init-go v0.0.5
github.com/fatih/color v1.13.0
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -70,8 +70,10 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220202200536-079d247f718c h1:ZmX1a+jRaOch/drczXW76JxH1e7QNv5sLVVLfcamsWM=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220202200536-079d247f718c/go.mod h1:eYUZRvpVK2o9CtZ6ER608BRCgf/w/wt6rvjqBvNSeOM=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220222141527-4a6f31e75616 h1:3awZHamUUM61M+KCTsyAoWKUZZ3ao7G7OfnZ5FYwbj0=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220222141527-4a6f31e75616/go.mod h1:eYUZRvpVK2o9CtZ6ER608BRCgf/w/wt6rvjqBvNSeOM=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220224155224-80ddde802be7 h1:Ns/rK1cb6WN7GcnEo0rB9fcpMbjxeLWiYJmUxwdFaoQ=
github.com/bmc-toolbox/bmclib v0.4.16-0.20220224155224-80ddde802be7/go.mod h1:eYUZRvpVK2o9CtZ6ER608BRCgf/w/wt6rvjqBvNSeOM=
github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM=
github.com/bombsimon/logrusr/v2 v2.0.1/go.mod h1:ByVAX+vHdLGAfdroiMg6q0zgq2FODY2lc5YJvzmOJio=
github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo=
30 changes: 22 additions & 8 deletions grpc/oob/bmc/bmc.go
Original file line number Diff line number Diff line change
@@ -102,8 +102,23 @@ func NewBMCResetter(opts ...Option) (*Action, error) {
}

// setupConnection connects to the BMC, returning BMC management methods.
func (m Action) setupConnection(ctx context.Context, u *bmclibUserManagement) ([]oob.BMC, error) {
connections := map[string]interface{}{"bmclib": u}
func (m Action) setupConnection(ctx context.Context, user, password, host string, creds *v1.UserCreds) ([]oob.BMC, error) {
connections := map[string]interface{}{
"bmclib": &bmclibUserManagement{
user: user,
password: password,
host: host,
log: m.Log,
creds: creds,
},
"bmclibNext": &bmclibNextUserManagement{
user: user,
password: password,
host: host,
log: m.Log,
creds: creds,
},
}

m.SendStatusMessage("connecting to BMC")
successfulConnections, err := common.EstablishConnections(ctx, connections)
@@ -117,8 +132,7 @@ func (m Action) setupConnection(ctx context.Context, u *bmclibUserManagement) ([
var actions []oob.BMC
for _, elem := range successfulConnections {
conn := connections[elem]

if r, ok := conn.(common.Connection); ok {
if r, ok := conn.(common.Connection); ok && elem == "bmclib" {
defer r.Close(ctx) // nolint:revive // defer in a loop is OK here, as loop length is limited
}

@@ -141,10 +155,10 @@ func (m Action) CreateUser(ctx context.Context) error {
}

creds := m.CreateUserRequest.GetUserCreds()
status := fmt.Sprintf("updating user %q", creds.GetUsername())
status := fmt.Sprintf("creating user %q", creds.GetUsername())
m.SendStatusMessage(status)

actions, err := m.setupConnection(ctx, &bmclibUserManagement{user: user, password: password, host: host, log: m.Log, creds: creds})
actions, err := m.setupConnection(ctx, user, password, host, creds)
if err != nil {
m.SendStatusMessage("connection setup failed")
return err
@@ -175,7 +189,7 @@ func (m Action) UpdateUser(ctx context.Context) error {
status := fmt.Sprintf("updating user %q", creds.GetUsername())
m.SendStatusMessage(status)

actions, err := m.setupConnection(ctx, &bmclibUserManagement{user: user, password: password, host: host, log: m.Log, creds: creds})
actions, err := m.setupConnection(ctx, user, password, host, creds)
if err != nil {
m.SendStatusMessage("connection setup failed")
return err
@@ -205,7 +219,7 @@ func (m Action) DeleteUser(ctx context.Context) error {
status := fmt.Sprintf("deleting user %q", creds.GetUsername())
m.SendStatusMessage(status)

actions, err := m.setupConnection(ctx, &bmclibUserManagement{user: user, password: password, host: host, log: m.Log, creds: creds})
actions, err := m.setupConnection(ctx, user, password, host, creds)
if err != nil {
m.SendStatusMessage("connectiion setup failed")
return err
106 changes: 106 additions & 0 deletions grpc/oob/bmc/users_bmclibnext.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package bmc

import (
"context"
"fmt"

"github.com/bmc-toolbox/bmclib"
"github.com/go-logr/logr"
v1 "github.com/tinkerbell/pbnj/api/v1"
"github.com/tinkerbell/pbnj/pkg/repository"
)

// bmclibNextUserManagement wraps attributes to manage user accounts.
type bmclibNextUserManagement struct {
conn *bmclib.Client
host string
log logr.Logger
password string
user string
creds *v1.UserCreds
}

// Connect sets up the BMC client connection.
func (b *bmclibNextUserManagement) Connect(ctx context.Context) error {
var errMsg repository.Error

client := bmclib.NewClient(b.host, "", b.user, b.password, bmclib.WithLogger(b.log))
client.Registry.Drivers = client.Registry.Using("redfish")

if err := client.Open(ctx); err != nil {
errMsg.Code = v1.Code_value["UNKNOWN"]
errMsg.Message = err.Error()
return &errMsg
}

b.conn = client

return nil
}

// Close closes the BMC client connection.
func (b *bmclibNextUserManagement) Close(ctx context.Context) {
b.conn.Close(ctx)
}

// CreateUser creates a user account.
func (b *bmclibNextUserManagement) CreateUser(ctx context.Context) error {
ok, err := b.conn.CreateUser(ctx, b.creds.Username, b.creds.Password, userRole(b.creds.UserRole))
if !ok && err == nil {
err = fmt.Errorf("error creating user")
}

if err != nil {
return &repository.Error{
Code: v1.Code_value["UNKNOWN"],
Message: err.Error(),
}
}

return nil
}

// UpdateUser updates a user account.
func (b *bmclibNextUserManagement) UpdateUser(ctx context.Context) error {
ok, err := b.conn.UpdateUser(ctx, b.creds.Username, b.creds.Password, userRole(b.creds.UserRole))
if !ok && err == nil {
err = fmt.Errorf("error updating user")
}

if err != nil {
return &repository.Error{
Code: v1.Code_value["UNKNOWN"],
Message: err.Error(),
}
}
return nil
}

// DeleteUser deletes a user account.
func (b *bmclibNextUserManagement) DeleteUser(ctx context.Context) error {
ok, err := b.conn.DeleteUser(ctx, b.creds.Username)
if !ok && err == nil {
err = fmt.Errorf("error deleting user")
}

if err != nil {
return &repository.Error{
Code: v1.Code_value["UNKNOWN"],
Message: err.Error(),
}
}

return nil
}

// userRole returns the Redfish equivalent role for a v1.UserRole string.
func userRole(role v1.UserRole) string {
var r string
switch role.String() {
case "USER_ROLE_USER":
r = "Operator"
default:
r = "Administrator"
}
return r
}

0 comments on commit 276cf3e

Please sign in to comment.