/
user.go
179 lines (152 loc) · 5.42 KB
/
user.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package asrockrack
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
bmclibErrs "github.com/bmc-toolbox/bmclib/errors"
"github.com/bmc-toolbox/bmclib/internal"
)
var (
// TODO: standardize these across Redfish, IPMI, Vendor GUI
validRoles = []string{"Administrator", "Operator", "User"}
)
// UserAccount is a ASRR BMC user account struct
type UserAccount struct {
ID int `json:"id"`
Name string `json:"name"`
Access int `json:"access"`
Kvm int `json:"kvm"`
Vmedia int `json:"vmedia"`
NetworkPrivilege string `json:"network_privilege"`
FixedUserCount int `json:"fixed_user_count"`
OEMProprietaryLevelPrivilege int `json:"OEMProprietary_level_Privilege"`
PrivilegeLimitSerial string `json:"privilege_limit_serial"`
SSHKey string `json:"ssh_key"`
CreationTime int `json:"creation_time"`
Changepassword int `json:"changepassword"`
UserOperation int `json:"UserOperation"`
Password string `json:"password"`
ConfirmPassword string `json:"confirm_password"`
PasswordSize string `json:"password_size"`
PrevSNMP int `json:"prev_snmp"`
SNMP int `json:"snmp"`
SNMPAccess string `json:"snmp_access"`
SNMPAuthenticationProtocol string `json:"snmp_authentication_protocol"`
EmailFormat string `json:"email_format"`
EmailID string `json:"email_id"`
}
// UserRead returns a list of enabled user accounts
func (a *ASRockRack) UserRead(ctx context.Context) (users []map[string]string, err error) {
err = a.Open(ctx)
if err != nil {
return nil, err
}
accounts, err := a.listUsers(ctx)
if err != nil {
return nil, errors.Wrap(bmclibErrs.ErrRetrievingUserAccounts, err.Error())
}
users = make([]map[string]string, 0)
for _, account := range accounts {
if account.Access == 1 {
user := map[string]string{
"ID": fmt.Sprintf("%d", account.ID),
"Name": account.Name,
"RoleID": account.NetworkPrivilege,
}
users = append(users, user)
}
}
return users, nil
}
// UserCreate adds a new user account
func (a *ASRockRack) UserCreate(ctx context.Context, user, pass, role string) (ok bool, err error) {
if !internal.StringInSlice(role, validRoles) {
return false, bmclibErrs.ErrInvalidUserRole
}
if user == "" || pass == "" || role == "" {
return false, bmclibErrs.ErrUserParamsRequired
}
// fetch current list of accounts
accounts, err := a.listUsers(ctx)
if err != nil {
return false, errors.Wrap(bmclibErrs.ErrRetrievingUserAccounts, err.Error())
}
// identify account slot not in use
for _, account := range accounts {
// ASRR BMCs have a reserved slot 1 for a disabled Anonymous, no idea why.
if account.ID == 1 {
continue
}
account := account
if account.Name == user {
return false, errors.Wrap(bmclibErrs.ErrUserAccountExists, user)
}
if account.Access == 0 && account.Name == "" {
newAccount := newUserAccount(account.ID, user, pass, strings.ToLower(role))
err := a.createUpdateUser(ctx, newAccount)
if err != nil {
return false, err
}
return true, nil
}
}
return false, bmclibErrs.ErrNoUserSlotsAvailable
}
//
// UserUpdate updates a user password and role
func (a *ASRockRack) UserUpdate(ctx context.Context, user, pass, role string) (ok bool, err error) {
if !internal.StringInSlice(role, validRoles) {
return false, bmclibErrs.ErrInvalidUserRole
}
if user == "" || pass == "" || role == "" {
return false, bmclibErrs.ErrUserParamsRequired
}
accounts, err := a.listUsers(ctx)
if err != nil {
return false, errors.Wrap(bmclibErrs.ErrRetrievingUserAccounts, err.Error())
}
role = strings.ToLower(role)
// identify account slot not in use
for _, account := range accounts {
account := account
if account.Name == user {
user := newUserAccount(account.ID, user, pass, role)
if role == "administrator" {
user.PrivilegeLimitSerial = "none"
user.UserOperation = 1
user.CreationTime = 6000 // doesn't mean anything.
}
err := a.createUpdateUser(ctx, user)
if err != nil {
return false, errors.Wrap(bmclibErrs.ErrUserAccountUpdate, err.Error())
}
return true, nil
}
}
return ok, errors.Wrap(bmclibErrs.ErrUserAccountNotFound, user)
}
// newUserAccount returns a user account object populated with the given attributes and certain defaults
//
// note: the role parameter must be validated before being passed to this constructor
func newUserAccount(id int, user, pass, role string) *UserAccount {
return &UserAccount{
ID: id,
Name: user,
Access: 1, // Access enabled
Kvm: 1,
Vmedia: 1,
NetworkPrivilege: role,
FixedUserCount: 2, // No idea what this is about
OEMProprietaryLevelPrivilege: 1,
PrivilegeLimitSerial: role,
SSHKey: "Not Available",
CreationTime: 0,
Changepassword: 1,
UserOperation: 0,
Password: pass,
ConfirmPassword: pass,
PasswordSize: "bytes_16", // bytes_20 for larger passwords
EmailFormat: "AMI-Format",
}
}