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 13, 2023
1 parent d7662f2 commit ecc1fb3
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 19 deletions.
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.serviceClient.csrfToken != "" {
formParts = append(formParts, form{
name: "csrf-token",
data: bytes.NewBufferString(c.serviceClient.csrfToken),
},
})
}

payloadWriter := multipart.NewWriter(&payloadBuffer)
Expand Down
15 changes: 8 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 @@ -168,12 +169,12 @@ 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.serviceClient.setCsrfToken(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
csrfToken := parseToken(contentsTopMenu)
c.serviceClient.setCsrfToken(csrfToken)

c.bmc, err = c.bmcQueryor(ctx)
if err != nil {
Expand Down Expand Up @@ -246,7 +247,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 ecc1fb3

Please sign in to comment.