Skip to content

Commit

Permalink
feat(backend): psk is written to temporary file for spdk
Browse files Browse the repository at this point in the history
  • Loading branch information
artek-koltun committed Jul 24, 2023
1 parent 8128c8d commit cee7041
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 2 deletions.
12 changes: 12 additions & 0 deletions pkg/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
package backend

import (
"os"

"github.com/opiproject/gospdk/spdk"
pb "github.com/opiproject/opi-api/storage/v1alpha1/gen/go"
)
Expand All @@ -31,6 +33,12 @@ type Server struct {
rpc spdk.JSONRPC
Volumes VolumeParameters
Pagination map[string]int
psk psk
}

type psk struct {
createTempFile func(dir, pattern string) (*os.File, error)
writeKey func(keyFile string, key []byte, perm os.FileMode) error
}

// NewServer creates initialized instance of BackEnd server communicating
Expand All @@ -45,5 +53,9 @@ func NewServer(jsonRPC spdk.JSONRPC) *Server {
NvmePaths: make(map[string]*pb.NvmePath),
},
Pagination: make(map[string]int),
psk: psk{
createTempFile: os.CreateTemp,
writeKey: os.WriteFile,
},
}
}
31 changes: 29 additions & 2 deletions pkg/backend/nvme_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"context"
"fmt"
"log"
"os"
"path"
"sort"
"strings"
Expand Down Expand Up @@ -74,8 +75,16 @@ func (s *Server) CreateNvmePath(_ context.Context, in *pb.CreateNvmePathRequest)
psk := ""
if len(controller.Psk) > 0 {
log.Printf("Notice, TLS is used to establish connection: to %v", in.NvmePath)
// TODO: write controller.Psk to file /tmp/opikey.txt
psk = "/tmp/opikey.txt"
keyFile, err := s.keyToTemporaryFile(controller.Psk)
if err != nil {
return nil, err
}
defer func() {
err := os.Remove(keyFile)
log.Printf("Cleanup key file %v: %v", keyFile, err)
}()

psk = keyFile
}
params := spdk.BdevNvmeAttachControllerParams{
Name: path.Base(controller.Name),
Expand Down Expand Up @@ -330,3 +339,21 @@ func (s *Server) numberOfPathsForController(controllerName string) int {
}
return numberOfPaths
}

func (s *Server) keyToTemporaryFile(pskKey []byte) (string, error) {
keyFile, err := s.psk.createTempFile("", "opikey")
if err != nil {
log.Printf("error: failed to create file for key: %v", err)
return "", status.Error(codes.Internal, "failed to handle key")
}

const keyPermissions = 0600
if err := s.psk.writeKey(keyFile.Name(), pskKey, keyPermissions); err != nil {
log.Printf("error: failed to write to key file: %v", err)
removeErr := os.Remove(keyFile.Name())
log.Printf("Delete key file after key write: %v", removeErr)
return "", status.Error(codes.Internal, "failed to handle key")
}

return keyFile.Name(), nil
}
92 changes: 92 additions & 0 deletions pkg/backend/nvme_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
package backend

import (
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"testing"

Expand Down Expand Up @@ -144,6 +147,95 @@ func TestBackEnd_CreateNvmePath(t *testing.T) {
}
})
}
pskTests := map[string]struct {
createErr error
writeErr error
spdk []string
errCode codes.Code
errMsg string
}{
"tmp key file creation failed": {
createErr: errors.New("stub error"),
writeErr: nil,
spdk: []string{},
errCode: codes.Internal,
errMsg: "failed to handle key",
},
"tmp key file write failed": {
createErr: nil,
writeErr: errors.New("stub error"),
spdk: []string{},
errCode: codes.Internal,
errMsg: "failed to handle key",
},
"tmp key file removed after successful call": {
createErr: nil,
writeErr: nil,
spdk: []string{`{"id":%d,"error":{"code":0,"message":""},"result":["mytest"]}`},
errCode: codes.OK,
errMsg: "",
},
}

for name, tt := range pskTests {
t.Run(name, func(t *testing.T) {
testEnv := createTestEnvironment(tt.spdk)
defer testEnv.Close()

const expectedKey = "NVMeTLSkey-1:01:MDAxMTIyMzM0NDU1NjY3Nzg4OTlhYWJiY2NkZGVlZmZwJEiQ:"
testEnv.opiSpdkServer.Volumes.NvmeControllers[testNvmeCtrlName] =
&pb.NvmeRemoteController{
Hdgst: false, Ddgst: false, Multipath: pb.NvmeMultipath_NVME_MULTIPATH_MULTIPATH,
Psk: []byte(expectedKey),
}

createdKeyFile := ""
origCreateTempFile := testEnv.opiSpdkServer.psk.createTempFile
testEnv.opiSpdkServer.psk.createTempFile =
func(dir, pattern string) (*os.File, error) {
if tt.createErr == nil {
keyFile, _ := origCreateTempFile(t.TempDir(), pattern)
createdKeyFile = keyFile.Name()
return keyFile, nil
}
return nil, tt.createErr
}
origWriteKey := testEnv.opiSpdkServer.psk.writeKey
testEnv.opiSpdkServer.psk.writeKey =
func(keyFile string, key []byte, perm os.FileMode) error {
if createdKeyFile != keyFile {
t.Errorf("Expected key is written to: %v, instead: %v", createdKeyFile, keyFile)
}
if _, err := os.Stat(createdKeyFile); err != nil {
t.Errorf("Expected temporary key file %v exists", createdKeyFile)
}
_ = origWriteKey(keyFile, key, perm)
written, _ := os.ReadFile(filepath.Clean(keyFile))
if string(written) != expectedKey {
t.Errorf("Expected psk key: %v is written, received: %v", expectedKey, key)
}
return tt.writeErr
}

request := &pb.CreateNvmePathRequest{NvmePath: &testNvmePath, NvmePathId: "nvmetcppath0"}
_, err := testEnv.client.CreateNvmePath(testEnv.ctx, request)

if er, ok := status.FromError(err); ok {
if er.Code() != tt.errCode {
t.Error("error code: expected", tt.errCode, "received", er.Code())
}
if er.Message() != tt.errMsg {
t.Error("error message: expected", tt.errMsg, "received", er.Message())
}
} else {
t.Error("expected grpc error status")
}

if _, err := os.Stat(createdKeyFile); err == nil {
t.Errorf("Expect temporary key file %v is removed", createdKeyFile)
}
})
}
}

func TestBackEnd_DeleteNvmePath(t *testing.T) {
Expand Down

0 comments on commit cee7041

Please sign in to comment.