diff --git a/.golangci.yml b/.golangci.yml index cfb64a75bfd21900b81d5682ead8831177c40bf8..8d602489e8e5bfaba199d755d36ec5c40d51763b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -19,7 +19,6 @@ linters: disable-all: true enable: - bodyclose - - deadcode - depguard - dogsled - exhaustive @@ -42,17 +41,15 @@ linters: - rowserrcheck - sqlclosecheck - staticcheck - - structcheck - stylecheck - tparallel - unconvert - unparam - unused - - varcheck - whitespace # Disable temporarily until everything works with Go 1.18 - # - typecheck + - typecheck # TODO: fix linter errors before enabling # - exhaustivestruct diff --git a/Makefile b/Makefile index 9c55ad2b11b25397da6188480fd2d724deb4cf34..0f1453bf497c29f03dac04aa35085bdb03db07c1 100644 --- a/Makefile +++ b/Makefile @@ -117,7 +117,7 @@ proto-internal: @protoc --go_out=paths=source_relative:. server/internal/*.proto # Dependency versions -GOLANGCI_VERSION = 1.46.0 +GOLANGCI_VERSION = 1.50.1 GOTESTSUM_VERSION ?= 1.7.0 PROTOC_VERSION = 3.15.6 PROTOC_GEN_GO_VERSION = 1.26.0 diff --git a/connector/atlassiancrowd/atlassiancrowd.go b/connector/atlassiancrowd/atlassiancrowd.go index e2ca94b0de9aa6fcef008d6b045fcd76c51bf0ff..aa142203415cde3cdf6a8eeb82715997cf365313 100644 --- a/connector/atlassiancrowd/atlassiancrowd.go +++ b/connector/atlassiancrowd/atlassiancrowd.go @@ -24,18 +24,17 @@ import ( // // An example config: // -// type: atlassian-crowd -// config: -// baseURL: https://crowd.example.com/context -// clientID: applogin -// clientSecret: appP4$$w0rd -// # users can be restricted by a list of groups -// groups: -// - admin -// # Prompt for username field -// usernamePrompt: Login -// preferredUsernameField: name -// +// type: atlassian-crowd +// config: +// baseURL: https://crowd.example.com/context +// clientID: applogin +// clientSecret: appP4$$w0rd +// # users can be restricted by a list of groups +// groups: +// - admin +// # Prompt for username field +// usernamePrompt: Login +// preferredUsernameField: name type Config struct { BaseURL string `json:"baseURL"` ClientID string `json:"clientID"` diff --git a/connector/connector.go b/connector/connector.go index aab994b4682a7529cee369a5ef04f4ba042777cb..e4cf58c0ae6e741fdf3807b42032284dc1c990c6 100644 --- a/connector/connector.go +++ b/connector/connector.go @@ -70,7 +70,8 @@ type CallbackConnector interface { } // SAMLConnector represents SAML connectors which implement the HTTP POST binding. -// RelayState is handled by the server. +// +// RelayState is handled by the server. // // See: https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf // "3.5 HTTP POST Binding" diff --git a/connector/google/google_test.go b/connector/google/google_test.go index 83c4cba1a02c4c7fe6e71a63c021b88d506b5671..cf5977ab6a85b9bc0007418159bb10f16ad292ca 100644 --- a/connector/google/google_test.go +++ b/connector/google/google_test.go @@ -31,7 +31,7 @@ var ( callCounter = make(map[string]int) ) -func testSetup(t *testing.T) *httptest.Server { +func testSetup() *httptest.Server { mux := http.NewServeMux() mux.HandleFunc("/admin/directory/v1/groups/", func(w http.ResponseWriter, r *http.Request) { @@ -46,7 +46,7 @@ func testSetup(t *testing.T) *httptest.Server { return httptest.NewServer(mux) } -func newConnector(config *Config, serverURL string) (*googleConnector, error) { +func newConnector(config *Config) (*googleConnector, error) { log := logrus.New() conn, err := config.Open("id", log) if err != nil { @@ -78,7 +78,7 @@ func tempServiceAccountKey() (string, error) { } func TestOpen(t *testing.T) { - ts := testSetup(t) + ts := testSetup() defer ts.Close() type testCase struct { @@ -155,7 +155,7 @@ func TestOpen(t *testing.T) { assert := assert.New(t) os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", reference.adc) - conn, err := newConnector(reference.config, ts.URL) + conn, err := newConnector(reference.config) if reference.expectedErr == "" { assert.Nil(err) @@ -168,7 +168,7 @@ func TestOpen(t *testing.T) { } func TestGetGroups(t *testing.T) { - ts := testSetup(t) + ts := testSetup() defer ts.Close() serviceAccountFilePath, err := tempServiceAccountKey() @@ -181,7 +181,7 @@ func TestGetGroups(t *testing.T) { RedirectURI: ts.URL + "/callback", Scopes: []string{"openid", "groups"}, AdminEmail: "admin@dexidp.com", - }, ts.URL) + }) assert.Nil(t, err) conn.adminSrv, err = admin.NewService(context.Background(), option.WithoutAuthentication(), option.WithEndpoint(ts.URL)) diff --git a/connector/microsoft/microsoft.go b/connector/microsoft/microsoft.go index 3952c94be631a72d05f22178dcebb9d237b7745e..719b92de66b8177a8d7b74d022b1ed7e2eeef396 100644 --- a/connector/microsoft/microsoft.go +++ b/connector/microsoft/microsoft.go @@ -316,22 +316,27 @@ func (c *microsoftConnector) Refresh(ctx context.Context, s connector.Scopes, id // https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/user // id - The unique identifier for the user. Inherited from -// directoryObject. Key. Not nullable. Read-only. +// +// directoryObject. Key. Not nullable. Read-only. +// // displayName - The name displayed in the address book for the user. -// This is usually the combination of the user's first name, -// middle initial and last name. This property is required -// when a user is created and it cannot be cleared during -// updates. Supports $filter and $orderby. +// +// This is usually the combination of the user's first name, +// middle initial and last name. This property is required +// when a user is created and it cannot be cleared during +// updates. Supports $filter and $orderby. +// // userPrincipalName - The user principal name (UPN) of the user. -// The UPN is an Internet-style login name for the user -// based on the Internet standard RFC 822. By convention, -// this should map to the user's email name. The general -// format is alias@domain, where domain must be present in -// the tenant’s collection of verified domains. This -// property is required when a user is created. The -// verified domains for the tenant can be accessed from the -// verifiedDomains property of organization. Supports -// $filter and $orderby. +// +// The UPN is an Internet-style login name for the user +// based on the Internet standard RFC 822. By convention, +// this should map to the user's email name. The general +// format is alias@domain, where domain must be present in +// the tenant’s collection of verified domains. This +// property is required when a user is created. The +// verified domains for the tenant can be accessed from the +// verifiedDomains property of organization. Supports +// $filter and $orderby. type user struct { ID string `json:"id"` Name string `json:"displayName"` @@ -364,8 +369,9 @@ func (c *microsoftConnector) user(ctx context.Context, client *http.Client) (u u // https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/resources/group // displayName - The display name for the group. This property is required when -// a group is created and it cannot be cleared during updates. -// Supports $filter and $orderby. +// +// a group is created and it cannot be cleared during updates. +// Supports $filter and $orderby. type group struct { Name string `json:"displayName"` } diff --git a/connector/saml/saml.go b/connector/saml/saml.go index 908ec703c9753a39a51e924ac407acbbc63d253c..06712db6ec70eb8bc42dda66cdb3d9fe11000807 100644 --- a/connector/saml/saml.go +++ b/connector/saml/saml.go @@ -24,7 +24,7 @@ import ( "github.com/dexidp/dex/pkg/log" ) -// nolint +//nolint const ( bindingRedirect = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" bindingPOST = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" @@ -292,7 +292,6 @@ func (p *provider) POSTData(s connector.Scopes, id string) (action, value string // * Verify signature on XML document (or verify sig on assertion elements). // * Verify various parts of the Assertion element. Conditions, audience, etc. // * Map the Assertion's attribute elements to user info. -// func (p *provider) HandlePOST(s connector.Scopes, samlResponse, inResponseTo string) (ident connector.Identity, err error) { rawResp, err := base64.StdEncoding.DecodeString(samlResponse) if err != nil { diff --git a/connector/saml/saml_test.go b/connector/saml/saml_test.go index 95d513ed19db27f1853c622adc963c2b09fe8e44..68c0cb1a93d7b0062255c752d0404cff0c572c25 100644 --- a/connector/saml/saml_test.go +++ b/connector/saml/saml_test.go @@ -24,19 +24,18 @@ import ( // To add a new test, define a new, unsigned SAML 2.0 response that exercises some // case, then sign it using the "testdata/gen.sh" script. // -// cp testdata/good-resp.tmpl testdata/( testname ).tmpl -// vim ( testname ).tmpl # Modify your template for your test case. -// vim testdata/gen.sh # Add a xmlsec1 command to the generation script. -// ./testdata/gen.sh # Sign your template. +// cp testdata/good-resp.tmpl testdata/( testname ).tmpl +// vim ( testname ).tmpl # Modify your template for your test case. +// vim testdata/gen.sh # Add a xmlsec1 command to the generation script. +// ./testdata/gen.sh # Sign your template. // // To install xmlsec1 on Fedora run: // -// sudo dnf install xmlsec1 xmlsec1-openssl +// sudo dnf install xmlsec1 xmlsec1-openssl // // On mac: // -// brew install Libxmlsec1 -// +// brew install Libxmlsec1 type responseTest struct { // CA file and XML file of the response. caFile string diff --git a/server/oauth2.go b/server/oauth2.go index 67223fa1c0d30c5251a42b7739b18b8dfdb923d0..bb0058a74a9728ec532c915d67eabdbe8ab4517f 100644 --- a/server/oauth2.go +++ b/server/oauth2.go @@ -93,7 +93,7 @@ func tokenErr(w http.ResponseWriter, typ, description string, statusCode int) er return nil } -// nolint +//nolint const ( errInvalidRequest = "invalid_request" errUnauthorizedClient = "unauthorized_client" @@ -211,9 +211,9 @@ func signPayload(key *jose.JSONWebKey, alg jose.SignatureAlgorithm, payload []by // The hash algorithm for the at_hash is determined by the signing // algorithm used for the id_token. From the spec: // -// ...the hash algorithm used is the hash algorithm used in the alg Header -// Parameter of the ID Token's JOSE Header. For instance, if the alg is RS256, -// hash the access_token value with SHA-256 +// ...the hash algorithm used is the hash algorithm used in the alg Header +// Parameter of the ID Token's JOSE Header. For instance, if the alg is RS256, +// hash the access_token value with SHA-256 // // https://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDToken var hashForSigAlg = map[jose.SignatureAlgorithm]func() hash.Hash{ diff --git a/server/templates.go b/server/templates.go index 33f00fda3649e10852d8089f97f9edfd8332808e..245378918fd96d2a785d9365cdff37222e601fe4 100644 --- a/server/templates.go +++ b/server/templates.go @@ -83,12 +83,11 @@ func getFuncMap(c webConfig) (template.FuncMap, error) { // // The directory layout is expected to be: // -// ( web directory ) -// |- static -// |- themes -// | |- (theme name) -// |- templates -// +// ( web directory ) +// |- static +// |- themes +// | |- (theme name) +// |- templates func loadWebConfig(c webConfig) (http.Handler, http.Handler, *templates, error) { // fallback to the default theme if the legacy theme name is provided if c.theme == "coreos" || c.theme == "tectonic" { diff --git a/storage/ent/postgres.go b/storage/ent/postgres.go index 1953f5992fbf6a8dc4b849b7c8e293adaa9b6dc0..ac091e702cf51d1b38eb6410172958ee7382d63e 100644 --- a/storage/ent/postgres.go +++ b/storage/ent/postgres.go @@ -20,7 +20,7 @@ import ( "github.com/dexidp/dex/storage/ent/db" ) -// nolint +//nolint const ( // postgres SSL modes pgSSLDisable = "disable" diff --git a/storage/kubernetes/client.go b/storage/kubernetes/client.go index 1e4e75d8695d3e25f9f23c860e45629cb105de87..e99c069027a400058ddcd13b65c3bb2c444c7308 100644 --- a/storage/kubernetes/client.go +++ b/storage/kubernetes/client.go @@ -211,7 +211,7 @@ func (cli *client) getResource(apiVersion, namespace, resource, name string, v i return cli.getURL(u, v) } -func (cli *client) listN(resource string, v interface{}, n int) error { +func (cli *client) listN(resource string, v interface{}, n int) error { //nolint:unparam // In practice, n is the gcResultLimit constant. params := url.Values{} params.Add("limit", fmt.Sprintf("%d", n)) u, err := cli.urlForWithParams(cli.apiVersion, cli.namespace, resource, "", params) diff --git a/storage/kubernetes/lock.go b/storage/kubernetes/lock.go index 798c1f161facfcf07a599a2739b9676343df6851..12075e81db6f1dcb4859bb421350770ccc6fc319 100644 --- a/storage/kubernetes/lock.go +++ b/storage/kubernetes/lock.go @@ -19,9 +19,9 @@ var ( // // Refresh token contains data to refresh identity in external authentication system. // There is a requirement that refresh should be called only once because of several reasons: -// * Some of OIDC providers could use the refresh token rotation feature which requires calling refresh only once. -// * Providers can limit the rate of requests to the token endpoint, which will lead to the error -// in case of many concurrent requests. +// - Some of OIDC providers could use the refresh token rotation feature which requires calling refresh only once. +// - Providers can limit the rate of requests to the token endpoint, which will lead to the error +// in case of many concurrent requests. type refreshTokenLock struct { cli *client waitingState bool diff --git a/storage/kubernetes/transport.go b/storage/kubernetes/transport.go index 5d39c27fba3151fbb8627c44c9a3d1b7f3188673..9c3cd2baac268bcbb5043000bc495dada7a922d5 100644 --- a/storage/kubernetes/transport.go +++ b/storage/kubernetes/transport.go @@ -62,15 +62,17 @@ func wrapRoundTripper(base http.RoundTripper, user k8sapi.AuthInfo, inCluster bo } // renewTokenPeriod is the interval after which dex will read the token from a well-known file. -// By Kubernetes documentation, this interval should be at least one minute long. -// Kubernetes client-go v0.15+ uses 10 seconds long interval. -// Dex uses the reasonable value between these two. +// +// By Kubernetes documentation, this interval should be at least one minute long. +// Kubernetes client-go v0.15+ uses 10 seconds long interval. +// Dex uses the reasonable value between these two. const renewTokenPeriod = 30 * time.Second // inClusterTransportHelper is capable of safely updating the user token. -// BoundServiceAccountTokenVolume feature is enabled in Kubernetes >=1.21 by default. -// With this feature, the service account token in the pod becomes periodically updated. -// Therefore, Dex needs to re-read the token from the disk after some time to be sure that it uses the valid token. +// +// BoundServiceAccountTokenVolume feature is enabled in Kubernetes >=1.21 by default. +// With this feature, the service account token in the pod becomes periodically updated. +// Therefore, Dex needs to re-read the token from the disk after some time to be sure that it uses the valid token. type inClusterTransportHelper struct { mu sync.RWMutex info k8sapi.AuthInfo diff --git a/storage/sql/config.go b/storage/sql/config.go index 1aedf04cae7ff84a40d7bf11fb6234a452e023a9..8b782425631db56bc938a820411b2d03376c9be2 100644 --- a/storage/sql/config.go +++ b/storage/sql/config.go @@ -31,7 +31,7 @@ const ( mysqlErrUnknownSysVar = 1193 ) -// nolint +//nolint const ( // postgres SSL modes pgSSLDisable = "disable" @@ -40,7 +40,7 @@ const ( pgSSLVerifyFull = "verify-full" ) -// nolint +//nolint const ( // MySQL SSL modes mysqlSSLTrue = "true" diff --git a/storage/sql/crud.go b/storage/sql/crud.go index 1583c17741253ba35219b72a5beab8712ac80c55..7f8666db05a0a1bfaae56ceea20836f3131a1559 100644 --- a/storage/sql/crud.go +++ b/storage/sql/crud.go @@ -21,19 +21,18 @@ const keysRowID = "keys" // encoder wraps the underlying value in a JSON marshaler which is automatically // called by the database/sql package. // -// s := []string{"planes", "bears"} -// err := db.Exec(`insert into t1 (id, things) values (1, $1)`, encoder(s)) -// if err != nil { -// // handle error -// } -// -// var r []byte -// err = db.QueryRow(`select things from t1 where id = 1;`).Scan(&r) -// if err != nil { -// // handle error -// } -// fmt.Printf("%s\n", r) // ["planes","bears"] +// s := []string{"planes", "bears"} +// err := db.Exec(`insert into t1 (id, things) values (1, $1)`, encoder(s)) +// if err != nil { +// // handle error +// } // +// var r []byte +// err = db.QueryRow(`select things from t1 where id = 1;`).Scan(&r) +// if err != nil { +// // handle error +// } +// fmt.Printf("%s\n", r) // ["planes","bears"] func encoder(i interface{}) driver.Valuer { return jsonEncoder{i} } diff --git a/storage/storage.go b/storage/storage.go index 198a70c8e6718ff790ec4d1ac1c8dc687b1eebaf..c77c191762344c7089109ef31d6aaa3be7dd600c 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -144,8 +144,8 @@ type Storage interface { // Client represents an OAuth2 client. // // For further reading see: -// * Trusted peers: https://developers.google.com/identity/protocols/CrossClientAuth -// * Public clients: https://developers.google.com/api-client-library/python/auth/installed-app +// - Trusted peers: https://developers.google.com/identity/protocols/CrossClientAuth +// - Public clients: https://developers.google.com/api-client-library/python/auth/installed-app type Client struct { // Client ID and secret used to identify the client. ID string `json:"id" yaml:"id"`