From e14700d00d2b440242c8caf32710b7f3e9dceb25 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 15:23:35 -0400 Subject: [PATCH 01/15] use martinjungblut/go-cryptsetup --- go.mod | 1 + go.sum | 2 + internal/driver/luks.go | 72 ++++++++++----------------- internal/driver/nodeserver_helpers.go | 15 ++---- 4 files changed, 35 insertions(+), 55 deletions(-) diff --git a/go.mod b/go.mod index 0891795f..c19c45a6 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/ianschenck/envflag v0.0.0-20140720210342-9111d830d133 github.com/linode/go-metadata v0.2.0 github.com/linode/linodego v1.35.0 + github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6 go.uber.org/mock v0.4.0 golang.org/x/net v0.27.0 golang.org/x/sys v0.22.0 diff --git a/go.sum b/go.sum index 4f1622a7..e7b92692 100644 --- a/go.sum +++ b/go.sum @@ -72,6 +72,8 @@ github.com/linode/go-metadata v0.2.0/go.mod h1:XraDbSwms0+CtA7/Qh7agkSvGDc6H0s78 github.com/linode/linodego v1.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do= github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6 h1:YDjLk3wsL5ZLhLC4TIwIvT2NkSCAdAV6pzzZaRfj4jk= +github.com/martinjungblut/go-cryptsetup v0.0.0-20220520180014-fd0874fd07a6/go.mod h1:gZoZ0+POlM1ge/VUxWpMmZVNPzzMJ7l436CgkQ5+qzU= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/internal/driver/luks.go b/internal/driver/luks.go index a1e3dee0..f9a986d8 100644 --- a/internal/driver/luks.go +++ b/internal/driver/luks.go @@ -25,12 +25,14 @@ import ( "errors" "fmt" "os/exec" + "strconv" "strings" "k8s.io/klog/v2" utilexec "k8s.io/utils/exec" - "github.com/linode/linode-blockstorage-csi-driver/pkg/mount-manager" + mountmanager "github.com/linode/linode-blockstorage-csi-driver/pkg/mount-manager" + cryptsetup "github.com/martinjungblut/go-cryptsetup" ) type LuksContext struct { @@ -116,59 +118,39 @@ func getLuksContext(secrets map[string]string, context map[string]string, lifecy } } -func (e *Encryption) luksFormat(ctx LuksContext, source string) error { - cryptsetupCmd, err := e.getCryptsetupCmd() +func (e *Encryption) luksFormat(ctx LuksContext, source string) (string, error) { + luks2 := cryptsetup.LUKS2{SectorSize: 512} + keySize, err := strconv.Atoi(ctx.EncryptionKeySize) if err != nil { - return err + return "", err } - - // initialize the luks partition - cryptsetupArgs := []string{ - "-v", - "--batch-mode", - "--cipher", ctx.EncryptionCipher, - "--key-size", ctx.EncryptionKeySize, - "--key-file", "-", - "luksFormat", source, + genericParams := cryptsetup.GenericParams{ + Cipher: ctx.EncryptionCipher, + CipherMode: "xts-plain64", + VolumeKeySize: keySize, } - - klog.V(4).Info("executing cryptsetup luksFormat command ", cryptsetupArgs) - - cmd := e.Exec.Command(cryptsetupCmd, cryptsetupArgs...) - - // Set the encryption key as stdin - cmd.SetStdin(strings.NewReader(ctx.EncryptionKey)) - - out, err := cmd.CombinedOutput() + device, err := cryptsetup.Init(source) if err != nil { - return fmt.Errorf("cryptsetup luksFormat failed: %w cmd: '%s %s' output: %q", - err, cryptsetupCmd, strings.Join(cryptsetupArgs, " "), string(out)) + return "", err } - - // open the luks partition - klog.V(4).Info("luksOpen ", source) - err = e.luksOpen(ctx, source) + err = device.Format(luks2, genericParams) if err != nil { - return fmt.Errorf("cryptsetup luksOpen failed: %w cmd: '%s %s' output: %q", - err, cryptsetupCmd, strings.Join(cryptsetupArgs, " "), string(out)) + return "", err } - - defer func() { - if e := e.luksClose(ctx.VolumeName); e != nil { - klog.Errorf("cannot close luks device: %s", e.Error()) - } - }() - - klog.V(4).Info("The LUKS volume name is ", ctx.VolumeName) - - return nil -} - -// prepares a luks-encrypted volume for mounting and returns the path of the mapped volume -func (e *Encryption) luksPrepareMount(ctx LuksContext, source string) (string, error) { - if err := e.luksOpen(ctx, source); err != nil { + err = device.KeyslotAddByVolumeKey(0, "", "") + if err != nil { + return "", err + } + defer device.Free() + err = device.Load(nil) + if err != nil { + return "", err + } + err = device.ActivateByPassphrase(ctx.VolumeName, 0, "", 0) + if err != nil { return "", err } + klog.V(4).Info("The volume has been LUKS formatted ", ctx.VolumeName) return "/dev/mapper/" + ctx.VolumeName, nil } diff --git a/internal/driver/nodeserver_helpers.go b/internal/driver/nodeserver_helpers.go index b1058aa8..a92a1670 100644 --- a/internal/driver/nodeserver_helpers.go +++ b/internal/driver/nodeserver_helpers.go @@ -259,8 +259,8 @@ func (ns *NodeServer) mountVolume(devicePath string, req *csi.NodeStageVolumeReq // Format and mount the drive klog.V(4).Info("formatting and mounting the drive") if err := ns.mounter.FormatAndMount(fmtAndMountSource, stagingTargetPath, fsType, mountOptions); err != nil { - return errInternal("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v", - devicePath, stagingTargetPath, fsType, mountOptions, err) + return errInternal("Failed to format and mount device from (%q) to (%q) with fstype (%q) and options (%q): %v", + devicePath, stagingTargetPath, fsType, mountOptions, err) } return nil @@ -272,6 +272,7 @@ func (ns *NodeServer) mountVolume(devicePath string, req *csi.NodeStageVolumeReq // If not, it formats the device using the provided LuksContext. // Finally, it prepares the LUKS volume for mounting. func (ns *NodeServer) prepareLUKSVolume(devicePath string, luksContext LuksContext) (string, error) { + var luksSource string // LUKS encryption enabled, check if the volume needs to be formatted. klog.V(4).Info("LUKS encryption enabled") @@ -291,17 +292,11 @@ func (ns *NodeServer) prepareLUKSVolume(devicePath string, luksContext LuksConte } // Format the volume with LUKS encryption. - if err := ns.encrypt.luksFormat(luksContext, devicePath); err != nil { + if luksSource, err = ns.encrypt.luksFormat(luksContext, devicePath); err != nil { return "", errInternal("Failed to luks format (%q): %v", devicePath, err) } } - // Prepare the LUKS volume for mounting. - luksSource, err := ns.encrypt.luksPrepareMount(luksContext, devicePath) - if err != nil { - return "", errInternal("Failed to prepare luks mount (%q): %v", devicePath, err) - } - return luksSource, nil } @@ -341,7 +336,7 @@ func (ns *NodeServer) getMountSources(target string) ([]string, error) { } return nil, err } - out, err := ns.mounter.Exec.Command("sh", "-c", fmt.Sprintf("findmnt -o SOURCE -n -M %s", target)).CombinedOutput() + out, err := ns.mounter.Exec.Command("sh", "-c", fmt.Sprintf("findmnt -o SOURCE -n -M %s", target)).CombinedOutput() // https://pkg.go.dev/k8s.io/utils/mount#GetDeviceNameFromMount if err != nil { // findmnt exits with non zero exit status if it couldn't find anything if strings.TrimSpace(string(out)) == "" { From 93c5328b65f7b4f96d6f3aceb87c3a29e407fe4d Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 20:14:28 -0400 Subject: [PATCH 02/15] install cryptsetup in gha --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d162e3be..9bf92997 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,6 +45,10 @@ jobs: LINODE_MACHINE_TYPE: g6-standard-2 WORKER_NODES: ${{ github.ref == 'refs/heads/main' && '3' || '0' }} steps: + - name: Install cryptsetup + run: | + apt install libcryptsetup12 libcryptset-dev + - uses: actions/checkout@v4 with: fetch-depth: 0 From d131112d62bab26082378b1baaa0d539cb8d671c Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 20:15:46 -0400 Subject: [PATCH 03/15] install cryptsetup in gha --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bf92997..fbbc1ed9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,10 @@ jobs: ci: runs-on: ubuntu-latest steps: + - name: Install cryptsetup + run: | + apt install libcryptsetup12 libcryptset-dev + - uses: actions/checkout@v4 with: fetch-depth: 0 From fb228033a0fe3dcb0c74e7ff152afb9c3912c1bf Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 20:20:15 -0400 Subject: [PATCH 04/15] elevated gha permissions --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbbc1ed9..b78559c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Install cryptsetup run: | - apt install libcryptsetup12 libcryptset-dev + sudo apt install libcryptsetup12 libcryptset-dev - uses: actions/checkout@v4 with: @@ -51,7 +51,7 @@ jobs: steps: - name: Install cryptsetup run: | - apt install libcryptsetup12 libcryptset-dev + sudo apt install libcryptsetup12 libcryptset-dev - uses: actions/checkout@v4 with: From 713375259a369fa63880c4e73f00c8b3402f565b Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 20:25:57 -0400 Subject: [PATCH 05/15] update package name --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b78559c6..102055b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: steps: - name: Install cryptsetup run: | - sudo apt install libcryptsetup12 libcryptset-dev + sudo apt install libcryptsetup12 libcryptsetup-dev - uses: actions/checkout@v4 with: @@ -51,7 +51,7 @@ jobs: steps: - name: Install cryptsetup run: | - sudo apt install libcryptsetup12 libcryptset-dev + sudo apt install libcryptsetup12 libcryptsetup-dev - uses: actions/checkout@v4 with: From 27a607ba07cb62d1257f8a218bf42519ffc9035a Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Wed, 4 Sep 2024 20:28:00 -0400 Subject: [PATCH 06/15] remove luksOpen function --- internal/driver/luks.go | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/internal/driver/luks.go b/internal/driver/luks.go index f9a986d8..5171003d 100644 --- a/internal/driver/luks.go +++ b/internal/driver/luks.go @@ -171,38 +171,6 @@ func (e *Encryption) luksClose(volume string) error { return nil } -func (e *Encryption) luksOpen(ctx LuksContext, volume string) error { - // check if the luks volume is already open - if _, err := e.FileSystem.Stat("/dev/mapper/" + ctx.VolumeName); !e.FileSystem.IsNotExist(err) { - klog.V(4).Infof("luks volume is already open %s", volume) - return nil - } - - cryptsetupCmd, err := e.getCryptsetupCmd() - if err != nil { - return err - } - cryptsetupArgs := []string{ - "--batch-mode", - "luksOpen", - "--key-file", "-", - volume, ctx.VolumeName, - } - klog.V(4).Info("executing cryptsetup luksOpen command") - - cmd := e.Exec.Command(cryptsetupCmd, cryptsetupArgs...) - - // Set the encryption key as stdin - cmd.SetStdin(strings.NewReader(ctx.EncryptionKey)) - - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("cryptsetup luksOpen failed: %w cmd: '%s %s' output: %q", - err, cryptsetupCmd, strings.Join(cryptsetupArgs, " "), string(out)) - } - return nil -} - // check is a given mapping under /dev/mapper is a luks volume func (e *Encryption) isLuksMapping(volume string) (bool, string, error) { if strings.HasPrefix(volume, "/dev/mapper/") { From e65d9151b479dbd9d3f00cd2c1b08e568a6aad39 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Thu, 5 Sep 2024 13:52:44 -0400 Subject: [PATCH 07/15] add cryptsetup-dev to dockerfile --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f17f5ead..fc9ccf27 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,6 +10,7 @@ COPY go.sum . COPY main.go . COPY pkg ./pkg COPY internal ./internal +RUN apk add --no-cache e2fsprogs findmnt blkid cryptsetup xfsprogs cryptsetup-dev RUN go mod download @@ -21,6 +22,4 @@ LABEL description="Linode CSI Driver" COPY --from=builder /bin/linode-blockstorage-csi-driver /linode -RUN apk add --no-cache e2fsprogs findmnt blkid cryptsetup xfsprogs - ENTRYPOINT ["/linode"] From 2f8e2997209de8da7d97e1623c96d4288a19f5ee Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Thu, 5 Sep 2024 16:13:54 -0400 Subject: [PATCH 08/15] update dockerfile to update packages and go buold flags --- Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index fc9ccf27..f90d4ebd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22.5-alpine as builder +FROM golang:1.22.5-alpine AS builder # from makefile ARG REV @@ -10,16 +10,18 @@ COPY go.sum . COPY main.go . COPY pkg ./pkg COPY internal ./internal -RUN apk add --no-cache e2fsprogs findmnt blkid cryptsetup xfsprogs cryptsetup-dev +RUN apk add cryptsetup cryptsetup-libs cryptsetup-dev gcc musl-dev pkgconfig RUN go mod download -RUN go build -a -ldflags '-X main.vendorVersion='${REV}' -extldflags "-static"' -o /bin/linode-blockstorage-csi-driver /linode +RUN CGO_ENABLED=1 go build -a -ldflags '-X main.vendorVersion='${REV}'' -o /bin/linode-blockstorage-csi-driver /linode FROM alpine:3.18.4 LABEL maintainers="Linode" LABEL description="Linode CSI Driver" +RUN apk add --no-cache e2fsprogs findmnt blkid cryptsetup xfsprogs + COPY --from=builder /bin/linode-blockstorage-csi-driver /linode ENTRYPOINT ["/linode"] From 9f563d9a74f29668ab5c576bb823431aa7a17a5d Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Thu, 5 Sep 2024 16:48:09 -0400 Subject: [PATCH 09/15] update go build make target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ca9f6294..f37261ef 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ WORKER_NODES ?= 0 .PHONY: build build: - go build -o linode-blockstorage-csi-driver -a -ldflags '-X main.vendorVersion='${IMAGE_VERSION}' -extldflags "-static"' ./main.go + CGO_ENABLED=1 go build -o linode-blockstorage-csi-driver -a -ldflags '-X main.vendorVersion='${IMAGE_VERSION}'' ./main.go .PHONY: docker-build docker-build: From 21bd6d1a089be7e9c1ca0b12c153b0cd561c1d07 Mon Sep 17 00:00:00 2001 From: amold1 Date: Fri, 6 Sep 2024 12:13:17 -0400 Subject: [PATCH 10/15] Update nodeserver_helpers.go --- internal/driver/nodeserver_helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/driver/nodeserver_helpers.go b/internal/driver/nodeserver_helpers.go index f613ed40..c078d229 100644 --- a/internal/driver/nodeserver_helpers.go +++ b/internal/driver/nodeserver_helpers.go @@ -345,7 +345,7 @@ func (ns *NodeServer) prepareLUKSVolume(ctx context.Context, devicePath string, } // Format the volume with LUKS encryption. - if luksSource, err = ns.encrypt.luksFormat(luksContext, devicePath); err != nil { + if err := ns.encrypt.luksFormat(luksContext, devicePath); err != nil { return "", errInternal("Failed to luks format (%q): %v", devicePath, err) } } From d1b1ab72365026a8593c08f13abd9e75a4731210 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Fri, 6 Sep 2024 12:18:31 -0400 Subject: [PATCH 11/15] fix --- internal/driver/nodeserver_helpers.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/internal/driver/nodeserver_helpers.go b/internal/driver/nodeserver_helpers.go index c078d229..edcf10eb 100644 --- a/internal/driver/nodeserver_helpers.go +++ b/internal/driver/nodeserver_helpers.go @@ -323,6 +323,7 @@ func (ns *NodeServer) mountVolume(ctx context.Context, devicePath string, req *c // If not, it formats the device using the provided LuksContext. // Finally, it prepares the LUKS volume for mounting. func (ns *NodeServer) prepareLUKSVolume(ctx context.Context, devicePath string, luksContext LuksContext) (string, error) { + var luksSource string log := logger.GetLogger(ctx) log.V(4).Info("Entering prepareLUKSVolume", "devicePath", devicePath, "luksContext", luksContext) @@ -345,18 +346,11 @@ func (ns *NodeServer) prepareLUKSVolume(ctx context.Context, devicePath string, } // Format the volume with LUKS encryption. - if err := ns.encrypt.luksFormat(luksContext, devicePath); err != nil { + if luksSource, err = ns.encrypt.luksFormat(luksContext, devicePath); err != nil { return "", errInternal("Failed to luks format (%q): %v", devicePath, err) } } - // Prepare the LUKS volume for mounting. - log.V(4).Info("preparing luks volume for mounting", "devicePath", devicePath) - luksSource, err := ns.encrypt.luksPrepareMount(luksContext, devicePath) - if err != nil { - return "", errInternal("Failed to prepare luks mount (%q): %v", devicePath, err) - } - log.V(4).Info("Exiting prepareLUKSVolume", "luksSource", luksSource) return luksSource, nil } From 7481068f477c64e7370e20b68d7ea7f219fbc011 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Fri, 6 Sep 2024 21:39:03 -0400 Subject: [PATCH 12/15] set the cipher and mode; add luks example --- .../examples/kubernetes/luks-enabled-vol.yaml | 58 +++++++++++++++++++ internal/driver/luks.go | 7 ++- 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 internal/driver/examples/kubernetes/luks-enabled-vol.yaml diff --git a/internal/driver/examples/kubernetes/luks-enabled-vol.yaml b/internal/driver/examples/kubernetes/luks-enabled-vol.yaml new file mode 100644 index 00000000..12651ef3 --- /dev/null +++ b/internal/driver/examples/kubernetes/luks-enabled-vol.yaml @@ -0,0 +1,58 @@ +--- +kind: Pod +apiVersion: v1 +metadata: + name: csi-example-pod-luks +spec: + containers: + - name: csi-example-container + image: busybox + volumeMounts: + - mountPath: "/data" + name: csi-example-volume-luks + command: ["sleep", "1000000"] + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + volumes: + - name: csi-example-volume-luks + persistentVolumeClaim: + claimName: csi-example-pvc-luks +--- +allowVolumeExpansion: true +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + annotations: + storageclass.kubernetes.io/is-default-class: "true" + name: linode-block-storage-luks-luks + namespace: kube-system +provisioner: linodebs.csi.linode.com +reclaimPolicy: Delete +parameters: + linodebs.csi.linode.com/luks-encrypted: "true" + linodebs.csi.linode.com/luks-cipher: "aes-xts-plain64" + linodebs.csi.linode.com/luks-key-size: "512" + csi.storage.k8s.io/node-stage-secret-namespace: default + csi.storage.k8s.io/node-stage-secret-name: csi-encrypt-example-luks-key + linodebs.csi.linode.com/volumeTags: default +--- +apiVersion: v1 +kind: Secret +metadata: + name: csi-encrypt-example-luks-key +stringData: + luksKey: klOMgxvP7v2lJ1LXjQQ4oMQ0n/axuGAjT311C6qbJO/Z7D6dIYYlz/qFn7+AF0oZm5Y2qJos+R/kZaEk/MA9vw== +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: csi-example-pvc-luks +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: linode-block-storage-luks-luks diff --git a/internal/driver/luks.go b/internal/driver/luks.go index 5171003d..66c9a8ca 100644 --- a/internal/driver/luks.go +++ b/internal/driver/luks.go @@ -124,10 +124,11 @@ func (e *Encryption) luksFormat(ctx LuksContext, source string) (string, error) if err != nil { return "", err } + cipherString := strings.SplitN(ctx.EncryptionCipher, "-", 2) genericParams := cryptsetup.GenericParams{ - Cipher: ctx.EncryptionCipher, - CipherMode: "xts-plain64", - VolumeKeySize: keySize, + Cipher: cipherString[0], + CipherMode: cipherString[1], + VolumeKeySize: keySize / 8, } device, err := cryptsetup.Init(source) if err != nil { From 97b828914d06fda2c759cf5b0badd26094852ebf Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Mon, 9 Sep 2024 22:54:08 -0400 Subject: [PATCH 13/15] dockerize make targets --- Dockerfile.dev | 26 ++++++++++++++++++++++++++ Makefile | 24 ++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 Dockerfile.dev diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..e9e3ffd9 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,26 @@ +FROM golang:1.22.5-alpine AS builder +# from makefile +ARG REV + +RUN mkdir -p /linode +WORKDIR /linode + +COPY . . +RUN apk add \ + blkid \ + cryptsetup \ + cryptsetup-libs \ + cryptsetup-dev \ + e2fsprogs \ + findmnt \ + gcc \ + pkgconfig \ + make \ + musl-dev \ + xfsprogs + +RUN go mod tidy + +RUN CGO_ENABLED=1 go build -a -ldflags '-X main.vendorVersion='${REV}'' -o /bin/linode-blockstorage-csi-driver /linode +RUN CGO_ENABLED=1 go install go.uber.org/mock/mockgen@latest +CMD ["sh"] diff --git a/Makefile b/Makefile index f37261ef..e2842fb5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,11 @@ PLATFORM ?= linux/amd64 REGISTRY_NAME ?= index.docker.io IMAGE_NAME ?= linode/linode-blockstorage-csi-driver REV := $(shell git describe --long --tags --dirty 2> /dev/null || echo "dev") +ifdef DEV_TAG_EXTENSION +IMAGE_VERSION ?= $(REV)-$(DEV_TAG_EXTENSION) +else IMAGE_VERSION ?= $(REV) +endif IMAGE_TAG ?= $(REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_VERSION) GOLANGCI_LINT_IMG := golangci/golangci-lint:v1.59-alpine RELEASE_DIR ?= release @@ -24,19 +28,19 @@ endif ##################################################################### .PHONY: fmt fmt: - go fmt ./... + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) go fmt ./... .PHONY: vet vet: fmt - go vet ./... + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) go vet ./... .PHONY: lint lint: vet - docker run --rm -v $(PWD):/app -w /app ${GOLANGCI_LINT_IMG} golangci-lint run -v + docker run --platform=$(PLATFORM) --rm -v $(PWD):/app -w /app ${GOLANGCI_LINT_IMG} golangci-lint run -v .PHONY: verify verify: - go mod verify + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) go mod verify .PHONY: clean clean: @@ -118,13 +122,17 @@ cleanup-cluster: .PHONY: generate-mock generate-mock: - mockgen -source=internal/driver/nodeserver_helpers.go -destination=mocks/mock_nodeserver.go -package=mocks - mockgen -source=pkg/mount-manager/device-utils.go -destination=mocks/mock_deviceutils.go -package=mocks - mockgen -source=pkg/mount-manager/fs-utils.go -destination=mocks/mock_fsutils.go -package=mocks + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) mockgen -source=internal/driver/nodeserver_helpers.go -destination=mocks/mock_nodeserver.go -package=mocks + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) mockgen -source=pkg/mount-manager/device-utils.go -destination=mocks/mock_deviceutils.go -package=mocks + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) mockgen -source=pkg/mount-manager/fs-utils.go -destination=mocks/mock_fsutils.go -package=mocks + +.PHONY: docker-dev-build +docker-dev-build: + DOCKER_BUILDKIT=1 docker build --platform=$(PLATFORM) --progress=plain -t $(IMAGE_TAG) --build-arg REV=$(IMAGE_VERSION) -f ./Dockerfile.dev . .PHONY: test test: vet verify generate-mock - go test `go list ./... | grep -v ./mocks$$` -cover $(TEST_ARGS) + docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) go test `go list ./... | grep -v ./mocks$$` -cover $(TEST_ARGS) .PHONY: elevated-test elevated-test: From 4a8da83ccb70a4d4ef1715683651ff9a0eac0486 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Mon, 9 Sep 2024 23:12:34 -0400 Subject: [PATCH 14/15] reuse docker-build target with dockerfile var --- Makefile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index e2842fb5..f947d977 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ endif IMAGE_TAG ?= $(REGISTRY_NAME)/$(IMAGE_NAME):$(IMAGE_VERSION) GOLANGCI_LINT_IMG := golangci/golangci-lint:v1.59-alpine RELEASE_DIR ?= release +DOCKERFILE ?= Dockerfile ##################################################################### # OS / ARCH @@ -67,7 +68,7 @@ build: .PHONY: docker-build docker-build: - DOCKER_BUILDKIT=1 docker build --platform=$(PLATFORM) --progress=plain -t $(IMAGE_TAG) --build-arg REV=$(IMAGE_VERSION) -f ./Dockerfile . + DOCKER_BUILDKIT=1 docker build --platform=$(PLATFORM) --progress=plain -t $(IMAGE_TAG) --build-arg REV=$(IMAGE_VERSION) -f ./$(DOCKERFILE) . .PHONY: docker-push docker-push: @@ -126,10 +127,6 @@ generate-mock: docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) mockgen -source=pkg/mount-manager/device-utils.go -destination=mocks/mock_deviceutils.go -package=mocks docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) mockgen -source=pkg/mount-manager/fs-utils.go -destination=mocks/mock_fsutils.go -package=mocks -.PHONY: docker-dev-build -docker-dev-build: - DOCKER_BUILDKIT=1 docker build --platform=$(PLATFORM) --progress=plain -t $(IMAGE_TAG) --build-arg REV=$(IMAGE_VERSION) -f ./Dockerfile.dev . - .PHONY: test test: vet verify generate-mock docker run --platform=$(PLATFORM) -it $(IMAGE_TAG) go test `go list ./... | grep -v ./mocks$$` -cover $(TEST_ARGS) From c6f8078350aed3663f75f6b958a47cddb3b373e5 Mon Sep 17 00:00:00 2001 From: Amol Deodhar Date: Tue, 10 Sep 2024 11:13:34 -0400 Subject: [PATCH 15/15] tests updates --- internal/driver/luks.go | 42 ++++--------------- internal/driver/nodeserver_helpers.go | 26 ++++-------- .../driver/nodeserver_helpers_linux_test.go | 38 ++--------------- 3 files changed, 20 insertions(+), 86 deletions(-) diff --git a/internal/driver/luks.go b/internal/driver/luks.go index 66c9a8ca..e205edef 100644 --- a/internal/driver/luks.go +++ b/internal/driver/luks.go @@ -119,6 +119,9 @@ func getLuksContext(secrets map[string]string, context map[string]string, lifecy } func (e *Encryption) luksFormat(ctx LuksContext, source string) (string, error) { + args := []string{""} + s, err := e.Exec.Command("lsblk", args...).CombinedOutput() + klog.V(2).Info("Command output ", s) luks2 := cryptsetup.LUKS2{SectorSize: 512} keySize, err := strconv.Atoi(ctx.EncryptionKeySize) if err != nil { @@ -138,6 +141,10 @@ func (e *Encryption) luksFormat(ctx LuksContext, source string) (string, error) if err != nil { return "", err } + if device.Dump() == 0 { + klog.V(4).Info("The volume is already LUKS formatted ", ctx.VolumeName) + return "/dev/mapper/" + ctx.VolumeName, nil + } err = device.KeyslotAddByVolumeKey(0, "", "") if err != nil { return "", err @@ -210,38 +217,3 @@ func (e *Encryption) getCryptsetupCmd() (string, error) { } return cryptsetupCmd, nil } - -func (e *Encryption) blkidValid(source string) (bool, error) { - if source == "" { - return false, errors.New("invalid source") - } - - blkidCmd := "blkid" - _, err := e.Exec.LookPath(blkidCmd) - if err != nil { - if err == exec.ErrNotFound { - return false, fmt.Errorf("%q executable invalid", blkidCmd) - } - return false, err - } - - blkidArgs := []string{source} - - exitCode := 0 - cmd := e.Exec.Command(blkidCmd, blkidArgs...) - err = cmd.Run() - if err != nil { - exitError, ok := err.(utilexec.ExitError) - if !ok { - return false, fmt.Errorf("checking blkdid failed: %w cmd: %q, args: %q", err, blkidCmd, blkidArgs) - } - // ws := exitError.Sys().(syscall.WaitStatus) - exitCode = exitError.ExitStatus() - if exitCode == 2 { - return false, nil - } - return false, errors.New("checking blkdid failed") - } - - return true, nil -} diff --git a/internal/driver/nodeserver_helpers.go b/internal/driver/nodeserver_helpers.go index edcf10eb..bc3b1895 100644 --- a/internal/driver/nodeserver_helpers.go +++ b/internal/driver/nodeserver_helpers.go @@ -324,31 +324,23 @@ func (ns *NodeServer) mountVolume(ctx context.Context, devicePath string, req *c // Finally, it prepares the LUKS volume for mounting. func (ns *NodeServer) prepareLUKSVolume(ctx context.Context, devicePath string, luksContext LuksContext) (string, error) { var luksSource string + var err error log := logger.GetLogger(ctx) log.V(4).Info("Entering prepareLUKSVolume", "devicePath", devicePath, "luksContext", luksContext) // LUKS encryption enabled, check if the volume needs to be formatted. log.V(4).Info("LUKS encryption enabled") - // Validate if the device is formatted with LUKS encryption or if it needs formatting. - formatted, err := ns.encrypt.blkidValid(devicePath) - if err != nil { - return "", errInternal("Failed to validate blkid (%q): %v", devicePath, err) - } - - // If the device is not, format it. - if !formatted { - log.V(4).Info("luks volume now formatting: ", devicePath) + log.V(4).Info("luks volume now formatting: ", devicePath) - // Validate the LUKS context. - if err := luksContext.validate(); err != nil { - return "", errInternal("Failed to luks format validation (%q): %v", devicePath, err) - } + // Validate the LUKS context. + if err = luksContext.validate(); err != nil { + return "", errInternal("Failed to luks format validation (%q): %v", devicePath, err) + } - // Format the volume with LUKS encryption. - if luksSource, err = ns.encrypt.luksFormat(luksContext, devicePath); err != nil { - return "", errInternal("Failed to luks format (%q): %v", devicePath, err) - } + // Format the volume with LUKS encryption. + if luksSource, err = ns.encrypt.luksFormat(luksContext, devicePath); err != nil { + return "", errInternal("Failed to luks format (%q): %v", devicePath, err) } log.V(4).Info("Exiting prepareLUKSVolume", "luksSource", luksSource) diff --git a/internal/driver/nodeserver_helpers_linux_test.go b/internal/driver/nodeserver_helpers_linux_test.go index a4915b3a..b95373cb 100644 --- a/internal/driver/nodeserver_helpers_linux_test.go +++ b/internal/driver/nodeserver_helpers_linux_test.go @@ -74,8 +74,8 @@ func TestNodeServer_mountVolume_linux(t *testing.T) { VolumeId: "test", VolumeContext: map[string]string{ LuksEncryptedAttribute: "true", - LuksCipherAttribute: "test", - LuksKeySizeAttribute: "test", + LuksCipherAttribute: "aes-xts-plain64", + LuksKeySizeAttribute: "512", PublishInfoVolumeName: "test", }, Secrets: map[string]string{LuksKeyAttribute: "test"}, @@ -83,25 +83,6 @@ func TestNodeServer_mountVolume_linux(t *testing.T) { expectMounterCalls: func(m *mocks.MockMounter) { m.EXPECT().MountSensitive("/dev/mapper/test", "", "ext4", []string{"defaults"}, emptyStringArray).Return(nil) }, - expectExecCalls: func(m *mocks.MockExecutor, c *mocks.MockCommand) { - m.EXPECT().LookPath("blkid").Return("/bin/blkid", nil) - m.EXPECT().Command("blkid", "/dev/test").Return(c) - c.EXPECT().Run().Return(nil) - - // LuksOpen - m.EXPECT().LookPath("cryptsetup").Return("/bin/cryptsetup", nil) - m.EXPECT().Command("cryptsetup", "--batch-mode", "luksOpen", "--key-file", "-", "/dev/test", "test").Return(c) - c.EXPECT().SetStdin(gomock.Any()) - c.EXPECT().CombinedOutput().Return([]byte("Command Successful"), nil) - - // Mount_linux: Check disk format. Disk is not formatted. - m.EXPECT().Command("blkid", "-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/mapper/test").Return(c) - c.EXPECT().CombinedOutput().Return([]byte(""), exec.CodeExitError{Code: 2, Err: fmt.Errorf("not formatted")}) - - // Mount_linux: Format disk - m.EXPECT().Command("mkfs.ext4", "-F", "-m0", "/dev/mapper/test").Return(c) - c.EXPECT().CombinedOutput().Return([]byte("Formatted successfully"), nil) - }, expectFsCalls: func(m *mocks.MockFileSystem) { m.EXPECT().IsNotExist(gomock.Any()).Return(true) m.EXPECT().Stat(gomock.Any()).Return(nil, nil) @@ -115,23 +96,12 @@ func TestNodeServer_mountVolume_linux(t *testing.T) { VolumeId: "test", VolumeContext: map[string]string{ LuksEncryptedAttribute: "true", - LuksCipherAttribute: "test", - LuksKeySizeAttribute: "test", + LuksCipherAttribute: "aes-xts-plain64", + LuksKeySizeAttribute: "512", PublishInfoVolumeName: "test", }, Secrets: map[string]string{LuksKeyAttribute: "test"}, }, - expectExecCalls: func(m *mocks.MockExecutor, c *mocks.MockCommand) { - m.EXPECT().LookPath("blkid").Return("/bin/blkid", nil) - m.EXPECT().Command("blkid", "/dev/test").Return(c) - c.EXPECT().Run().Return(nil) - - // LuksOpen - m.EXPECT().LookPath("cryptsetup").Return("/bin/cryptsetup", nil) - m.EXPECT().Command("cryptsetup", "--batch-mode", "luksOpen", "--key-file", "-", "/dev/test", "test").Return(c) - c.EXPECT().SetStdin(gomock.Any()) - c.EXPECT().CombinedOutput().Return(nil, fmt.Errorf("Unable to LuksOpen")) - }, expectFsCalls: func(m *mocks.MockFileSystem) { m.EXPECT().IsNotExist(gomock.Any()).Return(true) m.EXPECT().Stat(gomock.Any()).Return(nil, nil)