Compare commits

..

23 Commits

Author SHA1 Message Date
Juan Font
8426fe71e0 Correct typo on standalone (fixes #1021) 2022-12-02 16:47:21 +00:00
Kristoffer Dalby
0e28018637 Add breaking change about noise private path
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-12-02 16:47:21 +00:00
Kristoffer Dalby
9e1c3c1688 Ignore tparallel where it doesnt make sense
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-12-02 16:47:21 +00:00
Juan Font
a7c608f0cb generateACLPolicy() no longer a Headscale method 2022-11-30 23:37:58 +00:00
Kristoffer Dalby
eb072a1a74 mark some changes as more important
Signed-off-by: Kristoffer Dalby <kradalby@kradalby.no>
2022-11-26 12:01:12 +01:00
Kristoffer Dalby
36b8862e7c Add notes about current ssh status
Signed-off-by: Kristoffer Dalby <kradalby@kradalby.no>
2022-11-26 11:53:31 +01:00
Even Holthe
d4e3bf184b Add experimental flag to unit test 2022-11-26 11:53:31 +01:00
Even Holthe
c28ca27133 Add SSH ACL to changelog 2022-11-26 11:53:31 +01:00
Kristoffer Dalby
c02e105065 Mark the flag properly experimental
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
22da5bfc1d Enable SSH for tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
c6d31747f7 Add feature flag for SSH, and warning
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
91ed6e2197 Allow WithEnv to be passed multiple times
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
d71aef3b98 Mark all tests with Parallel
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
8a79c2e7ed Do not retry on permission denied in ssh
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
f34e7c341b Strip newline from hostname
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
e28d308796 Add negative tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Even Holthe
f610be632e SSH: add test between namespaces 2022-11-26 11:53:31 +01:00
Even Holthe
fd6d25b5c1 SSH: Lint and typos 2022-11-26 11:53:31 +01:00
Kristoffer Dalby
3695284286 Make simple initial test case
This commit makes the initial SSH test a bit simpler:

- Use the same pattern/functions for all clients as other tests
- Only test within _one_ namespace/user to confirm the base case
- Use retry function, same as taildrop, there is some funky going on
  there...

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
cfaa36e51a Add method to expose container id
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Kristoffer Dalby
d207c30949 Ensure we have ssh in container
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2022-11-26 11:53:31 +01:00
Even Holthe
519f22f9bf SSH integration test setup 2022-11-26 11:53:31 +01:00
Even Holthe
52a323b90d Add SSH capability advertisement
Advertises the SSH capability, and parses the SSH ACLs to pass to the
tailscale client. Doesn’t support ‘autogroup’ ACL functionality.

Co-authored-by: Daniel Brooks <db48x@headline.com>
2022-11-26 11:53:31 +01:00
7 changed files with 69 additions and 40 deletions

View File

@@ -1,15 +1,27 @@
# CHANGELOG
## 0.17.0 (2022-XX-XX)
## 0.17.0 (2022-11-26)
### BREAKING
- `noise.private_key_path` has been added and is required for the new noise protocol.
- Log level option `log_level` was moved to a distinct `log` config section and renamed to `level` [#768](https://github.com/juanfont/headscale/pull/768)
- Removed Alpine Linux container image [#962](https://github.com/juanfont/headscale/pull/962)
### Changes
### Important Changes
- Added support for Tailscale TS2021 protocol [#738](https://github.com/juanfont/headscale/pull/738)
- Add experimental support for [SSH ACL](https://tailscale.com/kb/1018/acls/#tailscale-ssh) (see docs for limitations) [#847](https://github.com/juanfont/headscale/pull/847)
- Please note that this support should be considered _partially_ implemented
- SSH ACLs status:
- Support `accept` and `check` (SSH can be enabled and used for connecting and authentication)
- Rejecting connections **are not supported**, meaning that if you enable SSH, then assume that _all_ `ssh` connections **will be allowed**.
- If you decied to try this feature, please carefully managed permissions by blocking port `22` with regular ACLs or do _not_ set `--ssh` on your clients.
- We are currently improving our testing of the SSH ACLs, help us get an overview by testing and giving feedback.
- This feature should be considered dangerous and it is disabled by default. Enable by setting `HEADSCALE_EXPERIMENTAL_FEATURE_SSH=1`.
### Changes
- Add ability to specify config location via env var `HEADSCALE_CONFIG` [#674](https://github.com/juanfont/headscale/issues/674)
- Target Go 1.19 for Headscale [#778](https://github.com/juanfont/headscale/pull/778)
- Target Tailscale v1.30.0 to build Headscale [#780](https://github.com/juanfont/headscale/pull/780)
@@ -29,14 +41,6 @@
- Fix OIDC registration issues [#960](https://github.com/juanfont/headscale/pull/960) and [#971](https://github.com/juanfont/headscale/pull/971)
- Add support for specifying NextDNS DNS-over-HTTPS resolver [#940](https://github.com/juanfont/headscale/pull/940)
- Make more sslmode available for postgresql connection [#927](https://github.com/juanfont/headscale/pull/927)
- Add experimental support for [SSH ACL](https://tailscale.com/kb/1018/acls/#tailscale-ssh) (see docs for limitations) [#847](https://github.com/juanfont/headscale/pull/847)
- Please note that this support should be considered _partially_ implemented
- SSH ACLs status:
- Support `accept` and `check` (SSH can be enabled and used for connecting and authentication)
- Rejecting connections **are not supported**, meaning that if you enable SSH, then assume that _all_ `ssh` connections **will be allowed**.
- If you decied to try this feature, please carefully managed permissions by blocking port `22` with regular ACLs or do _not_ set `--ssh` on your clients.
- We are currently improving our testing of the SSH ACLs, help us get an overview by testing and giving feedback.
- This feature should be considered dangerous and it is disabled by default. Enable by setting `HEADSCALE_EXPERIMENTAL_FEATURE_SSH=1`.
## 0.16.4 (2022-08-21)

41
acls.go
View File

@@ -117,7 +117,16 @@ func (h *Headscale) LoadACLPolicy(path string) error {
}
func (h *Headscale) UpdateACLRules() error {
rules, err := h.generateACLRules()
machines, err := h.ListMachines()
if err != nil {
return err
}
if h.aclPolicy == nil {
return errEmptyPolicy
}
rules, err := generateACLRules(machines, *h.aclPolicy, h.cfg.OIDC.StripEmaildomain)
if err != nil {
return err
}
@@ -141,26 +150,17 @@ func (h *Headscale) UpdateACLRules() error {
return nil
}
func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) {
func generateACLRules(machines []Machine, aclPolicy ACLPolicy, stripEmaildomain bool) ([]tailcfg.FilterRule, error) {
rules := []tailcfg.FilterRule{}
if h.aclPolicy == nil {
return nil, errEmptyPolicy
}
machines, err := h.ListMachines()
if err != nil {
return nil, err
}
for index, acl := range h.aclPolicy.ACLs {
for index, acl := range aclPolicy.ACLs {
if acl.Action != "accept" {
return nil, errInvalidAction
}
srcIPs := []string{}
for innerIndex, src := range acl.Sources {
srcs, err := h.generateACLPolicySrcIP(machines, *h.aclPolicy, src)
srcs, err := generateACLPolicySrcIP(machines, aclPolicy, src, stripEmaildomain)
if err != nil {
log.Error().
Msgf("Error parsing ACL %d, Source %d", index, innerIndex)
@@ -180,11 +180,12 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) {
destPorts := []tailcfg.NetPortRange{}
for innerIndex, dest := range acl.Destinations {
dests, err := h.generateACLPolicyDest(
dests, err := generateACLPolicyDest(
machines,
*h.aclPolicy,
aclPolicy,
dest,
needsWildcard,
stripEmaildomain,
)
if err != nil {
log.Error().
@@ -310,19 +311,21 @@ func sshCheckAction(duration string) (*tailcfg.SSHAction, error) {
}, nil
}
func (h *Headscale) generateACLPolicySrcIP(
func generateACLPolicySrcIP(
machines []Machine,
aclPolicy ACLPolicy,
src string,
stripEmaildomain bool,
) ([]string, error) {
return expandAlias(machines, aclPolicy, src, h.cfg.OIDC.StripEmaildomain)
return expandAlias(machines, aclPolicy, src, stripEmaildomain)
}
func (h *Headscale) generateACLPolicyDest(
func generateACLPolicyDest(
machines []Machine,
aclPolicy ACLPolicy,
dest string,
needsWildcard bool,
stripEmaildomain bool,
) ([]tailcfg.NetPortRange, error) {
tokens := strings.Split(dest, ":")
if len(tokens) < expectedTokenItems || len(tokens) > 3 {
@@ -346,7 +349,7 @@ func (h *Headscale) generateACLPolicyDest(
machines,
aclPolicy,
alias,
h.cfg.OIDC.StripEmaildomain,
stripEmaildomain,
)
if err != nil {
return nil, err

View File

@@ -54,7 +54,7 @@ func (s *Suite) TestBasicRule(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_1.hujson")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
rules, err := generateACLRules([]Machine{}, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
}
@@ -411,7 +411,7 @@ func (s *Suite) TestPortRange(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_range.hujson")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
rules, err := generateACLRules([]Machine{}, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
@@ -425,7 +425,7 @@ func (s *Suite) TestProtocolParsing(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_protocols.hujson")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
rules, err := generateACLRules([]Machine{}, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
@@ -439,7 +439,7 @@ func (s *Suite) TestPortWildcard(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_wildcards.hujson")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
rules, err := generateACLRules([]Machine{}, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
@@ -455,7 +455,7 @@ func (s *Suite) TestPortWildcardYAML(c *check.C) {
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_wildcards.yaml")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
rules, err := generateACLRules([]Machine{}, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
@@ -495,7 +495,10 @@ func (s *Suite) TestPortNamespace(c *check.C) {
)
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
machines, err := app.ListMachines()
c.Assert(err, check.IsNil)
rules, err := generateACLRules(machines, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)
@@ -535,7 +538,10 @@ func (s *Suite) TestPortGroup(c *check.C) {
err = app.LoadACLPolicy("./tests/acls/acl_policy_basic_groups.hujson")
c.Assert(err, check.IsNil)
rules, err := app.generateACLRules()
machines, err := app.ListMachines()
c.Assert(err, check.IsNil)
rules, err := generateACLRules(machines, *app.aclPolicy, false)
c.Assert(err, check.IsNil)
c.Assert(rules, check.NotNil)

View File

@@ -122,6 +122,10 @@ func TestPingAllByHostname(t *testing.T) {
}
}
// If subtests are parallel, then they will start before setup is run.
// This might mean we approach setup slightly wrong, but for now, ignore
// the linter
// nolint:tparallel
func TestTaildrop(t *testing.T) {
IntegrationSkip(t)
t.Parallel()

View File

@@ -21,6 +21,10 @@ func IntegrationSkip(t *testing.T) {
}
}
// If subtests are parallel, then they will start before setup is run.
// This might mean we approach setup slightly wrong, but for now, ignore
// the linter
// nolint:tparallel
func TestHeadscale(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -70,6 +74,10 @@ func TestHeadscale(t *testing.T) {
}
}
// If subtests are parallel, then they will start before setup is run.
// This might mean we approach setup slightly wrong, but for now, ignore
// the linter
// nolint:tparallel
func TestCreateTailscale(t *testing.T) {
IntegrationSkip(t)
t.Parallel()
@@ -104,6 +112,10 @@ func TestCreateTailscale(t *testing.T) {
}
}
// If subtests are parallel, then they will start before setup is run.
// This might mean we approach setup slightly wrong, but for now, ignore
// the linter
// nolint:tparallel
func TestTailscaleNodesJoiningHeadcale(t *testing.T) {
IntegrationSkip(t)
t.Parallel()

View File

@@ -220,8 +220,8 @@ func (h *Headscale) ApplePlatformConfig(
}
switch platform {
case "macos-standlone":
if err := macosStandloneTemplate.Execute(&payload, platformConfig); err != nil {
case "macos-standalone":
if err := macosStandaloneTemplate.Execute(&payload, platformConfig); err != nil {
handleMacError(err)
return
@@ -390,7 +390,7 @@ var macosAppStoreTemplate = template.Must(template.New("macosTemplate").Parse(`
</dict>
`))
var macosStandloneTemplate = template.Must(template.New("macosStandloneTemplate").Parse(`
var macosStandaloneTemplate = template.Must(template.New("macosStandaloneTemplate").Parse(`
<dict>
<key>PayloadType</key>
<string>io.tailscale.ipn.macsys</string>

View File

@@ -92,7 +92,7 @@
<code>defaults write io.tailscale.ipn.macos ControlURL {{.URL}}</code>
</li>
<li>
for standlone client:
for standalone client:
<code>defaults write io.tailscale.ipn.macsys ControlURL {{.URL}}</code>
</li>
</ul>