diff --git a/api/.golangci.yaml b/api/.golangci.yaml index 5b885de19..e5e5bc6a1 100644 --- a/api/.golangci.yaml +++ b/api/.golangci.yaml @@ -8,6 +8,8 @@ linters: - govet - errorlint - exportloopref + - staticcheck + linters-settings: depguard: rules: diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index 1b865581d..cfb204509 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -3,11 +3,9 @@ package main import ( "context" "crypto/sha256" - "math/rand" "os" "path" "strings" - "time" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/apikey" @@ -455,6 +453,9 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server { dockerClientFactory := initDockerClientFactory(digitalSignatureService, reverseTunnelService) kubernetesClientFactory, err := initKubernetesClientFactory(digitalSignatureService, reverseTunnelService, dataStore, instanceID, *flags.AddrHTTPS, settings.UserSessionTimeout) + if err != nil { + log.Fatal().Err(err).Msg("failed initializing kubernetes client factory") + } authorizationService := authorization.NewService(dataStore) authorizationService.K8sClientFactory = kubernetesClientFactory @@ -631,8 +632,6 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server { } func main() { - rand.Seed(time.Now().UnixNano()) - configureLogger() setLoggingMode("PRETTY") diff --git a/api/datastore/migrator/migrate_dbversion20.go b/api/datastore/migrator/migrate_dbversion20.go index 1f02b8885..24dbfd0db 100644 --- a/api/datastore/migrator/migrate_dbversion20.go +++ b/api/datastore/migrator/migrate_dbversion20.go @@ -56,6 +56,9 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error { endpointAdministratorRole.Authorizations = authorization.DefaultEndpointAuthorizationsForEndpointAdministratorRole() err = m.roleService.Update(endpointAdministratorRole.ID, endpointAdministratorRole) + if err != nil { + return err + } helpDeskRole, err := m.roleService.Read(portainer.RoleID(2)) if err != nil { @@ -65,6 +68,9 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error { helpDeskRole.Authorizations = authorization.DefaultEndpointAuthorizationsForHelpDeskRole(settings.AllowVolumeBrowserForRegularUsers) err = m.roleService.Update(helpDeskRole.ID, helpDeskRole) + if err != nil { + return err + } standardUserRole, err := m.roleService.Read(portainer.RoleID(3)) if err != nil { @@ -74,6 +80,9 @@ func (m *Migrator) updateUsersAndRolesToDBVersion22() error { standardUserRole.Authorizations = authorization.DefaultEndpointAuthorizationsForStandardUserRole(settings.AllowVolumeBrowserForRegularUsers) err = m.roleService.Update(standardUserRole.ID, standardUserRole) + if err != nil { + return err + } readOnlyUserRole, err := m.roleService.Read(portainer.RoleID(4)) if err != nil { diff --git a/api/git/git_test.go b/api/git/git_test.go index 1a824e7f7..7a28121f2 100644 --- a/api/git/git_test.go +++ b/api/git/git_test.go @@ -41,7 +41,7 @@ func Test_ClonePublicRepository_Shallow(t *testing.T) { t.Logf("Cloning into %s", dir) err := service.CloneRepository(dir, repositoryURL, referenceName, "", "", false) assert.NoError(t, err) - assert.Equal(t, 1, getCommitHistoryLength(t, err, dir), "cloned repo has incorrect depth") + assert.Equal(t, 1, getCommitHistoryLength(t, dir), "cloned repo has incorrect depth") } func Test_ClonePublicRepository_NoGitDirectory(t *testing.T) { @@ -76,7 +76,7 @@ func Test_cloneRepository(t *testing.T) { }) assert.NoError(t, err) - assert.Equal(t, 4, getCommitHistoryLength(t, err, dir), "cloned repo has incorrect depth") + assert.Equal(t, 4, getCommitHistoryLength(t, dir), "cloned repo has incorrect depth") } func Test_latestCommitID(t *testing.T) { @@ -91,7 +91,7 @@ func Test_latestCommitID(t *testing.T) { assert.Equal(t, "68dcaa7bd452494043c64252ab90db0f98ecf8d2", id) } -func getCommitHistoryLength(t *testing.T, err error, dir string) int { +func getCommitHistoryLength(t *testing.T, dir string) int { repo, err := git.PlainOpen(dir) if err != nil { t.Fatalf("can't open a git repo at %s with error %v", dir, err) diff --git a/api/http/handler/auth/authenticate.go b/api/http/handler/auth/authenticate.go index 0098e00b1..e25358955 100644 --- a/api/http/handler/auth/authenticate.go +++ b/api/http/handler/auth/authenticate.go @@ -200,7 +200,7 @@ func (handler *Handler) syncUserTeamsWithLDAPGroups(user *portainer.User, settin func teamExists(teamName string, ldapGroups []string) bool { for _, group := range ldapGroups { - if strings.ToLower(group) == strings.ToLower(teamName) { + if strings.EqualFold(group, teamName) { return true } } diff --git a/api/http/middlewares/endpoint.go b/api/http/middlewares/endpoint.go index ca9d3fbf8..ab733d4f9 100644 --- a/api/http/middlewares/endpoint.go +++ b/api/http/middlewares/endpoint.go @@ -13,7 +13,11 @@ import ( "github.com/gorilla/mux" ) -const contextEndpoint = "endpoint" +// Note: context keys must be distinct types to prevent collisions. They are NOT key/value map's internally +// See: https://go.dev/blog/context#TOC_3.2. +type key int + +const contextEndpoint key = 0 func WithEndpoint(endpointService dataservices.EndpointService, endpointIDParam string) mux.MiddlewareFunc { return func(next http.Handler) http.Handler { diff --git a/api/http/security/bouncer_test.go b/api/http/security/bouncer_test.go index 20220e588..126a6c6f8 100644 --- a/api/http/security/bouncer_test.go +++ b/api/http/security/bouncer_test.go @@ -344,6 +344,7 @@ func Test_apiKeyLookup(t *testing.T) { req.Header.Add("x-api-key", rawAPIKey) token, err := bouncer.apiKeyLookup(req) + is.NoError(err) expectedToken := &portainer.TokenData{ID: user.ID, Username: user.Username, Role: portainer.StandardUserRole} is.Equal(expectedToken, token) @@ -358,6 +359,7 @@ func Test_apiKeyLookup(t *testing.T) { req.Header.Add("x-api-key", rawAPIKey) token, err := bouncer.apiKeyLookup(req) + is.NoError(err) expectedToken := &portainer.TokenData{ID: user.ID, Username: user.Username, Role: portainer.StandardUserRole} is.Equal(expectedToken, token) @@ -372,6 +374,7 @@ func Test_apiKeyLookup(t *testing.T) { req.Header.Add("x-api-key", rawAPIKey) token, err := bouncer.apiKeyLookup(req) + is.NoError(err) expectedToken := &portainer.TokenData{ID: user.ID, Username: user.Username, Role: portainer.StandardUserRole} is.Equal(expectedToken, token) diff --git a/api/kubernetes/cli/client.go b/api/kubernetes/cli/client.go index cf6993097..8a3d42233 100644 --- a/api/kubernetes/cli/client.go +++ b/api/kubernetes/cli/client.go @@ -242,6 +242,10 @@ func (factory *ClientFactory) buildEdgeConfig(endpoint *portainer.Endpoint) (*re } signature, err := factory.signatureService.CreateSignature(portainer.PortainerAgentSignatureMessage) + if err != nil { + return nil, err + } + config.Insecure = true config.QPS = DefaultKubeClientQPS config.Burst = DefaultKubeClientBurst @@ -257,32 +261,6 @@ func (factory *ClientFactory) buildEdgeConfig(endpoint *portainer.Endpoint) (*re return config, nil } -func (factory *ClientFactory) createRemoteClient(endpointURL string) (*kubernetes.Clientset, error) { - signature, err := factory.signatureService.CreateSignature(portainer.PortainerAgentSignatureMessage) - if err != nil { - return nil, err - } - - config, err := clientcmd.BuildConfigFromFlags(endpointURL, "") - if err != nil { - return nil, err - } - - config.Insecure = true - config.QPS = DefaultKubeClientQPS - config.Burst = DefaultKubeClientBurst - - config.Wrap(func(rt http.RoundTripper) http.RoundTripper { - return &agentHeaderRoundTripper{ - signatureHeader: signature, - publicKeyHeader: factory.signatureService.EncodedPublicKey(), - roundTripper: rt, - } - }) - - return kubernetes.NewForConfig(config) -} - func (factory *ClientFactory) CreateRemoteMetricsClient(endpoint *portainer.Endpoint) (*metricsv.Clientset, error) { config, err := factory.CreateConfig(endpoint) if err != nil { diff --git a/api/stacks/deployments/deployer_remote.go b/api/stacks/deployments/deployer_remote.go index 33bec796e..69a54e7ba 100644 --- a/api/stacks/deployments/deployer_remote.go +++ b/api/stacks/deployments/deployer_remote.go @@ -198,7 +198,6 @@ func (d *stackDeployer) remoteStack(stack *portainer.Stack, endpoint *portainer. Str("cmd", strings.Join(cmd, " ")). Msg("running unpacker") - rand.Seed(time.Now().UnixNano()) unpackerContainer, err := cli.ContainerCreate(ctx, &container.Config{ Image: image, Cmd: cmd,