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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/step_tests-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ jobs:
- name: Lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.5.0
version: v2.7.2
args: --timeout=5m
1 change: 0 additions & 1 deletion cmd/cacct/testflags.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build test
// +build test

package main

Expand Down
1 change: 0 additions & 1 deletion cmd/ceems_api_server/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package main

Expand Down
1 change: 0 additions & 1 deletion cmd/ceems_lb/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package main

Expand Down
8 changes: 2 additions & 6 deletions cmd/redfish_proxy/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,7 @@ func TestNewRedfishProxyServerWithWebConfig(t *testing.T) {

// Make concurrent requests to detect data races
for i := range 20 {
wg.Add(1)

go func() {
defer wg.Done()

wg.Go(func() {
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost:%d/redfish/v1/", p), nil) //nolint:noctx
errs <- err

Expand All @@ -232,7 +228,7 @@ func TestNewRedfishProxyServerWithWebConfig(t *testing.T) {

// Check the body if it has same IP set
assert.Equal(t, strings.Join([]string{remoteIPs[tid]}, ","), string(bodyBytes))
}()
})
}

// Wait for all requests to finish
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

// Boiler plate code to create a new instance of CEEMSServer entrypoint
package main
Expand Down
1 change: 0 additions & 1 deletion examples/mock_updater/cmd/mock_ceems_server/main.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

// Boiler plate code to create a new instance of usageStatsServerApp entrypoint
package main
Expand Down
1 change: 1 addition & 0 deletions internal/common/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ func TestCheckHTTPClientConfigFiles(t *testing.T) {
tmpDir := t.TempDir()

testFiles := make(map[string]string)

for _, n := range []string{
"bearer_token_file",
"auth_credentials_file",
Expand Down
63 changes: 42 additions & 21 deletions internal/security/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ func NewManager(c *Config, logger *slog.Logger) (*Manager, error) {
// we asked for 32 bits while conversion
runAsUserUID := uint32(val)

// Get all group IDs that runAsUser is part of
runAsUserGIDs, err := manager.runAsUser.GroupIds()
if err != nil {
logger.Warn("Failed to get runAsUser groups", "err", err)
}

// Calculate ACL entries for different paths
for _, p := range c.ReadPaths {
if p == "" {
Expand Down Expand Up @@ -116,10 +122,10 @@ func NewManager(c *Config, logger *slog.Logger) (*Manager, error) {
switch mode := fperms.Stat.Mode(); {
case mode.IsDir():
perms = 5
hasPerms = hasReadExecutable(fperms, manager.currentUser, manager.runAsUser)
hasPerms = hasReadExecutable(fperms, manager.currentUser, manager.runAsUser, runAsUserGIDs)
case mode.IsRegular():
perms = 4
hasPerms = hasRead(fperms, manager.currentUser, manager.runAsUser)
hasPerms = hasRead(fperms, manager.currentUser, manager.runAsUser, runAsUserGIDs)
}

// If the path is readable/executable by runAsUser, nothing to do here. Continue
Expand Down Expand Up @@ -159,10 +165,10 @@ func NewManager(c *Config, logger *slog.Logger) (*Manager, error) {
switch mode := fperms.Stat.Mode(); {
case mode.IsDir():
perms = 7
hasPerms = hasReadWriteExecutable(fperms, manager.currentUser, manager.runAsUser)
hasPerms = hasReadWriteExecutable(fperms, manager.currentUser, manager.runAsUser, runAsUserGIDs)
case mode.IsRegular():
perms = 6
hasPerms = hasReadWrite(fperms, manager.currentUser, manager.runAsUser)
hasPerms = hasReadWrite(fperms, manager.currentUser, manager.runAsUser, runAsUserGIDs)
}

// If the path is readable/executable by runAsUser, nothing to do here. Continue
Expand Down Expand Up @@ -419,61 +425,76 @@ func setCapabilities(caps []cap.Value, enableEffective bool) error {
}

// hasRead returns true if runAsUser has r permissions on path.
func hasRead(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User) bool {
func hasRead(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User, runAsUserGIDs []string) bool {
// If current user is runAsUser, check for user permissions
if currentUser.Uid == runAsUser.Uid {
return p.UserReadable()
}

// If not check, check for other permissions
if p.Stat.Mode().Perm()&fileperm.OsOthR != 0 {
return true
// File group owner
pGID := strconv.FormatUint(uint64(p.GID), 10)

// Check if runAsUser GIDs matches with file GID and in that case
// check for group permissions
if slices.Contains(runAsUserGIDs, pGID) {
return p.Stat.Mode().Perm()&fileperm.OsGroupR != 0
}

return false
}

// hasReadExecutable returns true if runAsUser has rx permissions on path.
func hasReadExecutable(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User) bool {
func hasReadExecutable(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User, runAsUserGIDs []string) bool {
// If current user is runAsUser, check for user permissions
if currentUser.Uid == runAsUser.Uid {
return p.UserReadExecutable()
}

// If not check, check for other permissions
if p.Stat.Mode().Perm()&fileperm.OsOthR != 0 && p.Stat.Mode().Perm()&fileperm.OsOthX != 0 {
return true
// File group owner
pGID := strconv.FormatUint(uint64(p.GID), 10)

// Check if runAsUser GIDs matches with file GID and in that case
// check for group permissions
if slices.Contains(runAsUserGIDs, pGID) {
return p.Stat.Mode().Perm()&fileperm.OsGroupR != 0 && p.Stat.Mode().Perm()&fileperm.OsGroupX != 0
}

return false
}

// hasReadWrite returns true if runAsUser has rw permissions on path.
func hasReadWrite(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User) bool {
func hasReadWrite(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User, runAsUserGIDs []string) bool {
// If current user is runAsUser, check for user permissions
if currentUser.Uid == runAsUser.Uid {
return p.UserWriteReadable()
}

// If not check, check for other permissions
if p.Stat.Mode().Perm()&fileperm.OsOthR != 0 && p.Stat.Mode().Perm()&fileperm.OsOthW != 0 {
return true
// File group owner
pGID := strconv.FormatUint(uint64(p.GID), 10)

// Check if runAsUser GIDs matches with file GID and in that case
// check for group permissions
if slices.Contains(runAsUserGIDs, pGID) {
return p.Stat.Mode().Perm()&fileperm.OsGroupR != 0 && p.Stat.Mode().Perm()&fileperm.OsGroupW != 0
}

return false
}

// hasReadWriteExecutable returns true if runAsUser has rwx permissions on path.
func hasReadWriteExecutable(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User) bool {
func hasReadWriteExecutable(p fileperm.PermUser, currentUser *user.User, runAsUser *user.User, runAsUserGIDs []string) bool {
// If current user is runAsUser, check for user permissions
if currentUser.Uid == runAsUser.Uid {
return p.UserWriteReadExecutable()
}

// If not check, check for other permissions
if p.Stat.Mode().Perm()&fileperm.OsOthR != 0 && p.Stat.Mode().Perm()&fileperm.OsOthW != 0 &&
p.Stat.Mode().Perm()&fileperm.OsOthX != 0 {
return true
// File group owner
pGID := strconv.FormatUint(uint64(p.GID), 10)

// Check if runAsUser GIDs matches with file GID and in that case
// check for group permissions
if slices.Contains(runAsUserGIDs, pGID) {
return p.Stat.Mode().Perm()&fileperm.OsGroupR != 0 && p.Stat.Mode().Perm()&fileperm.OsGroupW != 0 && p.Stat.Mode().Perm()&fileperm.OsGroupX != 0
}

return false
Expand Down
2 changes: 2 additions & 0 deletions internal/security/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ func TestNewManager(t *testing.T) {

expectedEntries := []acl{
{path: filepath.Join(tmpDir, "l1", "l2", "l3"), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 5)},
{path: filepath.Join(tmpDir, "l1", "l2"), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 5)},
{path: filepath.Join(tmpDir, "l1"), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 5)},
{path: tmpDir, entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 5)},
{path: filepath.Dir(tmpDir), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 5)},
{path: filepath.Join(tmpDir, "l1", "l2", "l3", "testRead"), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 4)},
{path: filepath.Join(tmpDir, "l1", "l2", "l3", "testWrite"), entry: acls.NewEntry(acls.TAG_ACL_USER, 65534, 6)},
Expand Down
6 changes: 2 additions & 4 deletions internal/structset/structset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ func TestGetStructFieldTagMap(t *testing.T) {
}

func TestCachedFiledIndexes(t *testing.T) {
var value testStruct

indexes := CachedFieldIndexes(reflect.TypeOf(&value).Elem())
indexes := CachedFieldIndexes(reflect.TypeFor[testStruct]())

expected := map[string]int{"f1": 1, "f2": 2, "f3": 3, "f4": 4, "id": 0}
assert.Equal(t, expected, indexes)
Expand All @@ -60,6 +58,6 @@ func TestCachedFiledIndexes(t *testing.T) {
assert.Equal(t, 1, i)

// Now making second request should get value from cache
indexes = CachedFieldIndexes(reflect.TypeOf(&value).Elem())
indexes = CachedFieldIndexes(reflect.TypeFor[testStruct]())
assert.Equal(t, expected, indexes)
}
17 changes: 4 additions & 13 deletions pkg/api/cli/cli.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

// Package cli implements the CLI of the CEEMS API server app
package cli
Expand Down Expand Up @@ -417,11 +416,7 @@ func (b *CEEMSServer) Main() error {
// Initialize tickers. We will stop the ticker immediately after signal has received.
dbUpdateTicker = time.NewTicker(time.Duration(config.Server.Data.UpdateInterval))

wg.Add(1)

go func() {
defer wg.Done()

wg.Go(func() {
for {
// This will ensure that we will run the method as soon as go routine
// starts instead of waiting for ticker to tick.
Expand All @@ -441,18 +436,14 @@ func (b *CEEMSServer) Main() error {
return
}
}
}()
})

// Start backup go routine only backup path is provided in CLI.
if config.Server.Data.BackupPath != "" {
// Initialise ticker and increase waitgroup counter.
dbBackupTicker = time.NewTicker(time.Duration(config.Server.Data.BackupInterval))

wg.Add(1)

go func() {
defer wg.Done()

wg.Go(func() {
for {
select {
case <-dbBackupTicker.C:
Expand All @@ -471,7 +462,7 @@ func (b *CEEMSServer) Main() error {
return
}
}
}()
})
}

// Initializing the server in a goroutine so that
Expand Down
1 change: 0 additions & 1 deletion pkg/api/cli/cli_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package cli

Expand Down
1 change: 0 additions & 1 deletion pkg/api/db/db.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

// Package db creates DB tables, call resource manager interfaces and
// populates the DB with compute units
Expand Down
1 change: 0 additions & 1 deletion pkg/api/db/db_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package db

Expand Down
1 change: 0 additions & 1 deletion pkg/api/db/helpers.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package db

Expand Down
1 change: 0 additions & 1 deletion pkg/api/db/helpers_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package db

Expand Down
4 changes: 2 additions & 2 deletions pkg/api/http/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ func NewCompressor(level int, types ...string) *Compressor {
panic(fmt.Sprintf("middleware/compress: Unsupported content-type wildcard pattern '%s'. Only '/*' supported", t))
}

if strings.HasSuffix(t, "/*") {
allowedWildcards[strings.TrimSuffix(t, "/*")] = struct{}{}
if before, ok := strings.CutSuffix(t, "/*"); ok {
allowedWildcards[before] = struct{}{}
} else {
allowedTypes[t] = struct{}{}
}
Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/error.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/error_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/middleware.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/middleware_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
2 changes: 1 addition & 1 deletion pkg/api/http/querier.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func scanRows[T any](rows *sql.Rows, numRows int) ([]T, error) {
rowIdx := 0

// Get indexes
indexes := structset.CachedFieldIndexes(reflect.TypeOf(&value).Elem())
indexes := structset.CachedFieldIndexes(reflect.TypeFor[T]())

// Get columns
columns, err = rows.Columns()
Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/querier_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/server.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

// Package http implements the HTTP server handlers for different resource endpoints
package http
Expand Down
1 change: 0 additions & 1 deletion pkg/api/http/server_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build cgo
// +build cgo

package http

Expand Down
4 changes: 2 additions & 2 deletions pkg/api/resource/openstack/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,10 @@ type PowerState int
const (
NOSTATE = iota
RUNNING
_UNUSED1 //nolint:stylecheck
_UNUSED1
PAUSED
SHUTDOWN
_UNUSED2 //nolint:stylecheck
_UNUSED2
CRASHED
SUSPENDED
)
Expand Down
1 change: 0 additions & 1 deletion pkg/collector/cgroup_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !noslurm
// +build !noslurm

package collector

Expand Down
1 change: 0 additions & 1 deletion pkg/collector/cpu.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build !nocpu
// +build !nocpu

package collector

Expand Down
Loading