From e705173d6d285680d7c08dc54d3d097182823ac0 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 7 Apr 2025 17:38:16 +0530 Subject: [PATCH 01/39] update gomod Signed-off-by: Ashima-Ashima1 --- .travis.yml | 2 +- Dockerfile | 2 +- Dockerfile.builder | 2 +- cos-csi-mounter/go.mod | 2 +- go.mod | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 43b4efc2..c300f30d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ dist: bionic language: go go: - - 1.24.1 + - 1.24.2 group: bluezone diff --git a/Dockerfile b/Dockerfile index 5e02dda8..fdf383a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ FROM registry.access.redhat.com/ubi8/ubi as rclone-builder RUN yum install wget git gcc -y ENV ARCH=amd64 -ENV GO_VERSION=1.24.1 +ENV GO_VERSION=1.24.2 RUN echo $ARCH $GO_VERSION diff --git a/Dockerfile.builder b/Dockerfile.builder index 352d74e6..7f30c5c8 100644 --- a/Dockerfile.builder +++ b/Dockerfile.builder @@ -1,4 +1,4 @@ -FROM golang:1.24.1 +FROM golang:1.24.2 WORKDIR /go/src/github.com/IBM/ibm-object-csi-driver ADD . /go/src/github.com/IBM/ibm-object-csi-driver diff --git a/cos-csi-mounter/go.mod b/cos-csi-mounter/go.mod index d6198819..f4455c4b 100644 --- a/cos-csi-mounter/go.mod +++ b/cos-csi-mounter/go.mod @@ -1,3 +1,3 @@ module cos-csi-mounter -go 1.24.1 +go 1.24.2 diff --git a/go.mod b/go.mod index 560edd60..dcf3cbdc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/IBM/ibm-object-csi-driver -go 1.24.1 +go 1.24.2 require ( github.com/IBM/go-sdk-core/v5 v5.19.0 From 028fbc0129a6bb3249c31278a09680096e6739f7 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 7 Apr 2025 18:04:35 +0530 Subject: [PATCH 02/39] add server.go Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/server/server.go | 147 ++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 38dd16da..09b43814 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -1,3 +1,148 @@ package main -func main() {} +import ( + "flag" + "net" + "net/http" + "os" + "os/signal" + "syscall" + + mounterUtils "github.com/IBM/ibm-object-csi-driver/pkg/mounter/utils" + "github.com/gin-gonic/gin" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +var ( + logger *zap.Logger + socketPath = "/var/lib/coscsi.sock" + + s3fs = "s3fs" + rclone = "rclone" +) + +func init() { + _ = flag.Set("logtostderr", "true") // #nosec G104: Attempt to set flags for logging to stderr only on best-effort basis.Error cannot be usefully handled. + logger = setUpLogger() + defer logger.Sync() +} + +func setUpLogger() *zap.Logger { + // Prepare a new logger + atom := zap.NewAtomicLevel() + encoderCfg := zap.NewProductionEncoderConfig() + encoderCfg.TimeKey = "timestamp" + encoderCfg.EncodeTime = zapcore.ISO8601TimeEncoder + + logger := zap.New(zapcore.NewCore( + zapcore.NewJSONEncoder(encoderCfg), + zapcore.Lock(os.Stdout), + atom, + ), zap.AddCaller()).With(zap.String("ServiceName", "cos-csi-mounter-service")) + atom.SetLevel(zap.InfoLevel) + return logger +} + +func main() { + // Always create fresh socket file + os.Remove(socketPath) + + // Create a listener + logger.Info("Creating unix socket listener...") + listener, err := net.Listen("unix", socketPath) + if err != nil { + logger.Fatal("Failed to create unix socket listener:", zap.Error(err)) + } + // Close the listener at the end + defer listener.Close() + + // Handle SIGINT and SIGTERM signals to gracefully shut down the server + signals := make(chan os.Signal, 1) + signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) + go func() { + <-signals + os.Remove(socketPath) + os.Exit(0) + }() + + logger.Info("Starting cos-csi-mounter service...") + + // Create gin router + router := gin.Default() + + router.POST("/api/cos/mount", handleCosMount()) + router.POST("/api/cos/unmount", handleCosUnmount()) + + // Serve HTTP requests over Unix socket + err = http.Serve(listener, router) + if err != nil { + logger.Fatal("Error while serving HTTP requests:", zap.Error(err)) + } +} + +func handleCosMount() gin.HandlerFunc { + return func(c *gin.Context) { + var request struct { + Path string `json:"path"` + Mounter string `json:"mounter"` + Args []string `json:"args"` + } + + logger.Info("New mount request with values: ", zap.Any("Request:", request)) + + if err := c.BindJSON(&request); err != nil { + logger.Error("Invalid request: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + logger.Info("New mount request with values: ", zap.String("Path:", request.Path), zap.String("Mounter:", request.Mounter), zap.Any("Args:", request.Args)) + + if request.Mounter != s3fs && request.Mounter != rclone { + logger.Error("Invalid Request!!!!") + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + utils := mounterUtils.MounterOptsUtils{} + err := utils.FuseMount(request.Path, request.Mounter, request.Args) + if err != nil { + logger.Error("Mount Failed: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "Mount Failed"}) + return + } + + logger.Info("New COS Mount is Successfull") + c.JSON(http.StatusOK, "Success!!") + } +} + +func handleCosUnmount() gin.HandlerFunc { + return func(c *gin.Context) { + var request struct { + Path string `json:"path"` + } + + logger.Info("New unmount request with values: ", zap.Any("Request:", request)) + + if err := c.BindJSON(&request); err != nil { + logger.Error("Invalid request: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + logger.Info("New unmount request with values: ", zap.String("Path:", request.Path)) + + utils := mounterUtils.MounterOptsUtils{} + err := utils.FuseUnmount(request.Path) + if err != nil { + logger.Error("UnMount Failed: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "Mount Failed"}) + return + } + + logger.Info("COS UnMount is Successfull") + c.JSON(http.StatusOK, "Success!!") + } +} From 2d5c377627da2224cca63f6aff6ee9c0069c6d95 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 7 Apr 2025 18:04:56 +0530 Subject: [PATCH 03/39] add go.mod Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/go.mod | 39 ++++++++++++++++ cos-csi-mounter/go.sum | 104 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 cos-csi-mounter/go.sum diff --git a/cos-csi-mounter/go.mod b/cos-csi-mounter/go.mod index f4455c4b..da5622fa 100644 --- a/cos-csi-mounter/go.mod +++ b/cos-csi-mounter/go.mod @@ -1,3 +1,42 @@ module cos-csi-mounter go 1.24.2 + +require ( + github.com/IBM/ibm-object-csi-driver v0.1.0 + github.com/gin-gonic/gin v1.10.0 + go.uber.org/zap v1.27.0 +) + +require ( + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.8 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.24.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mitchellh/go-ps v1.0.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.36.0 // indirect + golang.org/x/net v0.37.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + google.golang.org/protobuf v1.36.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.130.1 // indirect +) diff --git a/cos-csi-mounter/go.sum b/cos-csi-mounter/go.sum new file mode 100644 index 00000000..477c92fd --- /dev/null +++ b/cos-csi-mounter/go.sum @@ -0,0 +1,104 @@ +github.com/IBM/ibm-object-csi-driver v0.1.0 h1:2b95Eh98JK1eewLCFDHZW0pJiD+xhRXcWx2DlAUXPnc= +github.com/IBM/ibm-object-csi-driver v0.1.0/go.mod h1:RLNxw4esPAlYYKHVAnlmi5TExNpuDl/6Luf+t0Du4Ik= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= +github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg= +github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From 5d0acece76ee05f0a95f21d4c8ea6f39686fdfdb Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 7 Apr 2025 18:28:36 +0530 Subject: [PATCH 04/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .github/workflows/release.yml | 6 +++--- .secrets.baseline | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 753617d4..0d87a646 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release on: push: branches: - - main + - ashima-server jobs: release: @@ -54,8 +54,8 @@ jobs: files: | /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz.sha256 - tag_name: v0.1.0 - name: v0.1.0 + tag_name: v0.1.0-dev + name: v0.1.0-dev body: CSR generated with SHA1 is not supported to get certs using Metadata. - name: Perform CodeQL Analysis diff --git a/.secrets.baseline b/.secrets.baseline index 26ee1693..1b58ad96 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-07T07:17:35Z", + "generated_at": "2025-04-07T12:56:25Z", "plugins_used": [ { "name": "AWSKeyDetector" From 8a528ea1594009cfc021f8bc3d4529399ad11d93 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 9 Apr 2025 19:58:05 +0530 Subject: [PATCH 05/39] comment unmount call Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- cos-csi-mounter/server/server.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 1b58ad96..28219fbe 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-07T12:56:25Z", + "generated_at": "2025-04-09T14:27:39Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 09b43814..aa960118 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -72,7 +72,7 @@ func main() { router := gin.Default() router.POST("/api/cos/mount", handleCosMount()) - router.POST("/api/cos/unmount", handleCosUnmount()) + // router.POST("/api/cos/unmount", handleCosUnmount()) // Serve HTTP requests over Unix socket err = http.Serve(listener, router) @@ -118,6 +118,9 @@ func handleCosMount() gin.HandlerFunc { } } +// Currently by calling FuseUnmount method from NodeServer is able to unmount the volume +// If required to have specific unmount methods based on mounters then following call can be modified and used +/* func handleCosUnmount() gin.HandlerFunc { return func(c *gin.Context) { var request struct { @@ -146,3 +149,4 @@ func handleCosUnmount() gin.HandlerFunc { c.JSON(http.StatusOK, "Success!!") } } +*/ From b7e59949b0d450cc424dcf317916402dca622067 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 9 Apr 2025 19:59:36 +0530 Subject: [PATCH 06/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d87a646..f89f308c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,8 +54,8 @@ jobs: files: | /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz.sha256 - tag_name: v0.1.0-dev - name: v0.1.0-dev + tag_name: v0.1.0-dev01 + name: v0.1.0-dev01 body: CSR generated with SHA1 is not supported to get certs using Metadata. - name: Perform CodeQL Analysis From 5c15592c37de2fe920483dd915233940630b033f Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 9 Apr 2025 21:12:31 +0530 Subject: [PATCH 07/39] cos apis Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/server/server.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index aa960118..11eedca7 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -72,7 +72,7 @@ func main() { router := gin.Default() router.POST("/api/cos/mount", handleCosMount()) - // router.POST("/api/cos/unmount", handleCosUnmount()) + router.POST("/api/cos/unmount", handleCosUnmount()) // Serve HTTP requests over Unix socket err = http.Serve(listener, router) @@ -120,7 +120,7 @@ func handleCosMount() gin.HandlerFunc { // Currently by calling FuseUnmount method from NodeServer is able to unmount the volume // If required to have specific unmount methods based on mounters then following call can be modified and used -/* + func handleCosUnmount() gin.HandlerFunc { return func(c *gin.Context) { var request struct { @@ -149,4 +149,3 @@ func handleCosUnmount() gin.HandlerFunc { c.JSON(http.StatusOK, "Success!!") } } -*/ From a84c660da86c1054d273128f1dbcc1da0c52cd85 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 14 Apr 2025 15:04:26 +0530 Subject: [PATCH 08/39] unmount grpc call Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- cos-csi-mounter/server/server.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 28219fbe..ebb2ef4a 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-09T14:27:39Z", + "generated_at": "2025-04-14T09:34:13Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 11eedca7..09b43814 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -118,9 +118,6 @@ func handleCosMount() gin.HandlerFunc { } } -// Currently by calling FuseUnmount method from NodeServer is able to unmount the volume -// If required to have specific unmount methods based on mounters then following call can be modified and used - func handleCosUnmount() gin.HandlerFunc { return func(c *gin.Context) { var request struct { From ca6e8f1f443963a444dfbb34bbaf140524060f07 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Tue, 15 Apr 2025 12:46:31 +0530 Subject: [PATCH 09/39] new tag Signed-off-by: Ashima-Ashima1 --- .github/workflows/release.yml | 4 ++-- .secrets.baseline | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f89f308c..9ce9d2d9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,8 +54,8 @@ jobs: files: | /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz.sha256 - tag_name: v0.1.0-dev01 - name: v0.1.0-dev01 + tag_name: v0.1.0-dev02 + name: v0.1.0-dev02 body: CSR generated with SHA1 is not supported to get certs using Metadata. - name: Perform CodeQL Analysis diff --git a/.secrets.baseline b/.secrets.baseline index ebb2ef4a..3d4fd564 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-14T09:34:13Z", + "generated_at": "2025-04-15T07:15:56Z", "plugins_used": [ { "name": "AWSKeyDetector" From 7fc63392381b082adb77ac997c244e6fdde7a6cc Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Tue, 15 Apr 2025 13:40:48 +0530 Subject: [PATCH 10/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index 3d4fd564..c20c5207 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-15T07:15:56Z", + "generated_at": "2025-04-15T08:10:43Z", "plugins_used": [ { "name": "AWSKeyDetector" From deef960724cd5b726142b4135bfd83ad618182c8 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Tue, 15 Apr 2025 14:12:34 +0530 Subject: [PATCH 11/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/server/server.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 09b43814..f836c1e7 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -7,6 +7,7 @@ import ( "os" "os/signal" "syscall" + "time" mounterUtils "github.com/IBM/ibm-object-csi-driver/pkg/mounter/utils" "github.com/gin-gonic/gin" @@ -46,7 +47,11 @@ func setUpLogger() *zap.Logger { func main() { // Always create fresh socket file - os.Remove(socketPath) + err := os.Remove(socketPath) + if err != nil { + // Handle it properly: log it, retry, return, etc. + logger.Warn("Failed to remove Socket File") + } // Create a listener logger.Info("Creating unix socket listener...") @@ -62,7 +67,11 @@ func main() { signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM) go func() { <-signals - os.Remove(socketPath) + err := os.Remove(socketPath) + if err != nil { + // Handle it properly: log it, retry, return, etc. + logger.Warn("Failed to remove Socket File") + } os.Exit(0) }() @@ -75,7 +84,12 @@ func main() { router.POST("/api/cos/unmount", handleCosUnmount()) // Serve HTTP requests over Unix socket - err = http.Serve(listener, router) + // err = http.Serve(listener, router) + server := &http.Server{ + Handler: router, + ReadHeaderTimeout: 3 * time.Second, + } + err = server.Serve(listener) if err != nil { logger.Fatal("Error while serving HTTP requests:", zap.Error(err)) } From 766ec6f9bc917d661bdca3d87e94b31eae633758 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Tue, 15 Apr 2025 14:45:49 +0530 Subject: [PATCH 12/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/go.mod | 4 ++-- cos-csi-mounter/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cos-csi-mounter/go.mod b/cos-csi-mounter/go.mod index da5622fa..da06db75 100644 --- a/cos-csi-mounter/go.mod +++ b/cos-csi-mounter/go.mod @@ -3,7 +3,7 @@ module cos-csi-mounter go 1.24.2 require ( - github.com/IBM/ibm-object-csi-driver v0.1.0 + github.com/IBM/ibm-object-csi-driver v0.1.0-dev02 github.com/gin-gonic/gin v1.10.0 go.uber.org/zap v1.27.0 ) @@ -33,7 +33,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.37.0 // indirect + golang.org/x/net v0.38.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.36.1 // indirect diff --git a/cos-csi-mounter/go.sum b/cos-csi-mounter/go.sum index 477c92fd..1a2b234e 100644 --- a/cos-csi-mounter/go.sum +++ b/cos-csi-mounter/go.sum @@ -1,5 +1,5 @@ -github.com/IBM/ibm-object-csi-driver v0.1.0 h1:2b95Eh98JK1eewLCFDHZW0pJiD+xhRXcWx2DlAUXPnc= -github.com/IBM/ibm-object-csi-driver v0.1.0/go.mod h1:RLNxw4esPAlYYKHVAnlmi5TExNpuDl/6Luf+t0Du4Ik= +github.com/IBM/ibm-object-csi-driver v0.1.0-dev02 h1:3i4YBSptX8XYliOGwnDsyRg2OS2iIdjU1c/hLrGPG3I= +github.com/IBM/ibm-object-csi-driver v0.1.0-dev02/go.mod h1:N9haoRDlC36GDFfxw5dCFTghjjsCOxWrBaetkrGS9ss= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= @@ -83,8 +83,8 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= From 39bbd65b1e32c795d8bd1fcadda04b4369496bec Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 16 Apr 2025 13:16:33 +0530 Subject: [PATCH 13/39] fix travis Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/go.mod | 6 +++--- cos-csi-mounter/go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cos-csi-mounter/go.mod b/cos-csi-mounter/go.mod index da06db75..e56749b3 100644 --- a/cos-csi-mounter/go.mod +++ b/cos-csi-mounter/go.mod @@ -1,9 +1,9 @@ -module cos-csi-mounter +module github.com/IBM/ibm-object-csi-driver/cos-csi-mounter go 1.24.2 require ( - github.com/IBM/ibm-object-csi-driver v0.1.0-dev02 + github.com/IBM/ibm-object-csi-driver v0.1.0 github.com/gin-gonic/gin v1.10.0 go.uber.org/zap v1.27.0 ) @@ -33,7 +33,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.36.0 // indirect - golang.org/x/net v0.38.0 // indirect + golang.org/x/net v0.37.0 // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/text v0.23.0 // indirect google.golang.org/protobuf v1.36.1 // indirect diff --git a/cos-csi-mounter/go.sum b/cos-csi-mounter/go.sum index 1a2b234e..477c92fd 100644 --- a/cos-csi-mounter/go.sum +++ b/cos-csi-mounter/go.sum @@ -1,5 +1,5 @@ -github.com/IBM/ibm-object-csi-driver v0.1.0-dev02 h1:3i4YBSptX8XYliOGwnDsyRg2OS2iIdjU1c/hLrGPG3I= -github.com/IBM/ibm-object-csi-driver v0.1.0-dev02/go.mod h1:N9haoRDlC36GDFfxw5dCFTghjjsCOxWrBaetkrGS9ss= +github.com/IBM/ibm-object-csi-driver v0.1.0 h1:2b95Eh98JK1eewLCFDHZW0pJiD+xhRXcWx2DlAUXPnc= +github.com/IBM/ibm-object-csi-driver v0.1.0/go.mod h1:RLNxw4esPAlYYKHVAnlmi5TExNpuDl/6Luf+t0Du4Ik= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= @@ -83,8 +83,8 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= -golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= -golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= From 9b53ee46e608acca35e5e634ced785984fd2167a Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 16 Apr 2025 15:25:07 +0530 Subject: [PATCH 14/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .github/workflows/release.yml | 2 +- .secrets.baseline | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ce9d2d9..6e530f3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ on: jobs: release: permissions: write-all - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: matrix: diff --git a/.secrets.baseline b/.secrets.baseline index c20c5207..6c4bca3f 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-15T08:10:43Z", + "generated_at": "2025-04-16T09:55:03Z", "plugins_used": [ { "name": "AWSKeyDetector" From cb4fd839b7d6990e45078b54fe53eb0a39a1e3aa Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Tue, 22 Apr 2025 15:07:24 +0530 Subject: [PATCH 15/39] mounter args validator implementation --- cos-csi-mounter/server/server.go | 17 ++--- cos-csi-mounter/server/utils.go | 105 +++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 cos-csi-mounter/server/utils.go diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index f836c1e7..c3e385c1 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -97,12 +97,7 @@ func main() { func handleCosMount() gin.HandlerFunc { return func(c *gin.Context) { - var request struct { - Path string `json:"path"` - Mounter string `json:"mounter"` - Args []string `json:"args"` - } - + var request MountRequest logger.Info("New mount request with values: ", zap.Any("Request:", request)) if err := c.BindJSON(&request); err != nil { @@ -119,8 +114,16 @@ func handleCosMount() gin.HandlerFunc { return } + // validate mounter args + args, err := request.ParseMounterArgs() + if err != nil { + logger.Error("Invalid args", zap.Any("mounter", request.Mounter), zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid args for mounter"}) + return + } + utils := mounterUtils.MounterOptsUtils{} - err := utils.FuseMount(request.Path, request.Mounter, request.Args) + err = utils.FuseMount(request.Path, request.Mounter, args) if err != nil { logger.Error("Mount Failed: ", zap.Error(err)) c.JSON(http.StatusBadRequest, gin.H{"error": "Mount Failed"}) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go new file mode 100644 index 00000000..3461dfb2 --- /dev/null +++ b/cos-csi-mounter/server/utils.go @@ -0,0 +1,105 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" +) + +// MountRequest ... +type MountRequest struct { + Path string `json:"path"` + Bucket string `json:"bucket"` + Mounter string `json:"mounter"` + Args json.RawMessage `json:"args"` +} + +// MounterArgs ... +type MounterArgs interface { + PopulateArgsSlice(string, string) ([]string, error) +} +type S3FSArgs struct { + URL string `json:"url,omitempty"` + PasswdFilePath string `json:"passwd_file,omitempty"` + UsePathRequestStyle string `json:"use_path_request_style,omitempty"` +} + +func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { + // Marshal to JSON + raw, err := json.Marshal(args) + if err != nil { + return nil, err + } + + // Unmarshal into map[string]interface{} + var m map[string]interface{} + if err := json.Unmarshal(raw, &m); err != nil { + return nil, err + } + + // Convert to key=value slice + result := []string{bucket, targetPath} + for k, v := range m { + result = append(result, "-o") + result = append(result, fmt.Sprintf("%s=%v", k, v)) // -o, key=value + } + + return result, nil // [bucket, path, -o, key1=value1, -o, key2=value2] +} + +type RCloneArgs struct { + BackupDir string `json:"backup-dir,omitempty"` + Bind string `json:"bind,omitempty"` + BWLimit string `json:"bwlimit,omitempty"` +} + +func (args RCloneArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { + // Marshal to JSON + raw, err := json.Marshal(args) + if err != nil { + return nil, err + } + + // Unmarshal into map[string]interface{} + var m map[string]interface{} + if err := json.Unmarshal(raw, &m); err != nil { + return nil, err + } + + // Convert to key=value slice + result := []string{"mount", bucket, targetPath} + for k, v := range m { + result = append(result, fmt.Sprintf("--%s=%v", k, v)) // --key=value + } + + return result, nil // [mount, bucket, path, --key1=value1, --key2=value2] +} + +func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { + dec := json.NewDecoder(bytes.NewReader(data)) + dec.DisallowUnknownFields() + return dec.Decode(v) +} + +// --- Parser for Mounter Arguments --- + +func (req *MountRequest) ParseMounterArgs() ([]string, error) { + switch req.Mounter { + case s3fs: + var args S3FSArgs + if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { + return nil, fmt.Errorf("invalid s3fs args decode error: %w", err) + } + return args.PopulateArgsSlice(req.Bucket, req.Path) + + case rclone: + var args RCloneArgs + if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { + return nil, fmt.Errorf("invalid rclone args decode error: %w", err) + } + return args.PopulateArgsSlice(req.Bucket, req.Path) + + default: + return nil, fmt.Errorf("unknown mounter: %s", req.Mounter) + } +} From 12979cc8187d50df92727e9ccb97d30600b7acbd Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 23 Apr 2025 08:18:41 +0530 Subject: [PATCH 16/39] Add endpoint and target path validator --- cos-csi-mounter/server/utils.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index 3461dfb2..201ffead 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "strings" ) // MountRequest ... @@ -48,6 +49,7 @@ func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, err } type RCloneArgs struct { + Endpoint string `json:"endpoint,omitempty"` BackupDir string `json:"backup-dir,omitempty"` Bind string `json:"bind,omitempty"` BWLimit string `json:"bwlimit,omitempty"` @@ -81,6 +83,17 @@ func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { return dec.Decode(v) } +func argsValidator(endpoint, targetPath string) error { + if !(strings.HasPrefix(endpoint, "https://") || strings.HasPrefix(endpoint, "http://")) { + return fmt.Errorf("Bad value for COS endpoint \"%v\": scheme is missing. "+ + "Must be of the form http:// or https://", endpoint) + } + if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { + return fmt.Errorf("Bad value for target path \"%v\"", targetPath) + } + return nil +} + // --- Parser for Mounter Arguments --- func (req *MountRequest) ParseMounterArgs() ([]string, error) { @@ -90,6 +103,9 @@ func (req *MountRequest) ParseMounterArgs() ([]string, error) { if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { return nil, fmt.Errorf("invalid s3fs args decode error: %w", err) } + if err := argsValidator(args.URL, req.Path); err != nil { + return nil, fmt.Errorf("s3fs endpoint or target path validation failed: %w", err) + } return args.PopulateArgsSlice(req.Bucket, req.Path) case rclone: @@ -97,6 +113,9 @@ func (req *MountRequest) ParseMounterArgs() ([]string, error) { if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { return nil, fmt.Errorf("invalid rclone args decode error: %w", err) } + if err := argsValidator(args.Endpoint, req.Path); err != nil { + return nil, fmt.Errorf("rclone endpoint or target path validation failed: %w", err) + } return args.PopulateArgsSlice(req.Bucket, req.Path) default: From 1ac99f18c3a28320fd01dc7bbef62e25e8a1b393 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 23 Apr 2025 08:47:21 +0530 Subject: [PATCH 17/39] support additional params for S3FS --- cos-csi-mounter/server/utils.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index 201ffead..033cc3a7 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -23,6 +23,13 @@ type S3FSArgs struct { URL string `json:"url,omitempty"` PasswdFilePath string `json:"passwd_file,omitempty"` UsePathRequestStyle string `json:"use_path_request_style,omitempty"` + SigV2 string `json:"sigv2,omitempty"` + AllowOther string `json:"allow_other,omitempty"` + MPUmask string `json:"mp_umask,omitempty"` + EndPoint string `json:"endpoint,omitempty"` + IBMIamAuth string `json:"ibm_iam_auth,omitempty"` + IBMIamEndpoint string `json:"ibm_iam_endpoint,omitempty"` + DefaultACL string `json:"default_acl,omitempty"` } func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { From 3bf775f148d1ea8dc4b6e6b4903a3b4b34f906c8 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 23 Apr 2025 08:50:50 +0530 Subject: [PATCH 18/39] update log message Signed-off-by: Mayank Sachan --- cos-csi-mounter/server/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index c3e385c1..54f83d2f 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -117,7 +117,7 @@ func handleCosMount() gin.HandlerFunc { // validate mounter args args, err := request.ParseMounterArgs() if err != nil { - logger.Error("Invalid args", zap.Any("mounter", request.Mounter), zap.Error(err)) + logger.Error("Failed to parse mounter args", zap.Any("mounter", request.Mounter), zap.Error(err)) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid args for mounter"}) return } From 79dfca8fca10420ea6fe5914f9cd8ea8416200c8 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 23 Apr 2025 14:19:50 +0530 Subject: [PATCH 19/39] handle boolean params Signed-off-by: Mayank Sachan --- cos-csi-mounter/server/utils.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index 033cc3a7..a7cb65b1 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -49,7 +49,11 @@ func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, err result := []string{bucket, targetPath} for k, v := range m { result = append(result, "-o") - result = append(result, fmt.Sprintf("%s=%v", k, v)) // -o, key=value + if strings.ToLower(strings.TrimSpace(v)) == "true" { + result = append(result, fmt.Sprintf("%s", k)) // -o, key + } else { + result = append(result, fmt.Sprintf("%s=%v", k, v)) // -o, key=value + } } return result, nil // [bucket, path, -o, key1=value1, -o, key2=value2] From 02e114ccf9e6e92f56cbde607d5119a1591977a4 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 23 Apr 2025 14:39:32 +0530 Subject: [PATCH 20/39] fix linter --- cos-csi-mounter/server/utils.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index a7cb65b1..bcb5a386 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -39,8 +39,8 @@ func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, err return nil, err } - // Unmarshal into map[string]interface{} - var m map[string]interface{} + // Unmarshal into map[string]string + var m map[string]string if err := json.Unmarshal(raw, &m); err != nil { return nil, err } @@ -73,8 +73,8 @@ func (args RCloneArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, e return nil, err } - // Unmarshal into map[string]interface{} - var m map[string]interface{} + // Unmarshal into map[string]string + var m map[string]string if err := json.Unmarshal(raw, &m); err != nil { return nil, err } From 871dfd5c26cce51efc69b3d3b97742007cb90e54 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 23 Apr 2025 15:20:32 +0530 Subject: [PATCH 21/39] fix build Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- cos-csi-mounter/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 6c4bca3f..b1f6d1e4 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-16T09:55:03Z", + "generated_at": "2025-04-23T09:50:09Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/cos-csi-mounter/Makefile b/cos-csi-mounter/Makefile index d6b370d9..c80e149d 100644 --- a/cos-csi-mounter/Makefile +++ b/cos-csi-mounter/Makefile @@ -21,7 +21,7 @@ ut-coverage: test go mod tidy build-linux: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod mod -o ${BIN_DIR}/cos-csi-mounter-server -ldflags "-s -w" -a ./server/server.go + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -mod mod -o ${BIN_DIR}/cos-csi-mounter-server -ldflags "-s -w" -a ./server deb-build: deb-build: build-linux From add5cb4232ba716b6a45505157a17c2c1d46554b Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 23 Apr 2025 15:23:45 +0530 Subject: [PATCH 22/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- cos-csi-mounter/server/utils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index bcb5a386..7e381cf9 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -19,6 +19,7 @@ type MountRequest struct { type MounterArgs interface { PopulateArgsSlice(string, string) ([]string, error) } + type S3FSArgs struct { URL string `json:"url,omitempty"` PasswdFilePath string `json:"passwd_file,omitempty"` From f0eb74fa2358d5a3bd1e7c5b62606a2d6d813532 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Mon, 28 Apr 2025 12:20:30 +0530 Subject: [PATCH 23/39] update supported args list for s3fs & rclone --- cos-csi-mounter/server/rclone.go | 70 +++++++++++++++++++++++++ cos-csi-mounter/server/s3fs.go | 90 ++++++++++++++++++++++++++++++++ cos-csi-mounter/server/server.go | 3 +- cos-csi-mounter/server/utils.go | 85 +++--------------------------- 4 files changed, 168 insertions(+), 80 deletions(-) create mode 100644 cos-csi-mounter/server/rclone.go create mode 100644 cos-csi-mounter/server/s3fs.go diff --git a/cos-csi-mounter/server/rclone.go b/cos-csi-mounter/server/rclone.go new file mode 100644 index 00000000..827e60ff --- /dev/null +++ b/cos-csi-mounter/server/rclone.go @@ -0,0 +1,70 @@ +package main + +import ( + "encoding/json" + "fmt" +) + +type RCloneArgs struct { + AllowOther string `json:"allow-other,omitempty"` + AllowRoot string `json:"allow-root,omitempty"` + AsyncRead string `json:"async-read,omitempty"` + AttrTimeout string `josn:"attr-timeout,omitempty"` + ConfigPath string `json:"config,omitempty"` + Daemon string `json:"daemon,omitempty"` + DaemonTimeout string `json:"daemon-timeout,omitempty"` + DaemonWait string `json:"daemon-wait,omitempty"` + DirCacheTime string `json:"dir-cache-time,omitempty"` + DirectIO string `json:"direct-io,omitempty"` + GID string `json:"gid,omitempty"` + LogFile string `json:"log-file,omitempty"` + NoModificationTime string `json:"no-modtime,omitempty"` + PollInterval string `json:"poll-interval,omitempty"` + ReadOnly string `json:"read-only,omitempty"` + UID string `json:"uid,omitempty"` + UMask string `json:"umask,omitempty"` + VfsCacheMaxAge string `json:"vfs-cache-max-age,omitempty"` + VfsCacheMaxSize string `json:"vfs-cache-max-size,omitempty"` + VfsCacheMinFreeSpace string `json:"vfs-cache-min-free-space,omitempty"` + VfsCacheMode string `json:"vfs-cache-mode,omitempty"` + VfsCachePollInterval string `json:"vfs-cache-poll-interval,omitempty"` + VfsDiskSpaceTotalSize string `json:"vfs-disk-space-total-size,omitempty"` + VfsReadAhead string `json:"vfs-read-ahead,omitempty"` + VfsReadChunkSize string `json:"vfs-read-chunk-size,omitempty"` + VfsReadChunkSizeLimit string `json:"vfs-read-chunk-size-limit,omitempty"` + VfsReadChunkStreams string `json:"vfs-read-chunk-streams,omitempty"` + VfsReadWait string `json:"vfs-read-wait,omitempty"` + VfsRefresh string `json:"vfs-refresh,omitempty"` + VfsWriteBack string `json:"vfs-write-back,omitempty"` + VfsWriteWait string `json:"vfs-write-wait,omitempty"` + WriteBackCache string `json:"write-back-cache,omitempty"` +} + +func (args RCloneArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { + // Marshal to JSON + raw, err := json.Marshal(args) + if err != nil { + return nil, err + } + + // Unmarshal into map[string]string + var m map[string]string + if err := json.Unmarshal(raw, &m); err != nil { + return nil, err + } + + // Convert to key=value slice + result := []string{"mount", bucket, targetPath} + for k, v := range m { + result = append(result, fmt.Sprintf("--%s=%v", k, v)) // --key=value + } + + return result, nil // [mount, bucket, path, --key1=value1, --key2=value2, ...] +} + +func (args RCloneArgs) Validate(targetPath string) error { + if err := pathValidator(targetPath); err != nil { + return err + } + return nil +} diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go new file mode 100644 index 00000000..d419fc70 --- /dev/null +++ b/cos-csi-mounter/server/s3fs.go @@ -0,0 +1,90 @@ +package main + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" + + "go.uber.org/zap" +) + +type S3FSArgs struct { + AllowOther string `json:"allow_other,omitempty"` + AutoCache string `json:"auto_cache,omitempty"` + CipherSuites string `json:"cipher_suites,omitempty"` + ConnectTimeoutSeconds string `json:"connect_timeout,omitempty"` + CurlDebug string `json:"curldbg,omitempty"` + DebugLevel string `json:"dbglevel,omitempty"` + DefaultACL string `json:"default_acl,omitempty"` + EndPoint string `json:"endpoint,omitempty"` + GID string `json:"gid,omitempty"` + IBMIamAuth string `json:"ibm_iam_auth,omitempty"` + IBMIamEndpoint string `json:"ibm_iam_endpoint,omitempty"` + InstanceName string `json:"instance_name,omitempty"` + KernelCache string `json:"kernel_cache,omitempty"` + MaxBackground string `json:"max_background,omitempty"` + MaxStatCacheSize string `json:"max_stat_cache_size,omitempty"` + MPUmask string `json:"mp_umask,omitempty"` + MultipartSize string `json:"multipart_size,omitempty"` + MultiReqMax string `json:"multireq_max,omitempty"` + ParallelCount string `json:"parallel_count,omitempty"` + PasswdFilePath string `json:"passwd_file,omitempty"` + ReadOnly string `json:"ro,omitempty"` + ReadwriteTimeoutSeconds string `json:"readwrite_timeout,omitempty"` + RetryCount string `json:"retries,omitempty"` + SigV2 string `json:"sigv2,omitempty"` + SigV4 string `json:"sigv4,omitempty"` + StatCacheExpireSeconds string `json:"stat_cache_expire,omitempty"` + UID string `json:"uid,omitempty"` + URL string `json:"url,omitempty"` + UsePathRequestStyle string `json:"use_path_request_style,omitempty"` + UseXattr string `json:"use_xattr,string,omitempty"` +} + +func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { + // Marshal to JSON + raw, err := json.Marshal(args) + if err != nil { + return nil, err + } + + // Unmarshal into map[string]string + var m map[string]string + if err := json.Unmarshal(raw, &m); err != nil { + return nil, err + } + + // Convert to key=value slice + result := []string{bucket, targetPath} + for k, v := range m { + result = append(result, "-o") + if strings.ToLower(strings.TrimSpace(v)) == "true" { + result = append(result, fmt.Sprintf("%s", k)) // -o, key + } else { + result = append(result, fmt.Sprintf("%s=%v", k, v)) // -o, key=value + } + } + + return result, nil // [bucket, path, -o, key1=value1, -o, key2=value2, -o key3, ...] +} + +func (args S3FSArgs) Validate(targetPath string) error { + if err := pathValidator(targetPath); err != nil { + return err + } + if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { + return fmt.Errorf("Bad value for target path \"%v\"", targetPath) + } + + retryCount, err := strconv.Atoi(args.RetryCount) + if err != nil { + logger.Error("cannot convert value of retires into integer", zap.Error(err)) + return fmt.Errorf("Cannot convert value of retires into integer: %v", err) + } + if retryCount < 1 { + logger.Error("value of retires should be >= 1", zap.Error(err)) + return fmt.Errorf("value of retires should be >= 1") + } + return nil +} diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 54f83d2f..0f14f9ad 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -98,7 +98,6 @@ func main() { func handleCosMount() gin.HandlerFunc { return func(c *gin.Context) { var request MountRequest - logger.Info("New mount request with values: ", zap.Any("Request:", request)) if err := c.BindJSON(&request); err != nil { logger.Error("Invalid request: ", zap.Error(err)) @@ -106,7 +105,7 @@ func handleCosMount() gin.HandlerFunc { return } - logger.Info("New mount request with values: ", zap.String("Path:", request.Path), zap.String("Mounter:", request.Mounter), zap.Any("Args:", request.Args)) + logger.Info("New mount request with values:", zap.String("Bucket", request.Bucket), zap.String("Path", request.Path), zap.String("Mounter", request.Mounter), zap.Any("Args", request.Args)) if request.Mounter != s3fs && request.Mounter != rclone { logger.Error("Invalid Request!!!!") diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index bcb5a386..36167e27 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -17,75 +17,8 @@ type MountRequest struct { // MounterArgs ... type MounterArgs interface { - PopulateArgsSlice(string, string) ([]string, error) -} -type S3FSArgs struct { - URL string `json:"url,omitempty"` - PasswdFilePath string `json:"passwd_file,omitempty"` - UsePathRequestStyle string `json:"use_path_request_style,omitempty"` - SigV2 string `json:"sigv2,omitempty"` - AllowOther string `json:"allow_other,omitempty"` - MPUmask string `json:"mp_umask,omitempty"` - EndPoint string `json:"endpoint,omitempty"` - IBMIamAuth string `json:"ibm_iam_auth,omitempty"` - IBMIamEndpoint string `json:"ibm_iam_endpoint,omitempty"` - DefaultACL string `json:"default_acl,omitempty"` -} - -func (args S3FSArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { - // Marshal to JSON - raw, err := json.Marshal(args) - if err != nil { - return nil, err - } - - // Unmarshal into map[string]string - var m map[string]string - if err := json.Unmarshal(raw, &m); err != nil { - return nil, err - } - - // Convert to key=value slice - result := []string{bucket, targetPath} - for k, v := range m { - result = append(result, "-o") - if strings.ToLower(strings.TrimSpace(v)) == "true" { - result = append(result, fmt.Sprintf("%s", k)) // -o, key - } else { - result = append(result, fmt.Sprintf("%s=%v", k, v)) // -o, key=value - } - } - - return result, nil // [bucket, path, -o, key1=value1, -o, key2=value2] -} - -type RCloneArgs struct { - Endpoint string `json:"endpoint,omitempty"` - BackupDir string `json:"backup-dir,omitempty"` - Bind string `json:"bind,omitempty"` - BWLimit string `json:"bwlimit,omitempty"` -} - -func (args RCloneArgs) PopulateArgsSlice(bucket, targetPath string) ([]string, error) { - // Marshal to JSON - raw, err := json.Marshal(args) - if err != nil { - return nil, err - } - - // Unmarshal into map[string]string - var m map[string]string - if err := json.Unmarshal(raw, &m); err != nil { - return nil, err - } - - // Convert to key=value slice - result := []string{"mount", bucket, targetPath} - for k, v := range m { - result = append(result, fmt.Sprintf("--%s=%v", k, v)) // --key=value - } - - return result, nil // [mount, bucket, path, --key1=value1, --key2=value2] + Validate(path string) error + PopulateArgsSlice(bucket, path string) ([]string, error) } func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { @@ -94,11 +27,7 @@ func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { return dec.Decode(v) } -func argsValidator(endpoint, targetPath string) error { - if !(strings.HasPrefix(endpoint, "https://") || strings.HasPrefix(endpoint, "http://")) { - return fmt.Errorf("Bad value for COS endpoint \"%v\": scheme is missing. "+ - "Must be of the form http:// or https://", endpoint) - } +func pathValidator(targetPath string) error { if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { return fmt.Errorf("Bad value for target path \"%v\"", targetPath) } @@ -114,8 +43,8 @@ func (req *MountRequest) ParseMounterArgs() ([]string, error) { if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { return nil, fmt.Errorf("invalid s3fs args decode error: %w", err) } - if err := argsValidator(args.URL, req.Path); err != nil { - return nil, fmt.Errorf("s3fs endpoint or target path validation failed: %w", err) + if err := args.Validate(req.Path); err != nil { + return nil, fmt.Errorf("s3fs args validation failed: %w", err) } return args.PopulateArgsSlice(req.Bucket, req.Path) @@ -124,8 +53,8 @@ func (req *MountRequest) ParseMounterArgs() ([]string, error) { if err := strictDecodeForUnknownFields(req.Args, &args); err != nil { return nil, fmt.Errorf("invalid rclone args decode error: %w", err) } - if err := argsValidator(args.Endpoint, req.Path); err != nil { - return nil, fmt.Errorf("rclone endpoint or target path validation failed: %w", err) + if err := args.Validate(req.Path); err != nil { + return nil, fmt.Errorf("rclone args validation failed: %w", err) } return args.PopulateArgsSlice(req.Bucket, req.Path) From a6138b29ca32898516948cc64c4552c0500cc3e7 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Mon, 28 Apr 2025 14:06:58 +0530 Subject: [PATCH 24/39] Remove duplicate code --- cos-csi-mounter/server/s3fs.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index d419fc70..f1ede816 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -73,9 +73,6 @@ func (args S3FSArgs) Validate(targetPath string) error { if err := pathValidator(targetPath); err != nil { return err } - if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { - return fmt.Errorf("Bad value for target path \"%v\"", targetPath) - } retryCount, err := strconv.Atoi(args.RetryCount) if err != nil { From 22be4bfc03da6bf1c5301df71f79556e242dcfb5 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 28 Apr 2025 15:03:22 +0530 Subject: [PATCH 25/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index b1f6d1e4..18942289 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-23T09:50:09Z", + "generated_at": "2025-04-28T09:33:18Z", "plugins_used": [ { "name": "AWSKeyDetector" From 6e0d601fb6bac7325d2c141ac09cea60d8635059 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Mon, 28 Apr 2025 15:39:17 +0530 Subject: [PATCH 26/39] Add max_drity_data s3fs param Signed-off-by: Mayank Sachan --- cos-csi-mounter/server/s3fs.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index f1ede816..9f3237e0 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -24,6 +24,7 @@ type S3FSArgs struct { InstanceName string `json:"instance_name,omitempty"` KernelCache string `json:"kernel_cache,omitempty"` MaxBackground string `json:"max_background,omitempty"` + MaxDirtyData string `json:"max_dirty_data,omitempty"` MaxStatCacheSize string `json:"max_stat_cache_size,omitempty"` MPUmask string `json:"mp_umask,omitempty"` MultipartSize string `json:"multipart_size,omitempty"` From d9556b12f9996373af6476b1b19dd24ae2318ccd Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Mon, 28 Apr 2025 15:43:14 +0530 Subject: [PATCH 27/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index 18942289..a4dd74bd 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-28T09:33:18Z", + "generated_at": "2025-04-28T10:13:10Z", "plugins_used": [ { "name": "AWSKeyDetector" From d16c376476881791d1094a8814281034f536c484 Mon Sep 17 00:00:00 2001 From: Mayank Sachan <34068620+mssachan@users.noreply.github.com> Date: Tue, 29 Apr 2025 18:30:47 +0530 Subject: [PATCH 28/39] Add validation for s3fs parameters (#164) * Add validation for s3fs parameters * Add validation for s3fs & rclone args --- cos-csi-mounter/server/rclone.go | 84 ++++++++++++ cos-csi-mounter/server/s3fs.go | 227 +++++++++++++++++++++++++++++-- cos-csi-mounter/server/utils.go | 19 +++ 3 files changed, 322 insertions(+), 8 deletions(-) diff --git a/cos-csi-mounter/server/rclone.go b/cos-csi-mounter/server/rclone.go index 827e60ff..3cb0764e 100644 --- a/cos-csi-mounter/server/rclone.go +++ b/cos-csi-mounter/server/rclone.go @@ -3,6 +3,8 @@ package main import ( "encoding/json" "fmt" + + "go.uber.org/zap" ) type RCloneArgs struct { @@ -66,5 +68,87 @@ func (args RCloneArgs) Validate(targetPath string) error { if err := pathValidator(targetPath); err != nil { return err } + + // Check if value of allow-other parameter is boolean "true" or "false" + if args.AllowOther != "" { + if isBool := isBoolString(args.AllowOther); !isBool { + logger.Error("cannot convert value of allow-other into boolean", zap.Any("allow-other", args.AllowOther)) + return fmt.Errorf("cannot convert value of allow-other into boolean: %v", args.AllowOther) + } + } + + // Check if value of allow-root parameter is boolean "true" or "false" + if args.AllowRoot != "" { + if isBool := isBoolString(args.AllowRoot); !isBool { + logger.Error("cannot convert value of allow-root into boolean", zap.Any("allow-root", args.AllowRoot)) + return fmt.Errorf("cannot convert value of allow-root into boolean: %v", args.AllowRoot) + } + } + + // Check if value of async-read parameter is boolean "true" or "false" + if args.AsyncRead != "" { + if isBool := isBoolString(args.AsyncRead); !isBool { + logger.Error("cannot convert value of async-read into boolean", zap.Any("async-read", args.AsyncRead)) + return fmt.Errorf("cannot convert value of async-read into boolean: %v", args.AsyncRead) + } + } + + // Check if rclone config file exists or not + if exists, err := fileExists(args.ConfigPath); err != nil { + logger.Error("error checking file existence", zap.Error(err), zap.Any("path", args.ConfigPath)) + return fmt.Errorf("error checking file existence: %v", err) + } else if !exists { + logger.Error("file not found", zap.Error(err), zap.Any("path", args.ConfigPath)) + return fmt.Errorf("file not found: %v", args.ConfigPath) + } + + // Check if value of daemon parameter is boolean "true" or "false" + if args.Daemon != "" { + if isBool := isBoolString(args.Daemon); !isBool { + logger.Error("cannot convert value of daemon into boolean", zap.Any("daemon", args.Daemon)) + return fmt.Errorf("cannot convert value of daemon into boolean: %v", args.Daemon) + } + } + + // Check if value of direct-io parameter is boolean "true" or "false" + if args.DirectIO != "" { + if isBool := isBoolString(args.DirectIO); !isBool { + logger.Error("cannot convert value of direct-io into boolean", zap.Any("direct-io", args.DirectIO)) + return fmt.Errorf("cannot convert value of direct-io into boolean: %v", args.DirectIO) + } + } + + // Check if value of no-modtime parameter is boolean "true" or "false" + if args.NoModificationTime != "" { + if isBool := isBoolString(args.NoModificationTime); !isBool { + logger.Error("cannot convert value of no-modtime into boolean", zap.Any("no-modtime", args.NoModificationTime)) + return fmt.Errorf("cannot convert value of no-modtime into boolean: %v", args.NoModificationTime) + } + } + + // Check if value of read-only parameter is boolean "true" or "false" + if args.ReadOnly != "" { + if isBool := isBoolString(args.ReadOnly); !isBool { + logger.Error("cannot convert value of read-only into boolean", zap.Any("read-only", args.ReadOnly)) + return fmt.Errorf("cannot convert value of read-only into boolean: %v", args.ReadOnly) + } + } + + // Check if value of vfs-refresh parameter is boolean "true" or "false" + if args.VfsRefresh != "" { + if isBool := isBoolString(args.VfsRefresh); !isBool { + logger.Error("cannot convert value of vfs-refresh into boolean", zap.Any("vfs-refresh", args.VfsRefresh)) + return fmt.Errorf("cannot convert value of vfs-refresh into boolean: %v", args.VfsRefresh) + } + } + + // Check if value of write-back-cache parameter is boolean "true" or "false" + if args.WriteBackCache != "" { + if isBool := isBoolString(args.WriteBackCache); !isBool { + logger.Error("cannot convert value of write-back-cache into boolean", zap.Any("write-back-cache", args.WriteBackCache)) + return fmt.Errorf("cannot convert value of write-back-cache into boolean: %v", args.WriteBackCache) + } + } + return nil } diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index 9f3237e0..728ad352 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -27,7 +27,7 @@ type S3FSArgs struct { MaxDirtyData string `json:"max_dirty_data,omitempty"` MaxStatCacheSize string `json:"max_stat_cache_size,omitempty"` MPUmask string `json:"mp_umask,omitempty"` - MultipartSize string `json:"multipart_size,omitempty"` + MultiPartSize string `json:"multipart_size,omitempty"` MultiReqMax string `json:"multireq_max,omitempty"` ParallelCount string `json:"parallel_count,omitempty"` PasswdFilePath string `json:"passwd_file,omitempty"` @@ -75,14 +75,225 @@ func (args S3FSArgs) Validate(targetPath string) error { return err } - retryCount, err := strconv.Atoi(args.RetryCount) - if err != nil { - logger.Error("cannot convert value of retires into integer", zap.Error(err)) - return fmt.Errorf("Cannot convert value of retires into integer: %v", err) + // Check if value of allow_other parameter is boolean "true" or "false" + if args.AllowOther != "" { + if isBool := isBoolString(args.AllowOther); !isBool { + logger.Error("cannot convert value of allow_other into boolean", zap.Any("allow_other", args.AllowOther)) + return fmt.Errorf("cannot convert value of allow_other into boolean: %v", args.AllowOther) + } + } + + // Check if value of auto_cache parameter is boolean "true" or "false" + if args.AutoCache != "" { + if isBool := isBoolString(args.AutoCache); !isBool { + logger.Error("cannot convert value of auto_cache into boolean", zap.Any("auto_cache", args.AutoCache)) + return fmt.Errorf("cannot convert value of auto_cache into boolean: %v", args.AutoCache) + } + } + + // Check if value of connect_timeout parameter can be converted to integer + if args.ConnectTimeoutSeconds != "" { + _, err := strconv.Atoi(args.ConnectTimeoutSeconds) + if err != nil { + logger.Error("cannot convert value of connect_timeout into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of connect_timeout into integer: %v", err) + } + } + + // Check if value of curldbg parameter is either "body" or "normal" + if args.CurlDebug != "" && !(args.CurlDebug == "body" || args.CurlDebug == "normal") { + logger.Error("invalid value for 'curldbg' param. Should be either 'body' or 'normal'", zap.Any("curldbg", args.CurlDebug)) + return fmt.Errorf("invalid value for 'curldbg' param. Should be either 'body' or 'normal': %v", args.CurlDebug) + } + + if !(strings.HasPrefix(args.EndPoint, "https://") || strings.HasPrefix(args.EndPoint, "http://")) { + logger.Error("bad value for endpoint: scheme is missing."+ + " Must be of the form http:// or https://", + zap.String("endpoint", args.EndPoint)) + return fmt.Errorf("bad value for endpoint \"%v\": scheme is missing."+ + " Must be of the form http:// or https://", args.EndPoint) + } + + // Check if value of gid parameter can be converted to integer + if args.GID != "" { + _, err := strconv.Atoi(args.GID) + if err != nil { + logger.Error("cannot convert value of gid into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of gid into integer: %v", err) + } + } + + // Check if value of ibm_iam_auth parameter is boolean "true" or "false" + if args.IBMIamAuth != "" { + if isBool := isBoolString(args.IBMIamAuth); !isBool { + logger.Error("cannot convert value of ibm_iam_auth into boolean", zap.Any("ibm_iam_auth", args.IBMIamAuth)) + return fmt.Errorf("cannot convert value of ibm_iam_auth into boolean: %v", args.IBMIamAuth) + } + } + + if args.IBMIamEndpoint != "" { + if !(strings.HasPrefix(args.IBMIamEndpoint, "https://") || strings.HasPrefix(args.IBMIamEndpoint, "http://")) { + logger.Error("bad value for ibm_iam_endpoint."+ + " Must be of the form https:// or http://", + zap.String("ibm_iam_endpoint", args.IBMIamEndpoint)) + return fmt.Errorf("bad value for ibm_iam_endpoint \"%v\":"+ + " Must be of the form https:// or http://", args.IBMIamEndpoint) + } + } + + // Check if value of kernel_cache parameter is boolean "true" or "false" + if args.KernelCache != "" { + if isBool := isBoolString(args.KernelCache); !isBool { + logger.Error("cannot convert value of kernel_cache into boolean", zap.Any("kernel_cache", args.KernelCache)) + return fmt.Errorf("cannot convert value of kernel_cache into boolean: %v", args.KernelCache) + } + } + + // Check if value of max_background parameter can be converted to integer + if args.MaxBackground != "" { + _, err := strconv.Atoi(args.MaxBackground) + if err != nil { + logger.Error("cannot convert value of max_background into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of max_background into integer: %v", err) + } + } + + // Check if value of max_dirty_data parameter can be converted to integer + if args.MaxDirtyData != "" { + _, err := strconv.Atoi(args.MaxDirtyData) + if err != nil { + logger.Error("cannot convert value of max_dirty_data into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of max_dirty_data into integer: %v", err) + } + } + + // Check if value of max_stat_cache_size parameter can be converted to integer + if args.MaxStatCacheSize != "" { + _, err := strconv.Atoi(args.MaxStatCacheSize) + if err != nil { + logger.Error("cannot convert value of max_stat_cache_size into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of max_stat_cache_size into integer: %v", err) + } + } + + // Check if value of multipart_size parameter can be converted to integer + if args.MultiPartSize != "" { + _, err := strconv.Atoi(args.MultiPartSize) + if err != nil { + logger.Error("cannot convert value of multipart_size into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of multipart_size into integer: %v", err) + } } - if retryCount < 1 { - logger.Error("value of retires should be >= 1", zap.Error(err)) - return fmt.Errorf("value of retires should be >= 1") + + // Check if value of multireq_max parameter can be converted to integer + if args.MultiReqMax != "" { + _, err := strconv.Atoi(args.MultiReqMax) + if err != nil { + logger.Error("cannot convert value of multireq_max into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of multireq_max into integer: %v", err) + } + } + + // Check if value of parallel_count parameter can be converted to integer + if args.ParallelCount != "" { + _, err := strconv.Atoi(args.ParallelCount) + if err != nil { + logger.Error("cannot convert value of parallel_count into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of parallel_count into integer: %v", err) + } + } + + // Check if .passwd file exists or not + if exists, err := fileExists(args.PasswdFilePath); err != nil { + logger.Error("error checking file existence", zap.Error(err), zap.Any("path", args.PasswdFilePath)) + return fmt.Errorf("error checking file existence: %v", err) + } else if !exists { + logger.Error("file not found", zap.Error(err), zap.Any("path", args.PasswdFilePath)) + return fmt.Errorf("file not found: %v", args.PasswdFilePath) + } + + // Check if value of ro parameter is boolean "true" or "false" + if args.ReadOnly != "" { + if isBool := isBoolString(args.ReadOnly); !isBool { + logger.Error("cannot convert value of ro into boolean", zap.Any("ro", args.ReadOnly)) + return fmt.Errorf("cannot convert value of roe into boolean: %v", args.ReadOnly) + } + } + + // Check if value of readwrite_timeout parameter can be converted to integer + if args.ReadwriteTimeoutSeconds != "" { + _, err := strconv.Atoi(args.ReadwriteTimeoutSeconds) + if err != nil { + logger.Error("cannot convert value of readwrite_timeout into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of readwrite_timeout into integer: %v", err) + } + } + + // Check if value of retries parameter can be converted to integer + if args.RetryCount != "" { + retryCount, err := strconv.Atoi(args.RetryCount) + if err != nil { + logger.Error("cannot convert value of retires into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of retires into integer: %v", err) + } + if retryCount < 1 { + logger.Error("value of retires should be >= 1") + return fmt.Errorf("value of retires should be >= 1") + } + } + + // Check if value of sigv2 parameter is boolean "true" or "false" + if args.SigV2 != "" { + if isBool := isBoolString(args.SigV2); !isBool { + logger.Error("cannot convert value of sigv2 into boolean", zap.Any("sigv2", args.SigV2)) + return fmt.Errorf("cannot convert value of sigv2 into boolean: %v", args.SigV2) + } + } + + // Check if value of sigv4 parameter is boolean "true" or "false" + if args.SigV4 != "" { + if isBool := isBoolString(args.SigV4); !isBool { + logger.Error("cannot convert value of sigv4 into boolean", zap.Any("sigv4", args.SigV4)) + return fmt.Errorf("cannot convert value of sigv4 into boolean: %v", args.SigV4) + } + } + + // Check if value of stat_cache_expire parameter can be converted to integer + if args.StatCacheExpireSeconds != "" { + cacheExpireSeconds, err := strconv.Atoi(args.StatCacheExpireSeconds) + if err != nil { + logger.Error("cannot convert value of stat_cache_expire into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of stat_cache_expire into integer: %v", err) + } else if cacheExpireSeconds < 0 { + logger.Error("value of stat_cache_expire should be >= 0") + return fmt.Errorf("value ofstat_cache_expire should be >= 0") + } + } + + // Check if value of uid parameter can be converted to integer + if args.UID != "" { + _, err := strconv.Atoi(args.UID) + if err != nil { + logger.Error("cannot convert value of uid into integer", zap.Error(err)) + return fmt.Errorf("cannot convert value of uid into integer: %v", err) + } + } + + // Check if value of use_path_request_style parameter is boolean "true" or "false" + if args.UsePathRequestStyle != "" { + if isBool := isBoolString(args.UsePathRequestStyle); !isBool { + logger.Error("cannot convert value of use_path_request_style into boolean", zap.Any("use_path_request_style", args.UsePathRequestStyle)) + return fmt.Errorf("cannot convert value of use_path_request_style into boolean: %v", args.UsePathRequestStyle) + } } + + // Check if value of use_xattr parameter is boolean "true" or "false" + if args.UseXattr != "" { + if isBool := isBoolString(args.UseXattr); !isBool { + logger.Error("cannot convert value of use_xattr into boolean", zap.Any("use_xattr", args.UseXattr)) + return fmt.Errorf("cannot convert value of use_xattr into boolean: %v", args.UseXattr) + } + } + return nil } diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index 36167e27..36ced396 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "os" "strings" ) @@ -62,3 +63,21 @@ func (req *MountRequest) ParseMounterArgs() ([]string, error) { return nil, fmt.Errorf("unknown mounter: %s", req.Mounter) } } + +// isBoolString checks if a string is "true" or "false" (case-insensitive) +func isBoolString(s string) bool { + s = strings.TrimSpace(strings.ToLower(s)) + return s == "true" || s == "false" +} + +// fileExists checks whether the given file path exists and is not a directory. +func fileExists(path string) (bool, error) { + info, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + return false, err + } + return !info.IsDir(), nil +} From 095d546120bf10913221e93970022f6711d53f05 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Tue, 29 Apr 2025 23:58:38 +0530 Subject: [PATCH 29/39] Fix typo in rclone args --- cos-csi-mounter/server/rclone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cos-csi-mounter/server/rclone.go b/cos-csi-mounter/server/rclone.go index 3cb0764e..3820bb35 100644 --- a/cos-csi-mounter/server/rclone.go +++ b/cos-csi-mounter/server/rclone.go @@ -11,7 +11,7 @@ type RCloneArgs struct { AllowOther string `json:"allow-other,omitempty"` AllowRoot string `json:"allow-root,omitempty"` AsyncRead string `json:"async-read,omitempty"` - AttrTimeout string `josn:"attr-timeout,omitempty"` + AttrTimeout string `json:"attr-timeout,omitempty"` ConfigPath string `json:"config,omitempty"` Daemon string `json:"daemon,omitempty"` DaemonTimeout string `json:"daemon-timeout,omitempty"` From 2de03aaab6ff0d952d52cfea2a4d880836225ae3 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 30 Apr 2025 15:01:38 +0530 Subject: [PATCH 30/39] Fix json reponse --- cos-csi-mounter/server/server.go | 32 ++++++++++++++++---------------- cos-csi-mounter/server/utils.go | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 0f14f9ad..231da821 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -2,6 +2,7 @@ package main import ( "flag" + "fmt" "net" "net/http" "os" @@ -100,36 +101,37 @@ func handleCosMount() gin.HandlerFunc { var request MountRequest if err := c.BindJSON(&request); err != nil { - logger.Error("Invalid request: ", zap.Error(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + logger.Error("invalid request: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } logger.Info("New mount request with values:", zap.String("Bucket", request.Bucket), zap.String("Path", request.Path), zap.String("Mounter", request.Mounter), zap.Any("Args", request.Args)) if request.Mounter != s3fs && request.Mounter != rclone { - logger.Error("Invalid Request!!!!") - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + logger.Error("invalid mounter", zap.Any("mounter", request.Mounter)) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid mounter"}) return } // validate mounter args args, err := request.ParseMounterArgs() if err != nil { - logger.Error("Failed to parse mounter args", zap.Any("mounter", request.Mounter), zap.Error(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid args for mounter"}) + logger.Error("failed to parse mounter args", zap.Any("mounter", request.Mounter), zap.Error(err)) + + c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("invalid args for mounter: %v", err)}) return } utils := mounterUtils.MounterOptsUtils{} err = utils.FuseMount(request.Path, request.Mounter, args) if err != nil { - logger.Error("Mount Failed: ", zap.Error(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": "Mount Failed"}) + logger.Error("mount failed: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("mount failed: %v", err)}) return } - logger.Info("New COS Mount is Successfull") + logger.Info("bucket mount is successful", zap.Any("bucket", request.Bucket), zap.Any("path", request.Path)) c.JSON(http.StatusOK, "Success!!") } } @@ -140,11 +142,9 @@ func handleCosUnmount() gin.HandlerFunc { Path string `json:"path"` } - logger.Info("New unmount request with values: ", zap.Any("Request:", request)) - if err := c.BindJSON(&request); err != nil { - logger.Error("Invalid request: ", zap.Error(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + logger.Error("invalid request: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"}) return } @@ -153,12 +153,12 @@ func handleCosUnmount() gin.HandlerFunc { utils := mounterUtils.MounterOptsUtils{} err := utils.FuseUnmount(request.Path) if err != nil { - logger.Error("UnMount Failed: ", zap.Error(err)) - c.JSON(http.StatusBadRequest, gin.H{"error": "Mount Failed"}) + logger.Error("unmount failed: ", zap.Error(err)) + c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("unmount failed :%v", err)}) return } - logger.Info("COS UnMount is Successfull") + logger.Info("bucket unmount is Successful", zap.Any("path", request.Path)) c.JSON(http.StatusOK, "Success!!") } } diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index 36ced396..a813b330 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -30,7 +30,7 @@ func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { func pathValidator(targetPath string) error { if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { - return fmt.Errorf("Bad value for target path \"%v\"", targetPath) + return fmt.Errorf("bad value for target path \"%v\"", targetPath) } return nil } From cd01e3485aaf60c24df31614c241c0a33b662216 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 30 Apr 2025 15:48:13 +0530 Subject: [PATCH 31/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index a4dd74bd..747b3902 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-28T10:13:10Z", + "generated_at": "2025-04-30T10:16:51Z", "plugins_used": [ { "name": "AWSKeyDetector" From d6cd02ed75c0341d7d5d0aca1472263b4b63056d Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 30 Apr 2025 16:22:43 +0530 Subject: [PATCH 32/39] Fix linter issues --- cos-csi-mounter/server/rclone.go | 8 ++++---- cos-csi-mounter/server/s3fs.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cos-csi-mounter/server/rclone.go b/cos-csi-mounter/server/rclone.go index 3820bb35..90b5ef33 100644 --- a/cos-csi-mounter/server/rclone.go +++ b/cos-csi-mounter/server/rclone.go @@ -95,11 +95,11 @@ func (args RCloneArgs) Validate(targetPath string) error { // Check if rclone config file exists or not if exists, err := fileExists(args.ConfigPath); err != nil { - logger.Error("error checking file existence", zap.Error(err), zap.Any("path", args.ConfigPath)) - return fmt.Errorf("error checking file existence: %v", err) + logger.Error("error checking rclone config file existence", zap.Error(err)) + return fmt.Errorf("error checking rclone config file existence: %v", err) } else if !exists { - logger.Error("file not found", zap.Error(err), zap.Any("path", args.ConfigPath)) - return fmt.Errorf("file not found: %v", args.ConfigPath) + logger.Error("rclone config file not found") + return fmt.Errorf("rclone config file not found") } // Check if value of daemon parameter is boolean "true" or "false" diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index 728ad352..6e1933af 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -205,11 +205,11 @@ func (args S3FSArgs) Validate(targetPath string) error { // Check if .passwd file exists or not if exists, err := fileExists(args.PasswdFilePath); err != nil { - logger.Error("error checking file existence", zap.Error(err), zap.Any("path", args.PasswdFilePath)) - return fmt.Errorf("error checking file existence: %v", err) + logger.Error("error checking credential file existence", zap.Error(err)) + return fmt.Errorf("error checking credential file existence: %v", err) } else if !exists { - logger.Error("file not found", zap.Error(err), zap.Any("path", args.PasswdFilePath)) - return fmt.Errorf("file not found: %v", args.PasswdFilePath) + logger.Error("credntial file not found") + return fmt.Errorf("credential file not found") } // Check if value of ro parameter is boolean "true" or "false" From e2fa792535f2507c04c749c24eea0d8c61eb302b Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 30 Apr 2025 16:24:39 +0530 Subject: [PATCH 33/39] FIx typo --- cos-csi-mounter/server/s3fs.go | 2 +- cos-csi-mounter/server/server.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index 6e1933af..b97fe389 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -208,7 +208,7 @@ func (args S3FSArgs) Validate(targetPath string) error { logger.Error("error checking credential file existence", zap.Error(err)) return fmt.Errorf("error checking credential file existence: %v", err) } else if !exists { - logger.Error("credntial file not found") + logger.Error("credential file not found") return fmt.Errorf("credential file not found") } diff --git a/cos-csi-mounter/server/server.go b/cos-csi-mounter/server/server.go index 231da821..59018622 100644 --- a/cos-csi-mounter/server/server.go +++ b/cos-csi-mounter/server/server.go @@ -158,7 +158,7 @@ func handleCosUnmount() gin.HandlerFunc { return } - logger.Info("bucket unmount is Successful", zap.Any("path", request.Path)) + logger.Info("bucket unmount is successful", zap.Any("path", request.Path)) c.JSON(http.StatusOK, "Success!!") } } From 4980dd11395f846e88799020bad3fc9778c55206 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Wed, 30 Apr 2025 16:51:48 +0530 Subject: [PATCH 34/39] Fix validation for s3fs url arg --- cos-csi-mounter/server/s3fs.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index b97fe389..b0c8a602 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -106,14 +106,6 @@ func (args S3FSArgs) Validate(targetPath string) error { return fmt.Errorf("invalid value for 'curldbg' param. Should be either 'body' or 'normal': %v", args.CurlDebug) } - if !(strings.HasPrefix(args.EndPoint, "https://") || strings.HasPrefix(args.EndPoint, "http://")) { - logger.Error("bad value for endpoint: scheme is missing."+ - " Must be of the form http:// or https://", - zap.String("endpoint", args.EndPoint)) - return fmt.Errorf("bad value for endpoint \"%v\": scheme is missing."+ - " Must be of the form http:// or https://", args.EndPoint) - } - // Check if value of gid parameter can be converted to integer if args.GID != "" { _, err := strconv.Atoi(args.GID) @@ -295,5 +287,13 @@ func (args S3FSArgs) Validate(targetPath string) error { } } + if !(strings.HasPrefix(args.URL, "https://") || strings.HasPrefix(args.URL, "http://")) { + logger.Error("bad value for url: scheme is missing."+ + " Must be of the form http:// or https://", + zap.String("url", args.URL)) + return fmt.Errorf("bad value for url \"%v\": scheme is missing."+ + " Must be of the form http:// or https://", args.URL) + } + return nil } From a595599b67d925349550e14d80dccd1b2bbedc63 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Wed, 30 Apr 2025 17:28:23 +0530 Subject: [PATCH 35/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index 747b3902..b9eb0b5c 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-04-30T10:16:51Z", + "generated_at": "2025-04-30T11:58:20Z", "plugins_used": [ { "name": "AWSKeyDetector" From 1773ddf78f2760c9e6c266ca5e3672a320275547 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Mon, 5 May 2025 17:43:45 +0530 Subject: [PATCH 36/39] Check if paths in payload are safe paths --- cos-csi-mounter/server/utils.go | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cos-csi-mounter/server/utils.go b/cos-csi-mounter/server/utils.go index a813b330..3d6eb5cf 100644 --- a/cos-csi-mounter/server/utils.go +++ b/cos-csi-mounter/server/utils.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "strings" ) @@ -16,6 +17,13 @@ type MountRequest struct { Args json.RawMessage `json:"args"` } +var ( + // Directories where bucket can be mounted + safeMountDirs = []string{"/var/data/kubelet/pods", "/var/lib/kubelet/pods"} + // Directories where s3fs/rclone configuration files need to be present + safeMounterConfigDir = "/var/lib/cos-csi" +) + // MounterArgs ... type MounterArgs interface { Validate(path string) error @@ -29,7 +37,11 @@ func strictDecodeForUnknownFields(data json.RawMessage, v interface{}) error { } func pathValidator(targetPath string) error { - if !(strings.HasPrefix(targetPath, "/var/data/kubelet/pods") || strings.HasPrefix(targetPath, "/var/lib/kubelet/pods")) { + absPath, err := filepath.Abs(targetPath) + if err != nil { + return fmt.Errorf("failed to resolve absolute mount path: %v", err) + } + if !(strings.HasPrefix(absPath, safeMountDirs[0]) || strings.HasPrefix(absPath, safeMountDirs[1])) { return fmt.Errorf("bad value for target path \"%v\"", targetPath) } return nil @@ -72,7 +84,14 @@ func isBoolString(s string) bool { // fileExists checks whether the given file path exists and is not a directory. func fileExists(path string) (bool, error) { - info, err := os.Stat(path) + absPath, err := filepath.Abs(path) + if err != nil { + return false, fmt.Errorf("failed to resolve absolute path: %v", err) + } + if !strings.HasPrefix(absPath, safeMounterConfigDir) { + return false, fmt.Errorf("path %v is outside the safe directory", absPath) + } + info, err := os.Stat(absPath) if err != nil { if os.IsNotExist(err) { return false, nil From 62b55d1ba4d589d5f4ede41d9d6e2c1428766b30 Mon Sep 17 00:00:00 2001 From: Mayank Sachan Date: Mon, 5 May 2025 18:30:32 +0530 Subject: [PATCH 37/39] Dont log credential file name --- cos-csi-mounter/server/rclone.go | 4 ++-- cos-csi-mounter/server/s3fs.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cos-csi-mounter/server/rclone.go b/cos-csi-mounter/server/rclone.go index 90b5ef33..b8b0df89 100644 --- a/cos-csi-mounter/server/rclone.go +++ b/cos-csi-mounter/server/rclone.go @@ -95,8 +95,8 @@ func (args RCloneArgs) Validate(targetPath string) error { // Check if rclone config file exists or not if exists, err := fileExists(args.ConfigPath); err != nil { - logger.Error("error checking rclone config file existence", zap.Error(err)) - return fmt.Errorf("error checking rclone config file existence: %v", err) + logger.Error("error checking rclone config file existence") + return fmt.Errorf("error checking rclone config file existence") } else if !exists { logger.Error("rclone config file not found") return fmt.Errorf("rclone config file not found") diff --git a/cos-csi-mounter/server/s3fs.go b/cos-csi-mounter/server/s3fs.go index b0c8a602..19169d26 100644 --- a/cos-csi-mounter/server/s3fs.go +++ b/cos-csi-mounter/server/s3fs.go @@ -197,8 +197,8 @@ func (args S3FSArgs) Validate(targetPath string) error { // Check if .passwd file exists or not if exists, err := fileExists(args.PasswdFilePath); err != nil { - logger.Error("error checking credential file existence", zap.Error(err)) - return fmt.Errorf("error checking credential file existence: %v", err) + logger.Error("error checking credential file existence") + return fmt.Errorf("error checking credential file existence") } else if !exists { logger.Error("credential file not found") return fmt.Errorf("credential file not found") From 3575d3b07ca7c89180426d8d819856ff8244c019 Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Thu, 15 May 2025 18:47:27 +0530 Subject: [PATCH 38/39] add systemctl reload cmd Signed-off-by: Ashima-Ashima1 --- .secrets.baseline | 2 +- cos-csi-mounter/install/postinst.sh | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.secrets.baseline b/.secrets.baseline index 5f92eae2..90147344 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "go.sum|^.secrets.baseline$", "lines": null }, - "generated_at": "2025-05-07T06:35:25Z", + "generated_at": "2025-05-15T13:16:44Z", "plugins_used": [ { "name": "AWSKeyDetector" diff --git a/cos-csi-mounter/install/postinst.sh b/cos-csi-mounter/install/postinst.sh index fc014a64..fb9ba963 100755 --- a/cos-csi-mounter/install/postinst.sh +++ b/cos-csi-mounter/install/postinst.sh @@ -1,6 +1,9 @@ #!/bin/bash set -e +# Reload systemd unit files +systemctl daemon-reload || true + # Once package is installed this script will called to enable the service systemctl enable cos-csi-mounter.service systemctl start cos-csi-mounter.service From 4e77457bdbbe9941537ceb7cb285c422ac44cb7a Mon Sep 17 00:00:00 2001 From: Ashima-Ashima1 Date: Thu, 15 May 2025 19:02:55 +0530 Subject: [PATCH 39/39] publish dev tag Signed-off-by: Ashima-Ashima1 --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e19d5fc..36bb620a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,8 +57,8 @@ jobs: files: | /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz /home/runner/work/ibm-object-csi-driver/ibm-object-csi-driver/cos-csi-mounter/cos-csi-mounter-latest.tar.gz.sha256 - tag_name: v0.1.0-dev02 - name: v0.1.0-dev02 + tag_name: v0.1.0-dev03 + name: v0.1.0-dev03 body: CSR generated with SHA1 is not supported to get certs using Metadata. prerelease: ${{ env.IS_LATEST_RELEASE != 'true' }}