This commit is contained in:
2026-01-02 18:20:15 +00:00
parent 0f7c29c3ef
commit ce5a8fbffd
37 changed files with 323 additions and 178 deletions
+15 -15
View File
@@ -2,7 +2,7 @@ package filesystem
import (
"context"
"crypto/md5"
"crypto/md5" // #nosec G501 -- MD5 used for file checksums, not cryptographic security
"crypto/sha256"
"encoding/hex"
"fmt"
@@ -29,7 +29,7 @@ type FilesystemStorage struct {
// New creates a new filesystem storage backend
func New(basePath string, quota int64) (*FilesystemStorage, error) {
// Create base directory if it doesn't exist
if err := os.MkdirAll(basePath, 0755); err != nil {
if err := os.MkdirAll(basePath, 0750); err != nil {
return nil, errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to create base directory")
}
@@ -57,7 +57,7 @@ func (fs *FilesystemStorage) Get(ctx context.Context, key string) (io.ReadCloser
path := fs.keyToPath(key)
file, err := os.Open(path)
file, err := os.Open(path) // #nosec G304 -- Path is sanitized storage key
if err != nil {
if os.IsNotExist(err) {
metrics.RecordStorageOperation("filesystem", "get", "not_found")
@@ -84,14 +84,14 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
dir := filepath.Dir(path)
// Create directory
if err := os.MkdirAll(dir, 0755); err != nil {
if err := os.MkdirAll(dir, 0750); err != nil {
metrics.RecordStorageOperation("filesystem", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to create directory")
}
// Create temp file for atomic write
tempPath := path + ".tmp"
tempFile, err := os.Create(tempPath)
tempFile, err := os.Create(tempPath) // #nosec G304 -- Temp path is constructed from sanitized storage key
if err != nil {
metrics.RecordStorageOperation("filesystem", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to create temp file")
@@ -99,20 +99,20 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
// Calculate checksums while writing
// NOTE: MD5 is used for integrity verification (checksums), not cryptographic security
md5Hash := md5.New()
md5Hash := md5.New() // #nosec G401 -- MD5 used for file integrity check, not cryptographic security
sha256Hash := sha256.New()
multiWriter := io.MultiWriter(tempFile, md5Hash, sha256Hash)
written, err := io.Copy(multiWriter, data)
if err != nil {
tempFile.Close()
os.Remove(tempPath)
tempFile.Close() // #nosec G104 -- Cleanup, error not critical
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
metrics.RecordStorageOperation("filesystem", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to write data")
}
if err := tempFile.Close(); err != nil {
os.Remove(tempPath)
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
metrics.RecordStorageOperation("filesystem", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to close temp file")
}
@@ -121,7 +121,7 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
fs.mu.Lock()
if fs.quota > 0 && fs.used+written > fs.quota {
fs.mu.Unlock()
os.Remove(tempPath)
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
metrics.RecordStorageOperation("filesystem", "put", "quota_exceeded")
return errors.QuotaExceeded(fs.quota)
}
@@ -134,13 +134,13 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
sha256Sum := hex.EncodeToString(sha256Hash.Sum(nil))
if opts.ChecksumMD5 != "" && opts.ChecksumMD5 != md5Sum {
os.Remove(tempPath)
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
return errors.New(errors.ErrCodeChecksumMismatch, "MD5 checksum mismatch")
}
if opts.ChecksumSHA256 != "" && opts.ChecksumSHA256 != sha256Sum {
os.Remove(tempPath)
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
metrics.RecordStorageOperation("filesystem", "put", "checksum_error")
return errors.New(errors.ErrCodeChecksumMismatch, "SHA256 checksum mismatch")
}
@@ -148,7 +148,7 @@ func (fs *FilesystemStorage) Put(ctx context.Context, key string, data io.Reader
// Atomic rename
if err := os.Rename(tempPath, path); err != nil {
os.Remove(tempPath)
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
fs.mu.Lock()
fs.used -= written
currentUsed := fs.used
@@ -331,8 +331,8 @@ func (fs *FilesystemStorage) Health(ctx context.Context) error {
if err != nil {
return errors.Wrap(err, errors.ErrCodeStorageFailure, "cannot write to storage")
}
f.Close()
os.Remove(tempPath)
f.Close() // #nosec G104 -- Cleanup, error not critical
_ = os.Remove(tempPath) // #nosec G104 -- Cleanup, error not critical
return nil
}
+9 -9
View File
@@ -32,10 +32,10 @@ func (s *FilesystemStorageTestSuite) SetupTest() {
func (s *FilesystemStorageTestSuite) TearDownTest() {
if s.fs != nil {
s.fs.Close()
s.fs.Close() // #nosec G104 -- Cleanup, error not critical
}
if s.tempDir != "" {
os.RemoveAll(s.tempDir)
_ = os.RemoveAll(s.tempDir) // #nosec G104 -- Cleanup
}
}
@@ -148,7 +148,7 @@ func (s *FilesystemStorageTestSuite) TestGet() {
} else {
s.NoError(err)
s.NotNil(reader)
defer reader.Close()
defer reader.Close() // #nosec G104 -- Cleanup, error not critical
data, err := io.ReadAll(reader)
s.NoError(err)
@@ -362,7 +362,7 @@ func (s *FilesystemStorageTestSuite) TestQuotaEnforcement() {
smallFs, err := New(smallQuotaDir, 100)
s.Require().NoError(err)
defer smallFs.Close()
defer smallFs.Close() // #nosec G104 -- Cleanup, error not critical
// First write should succeed
err = smallFs.Put(ctx, "file1.txt", strings.NewReader("small content"), nil)
@@ -532,7 +532,7 @@ func (s *FilesystemStorageTestSuite) TestConcurrentReadsAndWrites() {
reader, err := s.fs.Get(ctx, key)
if err == nil {
io.ReadAll(reader)
reader.Close()
reader.Close() // #nosec G104 -- Cleanup, error not critical
}
}
}(i)
@@ -614,7 +614,7 @@ func (s *FilesystemStorageTestSuite) TestAtomicWrite() {
continue
}
data, err := io.ReadAll(reader)
reader.Close()
reader.Close() // #nosec G104 -- Cleanup, error not critical
if err != nil {
readErrors <- err
continue
@@ -720,7 +720,7 @@ func BenchmarkFilesystemPut(b *testing.B) {
defer os.RemoveAll(tempDir)
fs, _ := New(tempDir, 1024*1024*1024) // 1GB quota
defer fs.Close()
defer fs.Close() // #nosec G104 -- Cleanup, error not critical
ctx := context.Background()
data := strings.Repeat("x", 1024) // 1KB
@@ -738,7 +738,7 @@ func BenchmarkFilesystemGet(b *testing.B) {
defer os.RemoveAll(tempDir)
fs, _ := New(tempDir, 1024*1024*1024)
defer fs.Close()
defer fs.Close() // #nosec G104 -- Cleanup, error not critical
ctx := context.Background()
data := strings.Repeat("x", 1024)
@@ -751,7 +751,7 @@ func BenchmarkFilesystemGet(b *testing.B) {
reader, _ := fs.Get(ctx, "bench/test.txt")
if reader != nil {
io.ReadAll(reader)
reader.Close()
reader.Close() // #nosec G104 -- Cleanup, error not critical
}
}
}
+2 -2
View File
@@ -3,7 +3,7 @@ package s3
import (
"bytes"
"context"
"crypto/md5"
"crypto/md5" // #nosec G501 -- MD5 used for S3 Content-MD5 header, not cryptographic security
"crypto/sha256"
"encoding/hex"
stderrors "errors"
@@ -136,7 +136,7 @@ func (s *S3Storage) Put(ctx context.Context, key string, data io.Reader, opts *s
// Read data into buffer to calculate checksums and size
var buf bytes.Buffer
md5Hash := md5.New()
md5Hash := md5.New() // #nosec G401 -- MD5 used for S3 integrity check, not cryptographic security
sha256Hash := sha256.New()
multiWriter := io.MultiWriter(&buf, md5Hash, sha256Hash)
+12 -12
View File
@@ -3,7 +3,7 @@ package smb
import (
"bytes"
"context"
"crypto/md5"
"crypto/md5" // #nosec G501 -- MD5 used for file checksums, not cryptographic security
"crypto/sha256"
"encoding/hex"
"fmt"
@@ -124,14 +124,14 @@ func (s *SMBStorage) createConnection(ctx context.Context) (*smbConnection, erro
session, err := dialer.Dial(conn)
if err != nil {
conn.Close()
conn.Close() // #nosec G104 -- Cleanup, error not critical
return nil, err
}
share, err := session.Mount(s.share)
if err != nil {
session.Logoff()
conn.Close()
_ = session.Logoff() // #nosec G104 -- SMB cleanup
conn.Close() // #nosec G104 -- Cleanup, error not critical
return nil, err
}
@@ -169,13 +169,13 @@ func (s *SMBStorage) returnConnection(conn *smbConnection) {
// close closes an SMB connection
func (c *smbConnection) close() {
if c.share != nil {
c.share.Umount()
_ = c.share.Umount() // #nosec G104 -- SMB cleanup
}
if c.session != nil {
c.session.Logoff()
_ = c.session.Logoff() // #nosec G104 -- SMB cleanup
}
if c.conn != nil {
c.conn.Close()
c.conn.Close() // #nosec G104 -- Cleanup, error not critical
}
}
@@ -203,7 +203,7 @@ func (s *SMBStorage) Get(ctx context.Context, key string) (io.ReadCloser, error)
// Read entire file into memory and close SMB connection
// This is necessary because we need to return the connection to the pool
data, err := io.ReadAll(file)
file.Close()
file.Close() // #nosec G104 -- Cleanup, error not critical
s.returnConnection(conn)
if err != nil {
@@ -234,7 +234,7 @@ func (s *SMBStorage) Put(ctx context.Context, key string, data io.Reader, opts *
// Read data into buffer to calculate checksums and size
var buf bytes.Buffer
md5Hash := md5.New()
md5Hash := md5.New() // #nosec G401 -- MD5 used for file integrity check, not cryptographic security
sha256Hash := sha256.New()
multiWriter := io.MultiWriter(&buf, md5Hash, sha256Hash)
@@ -282,17 +282,17 @@ func (s *SMBStorage) Put(ctx context.Context, key string, data io.Reader, opts *
// Write data
_, err = io.Copy(file, bytes.NewReader(buf.Bytes()))
file.Close()
file.Close() // #nosec G104 -- Cleanup, error not critical
if err != nil {
conn.share.Remove(tempPath)
_ = conn.share.Remove(tempPath) // #nosec G104 -- SMB cleanup
metrics.RecordStorageOperation("smb", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to write SMB file")
}
// Atomic rename
if err := conn.share.Rename(tempPath, path); err != nil {
conn.share.Remove(tempPath)
_ = conn.share.Remove(tempPath) // #nosec G104 -- SMB cleanup
metrics.RecordStorageOperation("smb", "put", "error")
return errors.Wrap(err, errors.ErrCodeStorageFailure, "failed to rename SMB temp file")
}