Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
292 changes: 184 additions & 108 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#See the License for the specific language governing permissions and
#limitations under the License.

ARG MOUNTPOINT_VERSION=1.18.0
ARG MOUNTPOINT_VERSION=1.22.0

# Download the mountpoint tarball and produce an installable directory
# Building on Amazon Linux 2 because it has an old libc version. libfuse from the os
Expand Down
15 changes: 15 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Release Notes

## [Unreleased]

### Breaking Changes

- **`-o` Mount Option Now Rejected**: The CSI driver now explicitly rejects volumes that specify
the `-o` (fstab-style) mount flag with an `InvalidArgument` error, rather than silently
stripping it. Pods using PVs or StorageClasses with `-o` in `mountOptions` will fail to start
after this upgrade.

**Migration**: Remove any `-o` entries from your PV or StorageClass `mountOptions`. The flag
was always silently ignored and had no effect on the mount. If you intended to pass options via
`-o option1,option2`, specify each option directly instead (e.g., use `uid=1000` and
`allow-other` as separate entries rather than `-o uid=1000,allow-other`). See
[Mount Options](docs/volume-provisioning/mount-options.md) for supported option syntax.

## [2.1.1](https://github.com/scality/mountpoint-s3-csi-driver/releases/tag/2.1.1)

March 5, 2026
Expand Down
1 change: 1 addition & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ aws s3 ls s3://your-bucket --endpoint-url https://your-s3-endpoint.com

| Error Message | Cause | Solution |
|---------------|-------|----------|
| `MountVolume.SetUp failed: running mount-s3 with mount flag -o is not supported in CSI Driver` | `-o` (fstab-style) flag present in PV or StorageClass `mountOptions` | Remove the `-o` entry from `mountOptions`. The CSI driver uses Mountpoint-style options directly — e.g., use `uid=1000` and `allow-other` as separate entries rather than `-o uid=1000,allow-other`. |
| "Transport endpoint not connected" | S3 endpoint unreachable | 1. Check network connectivity<br/>2. Check endpoint URL configuration<br/>3. Check security groups/firewall rules |
| "Failed to create mount process" | Mountpoint binary issue | 1. Check initContainer logs<br/>2. Check `/opt/mountpoint-s3-csi/bin/mount-s3` exists on node |
| "Access Denied" | Invalid S3 credentials | 1. Check secret contains `access_key_id` and `secret_access_key`<br/>2. Test credentials with AWS CLI<br/>3. Check bucket policy |
Expand Down
19 changes: 19 additions & 0 deletions docs/volume-provisioning/mount-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,25 @@ parameters:
```


## Unsupported Syntax

The CSI driver does **not** support fstab-style mount syntax using the `-o` flag.
Each option must be a separate entry in the `mountOptions` array.

!!! failure "This will fail"
```yaml
mountOptions:
- "-o uid=1000,gid=2000,allow-other" # ❌ Not supported — causes InvalidArgument error
```

!!! success "Use this instead"
```yaml
mountOptions:
- "uid=1000" # ✅ Each option as its own entry
- "gid=2000"
- "allow-other"
```

## Common Mount Options

Here's a list of commonly used Mountpoint S3 options relevant for the CSI driver:
Expand Down
4 changes: 4 additions & 0 deletions pkg/driver/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ func (ns *S3NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePubl

args := mountpoint.ParseArgs(mountpointArgs)

if args.Has(mountpoint.ArgFsTab) {
return nil, status.Error(codes.InvalidArgument, "Running mount-s3 with mount flag -o is not supported in Scality CSI Driver for S3.")
}

fsGroup := ""
if capMount := volCap.GetMount(); capMount != nil {
if volumeMountGroup := capMount.GetVolumeMountGroup(); volumeMountGroup != "" {
Expand Down
33 changes: 33 additions & 0 deletions pkg/driver/node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
csi "github.com/container-storage-interface/spec/lib/go/csi"
"github.com/golang/mock/gomock"
"github.com/scality/mountpoint-s3-csi-driver/pkg/util/testutil/assert"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/scality/mountpoint-s3-csi-driver/pkg/driver/node"
"github.com/scality/mountpoint-s3-csi-driver/pkg/driver/node/credentialprovider"
Expand Down Expand Up @@ -213,6 +215,37 @@ func TestNodePublishVolume(t *testing.T) {
nodeTestEnv.mockCtl.Finish()
},
},
{
name: "fail: fstab style option is present",
testFunc: func(t *testing.T) {
nodeTestEnv := initNodeServerTestEnv(t)
ctx := context.Background()
req := &csi.NodePublishVolumeRequest{
VolumeId: volumeId,
VolumeCapability: &csi.VolumeCapability{
AccessType: &csi.VolumeCapability_Mount{
Mount: &csi.VolumeCapability_MountVolume{
MountFlags: []string{"-o rw,nosuid,nodev,allow-other"},
},
},
AccessMode: &csi.VolumeCapability_AccessMode{
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_MULTI_WRITER,
},
},
TargetPath: targetPath,
VolumeContext: map[string]string{"bucketName": bucketName},
}

_, err := nodeTestEnv.server.NodePublishVolume(ctx, req)
if err == nil {
t.Fatal("NodePublishVolume should have failed for fstab option")
}
if got := status.Code(err); got != codes.InvalidArgument {
t.Errorf("expected gRPC code %v, got %v", codes.InvalidArgument, got)
}
nodeTestEnv.mockCtl.Finish()
},
},
}

for _, tc := range testCases {
Expand Down
28 changes: 26 additions & 2 deletions tests/e2e/customsuites/dynamic_provisioning_mount_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"os"
"time"

"github.com/onsi/ginkgo/v2"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -498,8 +499,31 @@ func (t *s3CSIDynamicProvisioningMountOptionsTestSuite) DefineTests(driver stora
testPolicyEnforcement(ctx, []string{"--storage-class=EXPRESS_ONEZONE"}, "storage-class")
})

ginkgo.It("should strip -o from mount options", func(ctx context.Context) {
testPolicyEnforcement(ctx, []string{"-o"}, "fs-tab")
ginkgo.It("should reject -o mount option with InvalidArgument error", func(ctx context.Context) {
ginkgo.By("Creating StorageClass with disallowed -o mount option")

mountOptions := []string{
fmt.Sprintf("uid=%d", DefaultNonRootUser),
fmt.Sprintf("gid=%d", DefaultNonRootGroup),
"allow-other",
"-o",
}

l.storageClass = createStorageClassWithMountOptions(ctx, mountOptions, nil, "fs-tab")

ginkgo.By("Creating PVC with the StorageClass")
pvc := createPVCWithStorageClass(ctx, l.storageClass, "fs-tab-pvc")

ginkgo.By("Creating pod that mounts the volume")
pod := MakeNonRootPodWithVolume(f.Namespace.Name, []*v1.PersistentVolumeClaim{pvc}, "")
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
defer func() {
framework.ExpectNoError(CleanupPodInErrorState(ctx, f, pod.Name))
}()

ginkgo.By("Verifying pod fails to start with CSI driver rejection message")
framework.ExpectNoError(WaitForPodError(ctx, f, pod.Name, "not supported in CSI Driver", 2*time.Minute))
})

ginkgo.It("should strip multiple disallowed mount options", func(ctx context.Context) {
Expand Down
27 changes: 25 additions & 2 deletions tests/e2e/customsuites/mountoptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/onsi/ginkgo/v2"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/kubernetes/test/e2e/framework"
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
Expand Down Expand Up @@ -250,8 +251,30 @@ func (t *s3CSIMountOptionsTestSuite) DefineTests(driver storageframework.TestDri
)
})

ginkgo.It("strips -o flag", func(ctx context.Context) {
validateStrippedOption(ctx, "-o", "fs-tab")
ginkgo.It("rejects -o flag with InvalidArgument error", func(ctx context.Context) {
ginkgo.By("PVC with disallowed flag: fs-tab")

res := BuildVolumeWithOptions(
ctx,
l.config,
pattern,
DefaultNonRootUser,
DefaultNonRootGroup,
"", // No specific file mode
"-o",
)
l.resources = append(l.resources, res)

ginkgo.By("Creating pod with a volume using -o flag")
pod := MakeNonRootPodWithVolume(f.Namespace.Name, []*v1.PersistentVolumeClaim{res.Pvc}, "")
pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, pod, metav1.CreateOptions{})
framework.ExpectNoError(err)
defer func() {
framework.ExpectNoError(CleanupPodInErrorState(ctx, f, pod.Name))
}()

ginkgo.By("Verifying pod fails to start with CSI driver rejection message")
framework.ExpectNoError(WaitForPodError(ctx, f, pod.Name, "not supported in CSI Driver", 2*time.Minute))
})

ginkgo.It("strips all unsupported volume level mount flags when they arrive together", func(ctx context.Context) {
Expand Down
Loading