Skip to content

Commit

Permalink
supermicro: support SMC BMCs that don't implement CSRF tokens
Browse files Browse the repository at this point in the history
Older X11 BMC firmwares don't include CSRF tokens in requests to the BMC API.
  • Loading branch information
joelrebel committed Nov 9, 2023
1 parent 4c4d249 commit a2f6af3
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 20 deletions.
1 change: 0 additions & 1 deletion providers/supermicro/firmware.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ var (
)

// bmc client interface implementations methods

func (c *Client) FirmwareInstallSteps(ctx context.Context, component string) ([]constants.FirmwareInstallStep, error) {
if err := c.firmwareInstallSupported(ctx); err != nil {
return nil, err
Expand Down
13 changes: 9 additions & 4 deletions providers/supermicro/floppy.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,23 @@ func (c *Client) MountFloppyImage(ctx context.Context, image io.Reader) error {

var payloadBuffer bytes.Buffer

formParts := []struct {
type form struct {
name string
data io.Reader
}{
}

formParts := []form{
{
name: "img_file",
data: image,
},
{
}

if c.csrfToken != "" {
formParts = append(formParts, form{
name: "csrf-token",
data: bytes.NewBufferString(c.csrfToken),
},
})
}

payloadWriter := multipart.NewWriter(&payloadBuffer)
Expand Down
14 changes: 7 additions & 7 deletions providers/supermicro/supermicro.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ var (
providers.FeatureFirmwareUpload,
providers.FeatureFirmwareInstallUploaded,
providers.FeatureFirmwareTaskStatus,
providers.FeatureFirmwareInstallSteps,
}
)

Expand Down Expand Up @@ -175,12 +176,11 @@ func (c *Client) Open(ctx context.Context) (err error) {
return errors.Wrap(bmclibErrs.ErrLoginFailed, strconv.Itoa(status))
}

token := parseToken(contentsTopMenu)
if token == "" {
return errors.Wrap(bmclibErrs.ErrLoginFailed, "could not parse CSRF-TOKEN from page")
}

c.csrfToken = token
// Note: older firmware version on the X11s don't use a CSRF token
// so here theres no explicit requirement for it to be found.
//
// X11DPH-T 01.71.11 10/25/2019
c.csrfToken = parseToken(contentsTopMenu)

c.model, err = c.deviceModel(ctx)
if err != nil {
Expand Down Expand Up @@ -219,7 +219,7 @@ func parseToken(body []byte) string {
return ""
}

re, err := regexp.Compile(`"CSRF_TOKEN", "(?P<token>.*)"`)
re, err := regexp.Compile(fmt.Sprintf(`"%s", "(?P<token>.*)"`, key))
if err != nil {
return ""
}
Expand Down
5 changes: 5 additions & 0 deletions providers/supermicro/supermicro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ func TestParseToken(t *testing.T) {
[]byte(`<script>SmcCsrfInsert ("CSRF_TOKEN", "RYjdEjWIhU+PCRFMBP2ZRPPePcQ4n3dM3s+rCgTnBBU");</script></body>`),
"RYjdEjWIhU+PCRFMBP2ZRPPePcQ4n3dM3s+rCgTnBBU",
},
{
"token with key type 5 found",
[]byte(`<script>SmcCsrfInsert ("CSRF-TOKEN", "RYjdEjWIhU+PCRFMBP2ZRPPePcQ4n3dM3s+rCgTnBBU");</script></body>`),
"RYjdEjWIhU+PCRFMBP2ZRPPePcQ4n3dM3s+rCgTnBBU",
},
}

for _, tc := range testcases {
Expand Down
13 changes: 9 additions & 4 deletions providers/supermicro/x11_firmware_bios.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,18 +195,23 @@ func (c *x11) uploadBIOSFirmware(ctx context.Context, fwReader io.Reader) error
var payloadBuffer bytes.Buffer
var err error

formParts := []struct {
type form struct {
name string
data io.Reader
}{
}

formParts := []form{
{
name: "bios_rom",
data: fwReader,
},
{
}

if c.csrfToken != "" {
formParts = append(formParts, form{
name: "csrf-token",
data: bytes.NewBufferString(c.csrfToken),
},
})
}

payloadWriter := multipart.NewWriter(&payloadBuffer)
Expand Down
13 changes: 9 additions & 4 deletions providers/supermicro/x11_firmware_bmc.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,23 @@ func (c *x11) uploadBMCFirmware(ctx context.Context, fwReader io.Reader) error {
var payloadBuffer bytes.Buffer
var err error

formParts := []struct {
type form struct {
name string
data io.Reader
}{
}

formParts := []form{
{
name: "fw_image",
data: fwReader,
},
{
}

if c.csrfToken != "" {
formParts = append(formParts, form{
name: "csrf-token",
data: bytes.NewBufferString(c.csrfToken),
},
})
}

payloadWriter := multipart.NewWriter(&payloadBuffer)
Expand Down

0 comments on commit a2f6af3

Please sign in to comment.