diff --git a/.golangci.yaml b/.golangci.yaml index 1c2b2b2e851ca..e3f3797d06b81 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -2,6 +2,10 @@ # Over time we should try tightening some of these. linters-settings: + exhaustruct: + include: + # Gradually extend to cover more of the codebase. + - 'httpmw\.\w+' gocognit: min-complexity: 46 # Min code complexity (def 30). @@ -195,6 +199,10 @@ issues: # We use assertions rather than explicitly checking errors in tests - errcheck - forcetypeassert + - exhaustruct # This is unhelpful in tests. + - path: scripts/* + linters: + - exhaustruct fix: true max-issues-per-linter: 0 @@ -219,6 +227,7 @@ linters: - errcheck - errname - errorlint + - exhaustruct - exportloopref - forcetypeassert - gocritic diff --git a/coderd/coderd.go b/coderd/coderd.go index 79d58565b53d9..dc14727879f08 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -390,6 +390,7 @@ func New(options *Options) *API { RedirectToLogin: false, DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), Optional: false, + SessionTokenFunc: nil, // Default behavior }) // Same as above but it redirects to the login page. apiKeyMiddlewareRedirect := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ @@ -398,6 +399,7 @@ func New(options *Options) *API { RedirectToLogin: true, DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), Optional: false, + SessionTokenFunc: nil, // Default behavior }) // Same as the first but it's optional. apiKeyMiddlewareOptional := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ @@ -406,6 +408,7 @@ func New(options *Options) *API { RedirectToLogin: false, DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), Optional: true, + SessionTokenFunc: nil, // Default behavior }) // API rate limit middleware. The counter is local and not shared between diff --git a/coderd/httpmw/hsts.go b/coderd/httpmw/hsts.go index 52cfb79bbc403..fa72c83889d66 100644 --- a/coderd/httpmw/hsts.go +++ b/coderd/httpmw/hsts.go @@ -20,7 +20,7 @@ type HSTSConfig struct { func HSTSConfigOptions(maxAge int, options []string) (HSTSConfig, error) { if maxAge <= 0 { // No header, so no need to build the header string. - return HSTSConfig{}, nil + return HSTSConfig{HeaderValue: ""}, nil } // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security diff --git a/coderd/httpmw/realip.go b/coderd/httpmw/realip.go index ee708680e03cd..e7cc679ba95c0 100644 --- a/coderd/httpmw/realip.go +++ b/coderd/httpmw/realip.go @@ -56,7 +56,10 @@ func ExtractRealIP(config *RealIPConfig) func(next http.Handler) http.Handler { // configuration and headers. It does not mutate the original request. func ExtractRealIPAddress(config *RealIPConfig, req *http.Request) (net.IP, error) { if config == nil { - config = &RealIPConfig{} + config = &RealIPConfig{ + TrustedOrigins: nil, + TrustedHeaders: nil, + } } cf := isContainedIn(config.TrustedOrigins, getRemoteAddress(req.RemoteAddr)) @@ -81,7 +84,10 @@ func ExtractRealIPAddress(config *RealIPConfig, req *http.Request) (net.IP, erro // of each proxy header is set. func FilterUntrustedOriginHeaders(config *RealIPConfig, req *http.Request) { if config == nil { - config = &RealIPConfig{} + config = &RealIPConfig{ + TrustedOrigins: nil, + TrustedHeaders: nil, + } } cf := isContainedIn(config.TrustedOrigins, getRemoteAddress(req.RemoteAddr)) @@ -208,7 +214,10 @@ func RealIP(ctx context.Context) *RealIPState { // ParseRealIPConfig takes a raw string array of headers and origins // to produce a config. func ParseRealIPConfig(headers, origins []string) (*RealIPConfig, error) { - config := &RealIPConfig{} + config := &RealIPConfig{ + TrustedOrigins: []*net.IPNet{}, + TrustedHeaders: []string{}, + } for _, origin := range origins { _, network, err := net.ParseCIDR(origin) if err != nil { diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 75476b508eaad..1576950b97b61 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -88,6 +88,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { RedirectToLogin: false, DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), Optional: false, + SessionTokenFunc: nil, // Default behavior }) apiKeyMiddlewareOptional := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ DB: options.Database, @@ -95,6 +96,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { RedirectToLogin: false, DisableSessionExpiryRefresh: options.DeploymentValues.DisableSessionExpiryRefresh.Value(), Optional: true, + SessionTokenFunc: nil, // Default behavior }) deploymentID, err := options.Database.GetDeploymentID(ctx) diff --git a/install.sh b/install.sh index 3c0b7b2781e36..32f8799ddecbf 100755 --- a/install.sh +++ b/install.sh @@ -527,6 +527,7 @@ distro() { if [ -f /etc/os-release ]; then ( + # shellcheck disable=SC1091 . /etc/os-release if [ "${ID_LIKE-}" ]; then for id_like in $ID_LIKE; do @@ -553,6 +554,7 @@ distro_name() { if [ -f /etc/os-release ]; then ( + # shellcheck disable=SC1091 . /etc/os-release echo "$PRETTY_NAME" ) diff --git a/site/site.go b/site/site.go index 98ec8000fb761..6519e539e1458 100644 --- a/site/site.go +++ b/site/site.go @@ -297,6 +297,8 @@ func (h *Handler) renderHTMLWithState(rw http.ResponseWriter, r *http.Request, f // Special case for site, we can always disable refresh here because // the frontend will perform API requests if this fails. DisableSessionExpiryRefresh: true, + RedirectToLogin: false, + SessionTokenFunc: nil, }) if apiKey != nil && actor != nil { ctx := dbauthz.As(r.Context(), actor.Actor)