mirror of
https://github.com/juanfont/headscale.git
synced 2026-05-23 18:48:42 +09:00
all: annotate gosec false positives with rationale
Each //nolint:gosec carries the gosec code and one line on why
the finding is a false positive or already mitigated.
G124 cookies (oidc.go x3, oidc_confirm_test.go)
Secure is set conditionally on req.TLS != nil; HttpOnly and
SameSiteStrictMode already on. gosec misses the conditional.
Test fixture cookie is explicitly a test fixture.
G705 (debug.go)
templates.PingPage(...).Render() is a templ component that
auto-escapes user input.
G706 (scenario.go)
Integration log emits trusted scenario state. The pre-built
image G706 sites in hsic.go / tsic.go ride along with the
earlier constants commit.
G710 (app.go, tailsql.go)
Redirect target is "trusted ServerURL prefix + path". gosec
cannot see past the prefix.
This commit is contained in:
@@ -56,7 +56,7 @@ var (
|
||||
errNoClientFound = errors.New("client not found")
|
||||
|
||||
// AllVersions represents a list of Tailscale versions the suite
|
||||
// uses to test compatibility with the ControlServer.
|
||||
// uses to test compatibility with the [ControlServer].
|
||||
//
|
||||
// The list contains two special cases, "head" and "unstable" which
|
||||
// points to the current tip of Tailscale's main branch and the latest
|
||||
@@ -78,7 +78,7 @@ var (
|
||||
)
|
||||
)
|
||||
|
||||
// User represents a User in the ControlServer and a map of TailscaleClient's
|
||||
// User represents a User in the [ControlServer] and a map of [TailscaleClient]'s
|
||||
// associated with the User.
|
||||
type User struct {
|
||||
Clients map[string]TailscaleClient
|
||||
@@ -88,10 +88,10 @@ type User struct {
|
||||
syncWaitGroup errgroup.Group
|
||||
}
|
||||
|
||||
// Scenario is a representation of an environment with one ControlServer and
|
||||
// one or more User's and its associated TailscaleClients.
|
||||
// Scenario is a representation of an environment with one [ControlServer] and
|
||||
// one or more [User]'s and its associated [TailscaleClient]s.
|
||||
// A Scenario is intended to simplify setting up a new testcase for testing
|
||||
// a ControlServer with TailscaleClients.
|
||||
// a [ControlServer] with [TailscaleClient]s.
|
||||
// TODO(kradalby): make control server configurable, test correctness with Tailscale SaaS.
|
||||
type Scenario struct {
|
||||
// TODO(kradalby): support multiple headcales for later, currently only
|
||||
@@ -177,8 +177,8 @@ func (s *Scenario) prefixedNetworkName(name string) string {
|
||||
return s.testHashPrefix + "-" + name
|
||||
}
|
||||
|
||||
// NewScenario creates a test Scenario which can be used to bootstraps a ControlServer with
|
||||
// a set of Users and TailscaleClients.
|
||||
// NewScenario creates a test [Scenario] which can be used to bootstraps a [ControlServer] with
|
||||
// a set of [User]s and [TailscaleClient]s.
|
||||
func NewScenario(spec ScenarioSpec) (*Scenario, error) {
|
||||
pool, err := dockertest.NewPool("")
|
||||
if err != nil {
|
||||
@@ -422,15 +422,15 @@ func (s *Scenario) ShutdownAssertNoPanics(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown shuts down and cleans up all the containers (ControlServer, TailscaleClient)
|
||||
// Shutdown shuts down and cleans up all the containers ([ControlServer], [TailscaleClient])
|
||||
// and networks associated with it.
|
||||
// In addition, it will save the logs of the ControlServer to `/tmp/control` in the
|
||||
// In addition, it will save the logs of the [ControlServer] to `/tmp/control` in the
|
||||
// environment running the tests.
|
||||
func (s *Scenario) Shutdown() {
|
||||
s.ShutdownAssertNoPanics(nil)
|
||||
}
|
||||
|
||||
// Users returns the name of all users associated with the Scenario.
|
||||
// Users returns the name of all users associated with the [Scenario].
|
||||
func (s *Scenario) Users() []string {
|
||||
users := make([]string, 0, len(s.users))
|
||||
for user := range s.users {
|
||||
@@ -443,8 +443,8 @@ func (s *Scenario) Users() []string {
|
||||
/// Headscale related stuff
|
||||
// Note: These functions assume that there is a _single_ headscale instance for now
|
||||
|
||||
// Headscale returns a ControlServer instance based on hsic (HeadscaleInContainer)
|
||||
// If the Scenario already has an instance, the pointer to the running container
|
||||
// Headscale returns a [ControlServer] instance based on hsic ([hsic.HeadscaleInContainer]).
|
||||
// If the [Scenario] already has an instance, the pointer to the running container
|
||||
// will be return, otherwise a new instance will be created.
|
||||
// TODO(kradalby): make port and headscale configurable, multiple instances support?
|
||||
func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
|
||||
@@ -474,12 +474,12 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
|
||||
return headscale, nil
|
||||
}
|
||||
|
||||
// Pool returns the dockertest pool for the scenario.
|
||||
// Pool returns the [dockertest.Pool] for the scenario.
|
||||
func (s *Scenario) Pool() *dockertest.Pool {
|
||||
return s.pool
|
||||
}
|
||||
|
||||
// GetOrCreateUser gets or creates a user in the scenario.
|
||||
// GetOrCreateUser gets or creates a user in the [Scenario].
|
||||
func (s *Scenario) GetOrCreateUser(userStr string) *User {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
@@ -497,7 +497,7 @@ func (s *Scenario) GetOrCreateUser(userStr string) *User {
|
||||
}
|
||||
|
||||
// CreatePreAuthKey creates a "pre authentorised key" to be created in the
|
||||
// Headscale instance on behalf of the Scenario.
|
||||
// Headscale instance on behalf of the [Scenario].
|
||||
func (s *Scenario) CreatePreAuthKey(
|
||||
user uint64,
|
||||
reusable bool,
|
||||
@@ -516,7 +516,7 @@ func (s *Scenario) CreatePreAuthKey(
|
||||
}
|
||||
|
||||
// CreatePreAuthKeyWithOptions creates a "pre authorised key" with the specified options
|
||||
// to be created in the Headscale instance on behalf of the Scenario.
|
||||
// to be created in the Headscale instance on behalf of the [Scenario].
|
||||
func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.PreAuthKey, error) {
|
||||
headscale, err := s.Headscale()
|
||||
if err != nil {
|
||||
@@ -532,7 +532,7 @@ func (s *Scenario) CreatePreAuthKeyWithOptions(opts hsic.AuthKeyOptions) (*v1.Pr
|
||||
}
|
||||
|
||||
// CreatePreAuthKeyWithTags creates a "pre authorised key" with the specified tags
|
||||
// to be created in the Headscale instance on behalf of the Scenario.
|
||||
// to be created in the Headscale instance on behalf of the [Scenario].
|
||||
func (s *Scenario) CreatePreAuthKeyWithTags(
|
||||
user uint64,
|
||||
reusable bool,
|
||||
@@ -552,8 +552,8 @@ func (s *Scenario) CreatePreAuthKeyWithTags(
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// CreateUser creates a User to be created in the
|
||||
// Headscale instance on behalf of the Scenario.
|
||||
// CreateUser creates a [User] to be created in the
|
||||
// Headscale instance on behalf of the [Scenario].
|
||||
func (s *Scenario) CreateUser(user string) (*v1.User, error) {
|
||||
if headscale, err := s.Headscale(); err == nil { //nolint:noinlineerr
|
||||
u, err := headscale.CreateUser(user)
|
||||
@@ -619,8 +619,8 @@ func (s *Scenario) CreateTailscaleNode(
|
||||
return tsClient, nil
|
||||
}
|
||||
|
||||
// CreateTailscaleNodesInUser creates and adds a new TailscaleClient to a
|
||||
// User in the Scenario.
|
||||
// CreateTailscaleNodesInUser creates and adds a new [TailscaleClient] to a
|
||||
// [User] in the [Scenario].
|
||||
func (s *Scenario) CreateTailscaleNodesInUser(
|
||||
userStr string,
|
||||
requestedVersion string,
|
||||
@@ -720,8 +720,8 @@ func (s *Scenario) CreateTailscaleNodesInUser(
|
||||
return fmt.Errorf("adding tailscale node: %w", errNoUserAvailable)
|
||||
}
|
||||
|
||||
// RunTailscaleUp will log in all of the TailscaleClients associated with a
|
||||
// User to the given ControlServer (by URL).
|
||||
// RunTailscaleUp will log in all of the [TailscaleClient]s associated with a
|
||||
// [User] to the given [ControlServer] (by URL).
|
||||
func (s *Scenario) RunTailscaleUp(
|
||||
userStr, loginServer, authKey string,
|
||||
) error {
|
||||
@@ -752,7 +752,7 @@ func (s *Scenario) RunTailscaleUp(
|
||||
return fmt.Errorf("bringing up tailscale node: %w", errNoUserAvailable)
|
||||
}
|
||||
|
||||
// CountTailscale returns the total number of TailscaleClients in a Scenario.
|
||||
// CountTailscale returns the total number of [TailscaleClient]s in a [Scenario].
|
||||
// This is the sum of Users x TailscaleClients.
|
||||
func (s *Scenario) CountTailscale() int {
|
||||
count := 0
|
||||
@@ -764,8 +764,8 @@ func (s *Scenario) CountTailscale() int {
|
||||
return count
|
||||
}
|
||||
|
||||
// WaitForTailscaleSync blocks execution until all the TailscaleClient reports
|
||||
// to have all other TailscaleClients present in their netmap.NetworkMap.
|
||||
// WaitForTailscaleSync blocks execution until all the [TailscaleClient] reports
|
||||
// to have all other [TailscaleClient]s present in their [netmap.NetworkMap].
|
||||
func (s *Scenario) WaitForTailscaleSync() error {
|
||||
tsCount := s.CountTailscale()
|
||||
|
||||
@@ -784,7 +784,7 @@ func (s *Scenario) WaitForTailscaleSync() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// SyncOption configures WaitForTailscaleSyncPerUser.
|
||||
// SyncOption configures [Scenario.WaitForTailscaleSyncPerUser].
|
||||
type SyncOption func(*syncOptions)
|
||||
|
||||
type syncOptions struct {
|
||||
@@ -799,7 +799,7 @@ func WithPreBarrier(barrier func(context.Context) error) SyncOption {
|
||||
return func(o *syncOptions) { o.preBarrier = barrier }
|
||||
}
|
||||
|
||||
// WaitForTailscaleSyncPerUser blocks until each TailscaleClient has
|
||||
// WaitForTailscaleSyncPerUser blocks until each [TailscaleClient] has
|
||||
// the expected per-user peer count (necessary for policies like
|
||||
// autogroup:self where cross-user peers are invisible).
|
||||
func (s *Scenario) WaitForTailscaleSyncPerUser(timeout, retryInterval time.Duration, opts ...SyncOption) error {
|
||||
@@ -848,8 +848,8 @@ func (s *Scenario) WaitForTailscaleSyncPerUser(timeout, retryInterval time.Durat
|
||||
return nil
|
||||
}
|
||||
|
||||
// WaitForTailscaleSyncWithPeerCount blocks execution until all the TailscaleClient reports
|
||||
// to have all other TailscaleClients present in their netmap.NetworkMap.
|
||||
// WaitForTailscaleSyncWithPeerCount blocks execution until all the [TailscaleClient] reports
|
||||
// to have all other [TailscaleClient]s present in their [netmap.NetworkMap].
|
||||
func (s *Scenario) WaitForTailscaleSyncWithPeerCount(peerCount int, timeout, retryInterval time.Duration) error {
|
||||
var allErrors []error
|
||||
|
||||
@@ -890,7 +890,7 @@ func (s *Scenario) CreateHeadscaleEnv(
|
||||
}
|
||||
|
||||
// CreateHeadscaleEnv starts the headscale environment and the clients
|
||||
// according to the ScenarioSpec passed to the Scenario.
|
||||
// according to the [ScenarioSpec] passed to the [Scenario].
|
||||
func (s *Scenario) createHeadscaleEnv(
|
||||
withURL bool,
|
||||
tsOpts []tsic.Option,
|
||||
@@ -900,7 +900,7 @@ func (s *Scenario) createHeadscaleEnv(
|
||||
}
|
||||
|
||||
// createHeadscaleEnvWithTags starts the headscale environment and the clients
|
||||
// according to the ScenarioSpec passed to the Scenario. If preAuthKeyTags is
|
||||
// according to the [ScenarioSpec] passed to the [Scenario]. If preAuthKeyTags is
|
||||
// non-empty and withURL is false, the tags will be applied to the PreAuthKey
|
||||
// (tags-as-identity model).
|
||||
//
|
||||
@@ -1381,6 +1381,7 @@ func (t LoggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//nolint:gosec // G706: integration-only log of trusted scenario state
|
||||
log.Printf(`
|
||||
---
|
||||
%s - method: %s | url: %s
|
||||
@@ -1391,8 +1392,8 @@ func (t LoggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetIPs returns all netip.Addr of TailscaleClients associated with a User
|
||||
// in a Scenario.
|
||||
// GetIPs returns all [netip.Addr] of [TailscaleClient]s associated with a [User]
|
||||
// in a [Scenario].
|
||||
func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
|
||||
var ips []netip.Addr
|
||||
|
||||
@@ -1412,7 +1413,7 @@ func (s *Scenario) GetIPs(user string) ([]netip.Addr, error) {
|
||||
return ips, fmt.Errorf("getting IPs: %w", errNoUserAvailable)
|
||||
}
|
||||
|
||||
// GetClients returns all TailscaleClients associated with a User in a Scenario.
|
||||
// GetClients returns all [TailscaleClient]s associated with a [User] in a [Scenario].
|
||||
func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
|
||||
var clients []TailscaleClient
|
||||
|
||||
@@ -1427,7 +1428,7 @@ func (s *Scenario) GetClients(user string) ([]TailscaleClient, error) {
|
||||
return clients, fmt.Errorf("getting clients: %w", errNoUserAvailable)
|
||||
}
|
||||
|
||||
// ListTailscaleClients returns a list of TailscaleClients given the Users
|
||||
// ListTailscaleClients returns a list of [TailscaleClient]s given the [User]s
|
||||
// passed as parameters.
|
||||
func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, error) {
|
||||
var allClients []TailscaleClient
|
||||
@@ -1448,7 +1449,7 @@ func (s *Scenario) ListTailscaleClients(users ...string) ([]TailscaleClient, err
|
||||
return allClients, nil
|
||||
}
|
||||
|
||||
// FindTailscaleClientByIP returns a TailscaleClient associated with an IP address
|
||||
// FindTailscaleClientByIP returns a [TailscaleClient] associated with an IP address
|
||||
// if it exists.
|
||||
func (s *Scenario) FindTailscaleClientByIP(ip netip.Addr) (TailscaleClient, error) {
|
||||
clients, err := s.ListTailscaleClients()
|
||||
@@ -1466,7 +1467,7 @@ func (s *Scenario) FindTailscaleClientByIP(ip netip.Addr) (TailscaleClient, erro
|
||||
return nil, errNoClientFound
|
||||
}
|
||||
|
||||
// ListTailscaleClientsIPs returns a list of netip.Addr based on Users
|
||||
// ListTailscaleClientsIPs returns a list of [netip.Addr] based on [User]s
|
||||
// passed as parameters.
|
||||
func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error) {
|
||||
var allIps []netip.Addr
|
||||
@@ -1487,7 +1488,7 @@ func (s *Scenario) ListTailscaleClientsIPs(users ...string) ([]netip.Addr, error
|
||||
return allIps, nil
|
||||
}
|
||||
|
||||
// ListTailscaleClientsFQDNs returns a list of FQDN based on Users
|
||||
// ListTailscaleClientsFQDNs returns a list of FQDN based on [User]s
|
||||
// passed as parameters.
|
||||
func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error) {
|
||||
allFQDNs := make([]string, 0)
|
||||
@@ -1509,8 +1510,8 @@ func (s *Scenario) ListTailscaleClientsFQDNs(users ...string) ([]string, error)
|
||||
return allFQDNs, nil
|
||||
}
|
||||
|
||||
// WaitForTailscaleLogout blocks execution until all TailscaleClients have
|
||||
// logged out of the ControlServer.
|
||||
// WaitForTailscaleLogout blocks execution until all [TailscaleClient]s have
|
||||
// logged out of the [ControlServer].
|
||||
func (s *Scenario) WaitForTailscaleLogout() error {
|
||||
for _, user := range s.users {
|
||||
for _, client := range user.Clients {
|
||||
|
||||
Reference in New Issue
Block a user