mirror of
https://github.com/juanfont/headscale.git
synced 2024-12-02 03:33:05 +00:00
inline old acl hujson tests
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
f2c1d1b8f9
commit
2d365c8c9c
16 changed files with 359 additions and 474 deletions
|
@ -59,8 +59,8 @@ const (
|
||||||
|
|
||||||
var featureEnableSSH = envknob.RegisterBool("HEADSCALE_EXPERIMENTAL_FEATURE_SSH")
|
var featureEnableSSH = envknob.RegisterBool("HEADSCALE_EXPERIMENTAL_FEATURE_SSH")
|
||||||
|
|
||||||
// LoadACLPolicy loads the ACL policy from the specify path, and generates the ACL rules.
|
// LoadACLPolicyFromPath loads the ACL policy from the specify path, and generates the ACL rules.
|
||||||
func (h *Headscale) LoadACLPolicy(path string) error {
|
func (h *Headscale) LoadACLPolicyFromPath(path string) error {
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("func", "LoadACLPolicy").
|
Str("func", "LoadACLPolicy").
|
||||||
Str("path", path).
|
Str("path", path).
|
||||||
|
@ -72,37 +72,42 @@ func (h *Headscale) LoadACLPolicy(path string) error {
|
||||||
}
|
}
|
||||||
defer policyFile.Close()
|
defer policyFile.Close()
|
||||||
|
|
||||||
var policy ACLPolicy
|
|
||||||
policyBytes, err := io.ReadAll(policyFile)
|
policyBytes, err := io.ReadAll(policyFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch filepath.Ext(path) {
|
|
||||||
case ".yml", ".yaml":
|
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("path", path).
|
Str("path", path).
|
||||||
Bytes("file", policyBytes).
|
Bytes("file", policyBytes).
|
||||||
Msg("Loading ACLs from YAML")
|
Msg("Loading ACLs")
|
||||||
|
|
||||||
err := yaml.Unmarshal(policyBytes, &policy)
|
switch filepath.Ext(path) {
|
||||||
|
case ".yml", ".yaml":
|
||||||
|
return h.LoadACLPolicyFromBytes(policyBytes, "yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.LoadACLPolicyFromBytes(policyBytes, "hujson")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Headscale) LoadACLPolicyFromBytes(acl []byte, format string) error {
|
||||||
|
var policy ACLPolicy
|
||||||
|
switch format {
|
||||||
|
case "yaml":
|
||||||
|
err := yaml.Unmarshal(acl, &policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace().
|
|
||||||
Interface("policy", policy).
|
|
||||||
Msg("Loaded policy from YAML")
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ast, err := hujson.Parse(policyBytes)
|
ast, err := hujson.Parse(acl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ast.Standardize()
|
ast.Standardize()
|
||||||
policyBytes = ast.Pack()
|
acl = ast.Pack()
|
||||||
err = json.Unmarshal(policyBytes, &policy)
|
err = json.Unmarshal(acl, &policy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,26 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Suite) TestWrongPath(c *check.C) {
|
func (s *Suite) TestWrongPath(c *check.C) {
|
||||||
err := app.LoadACLPolicy("asdfg")
|
err := app.LoadACLPolicyFromPath("asdfg")
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestBrokenHuJson(c *check.C) {
|
func (s *Suite) TestBrokenHuJson(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/broken.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestInvalidPolicyHuson(c *check.C) {
|
func (s *Suite) TestInvalidPolicyHuson(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/invalid.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"valid_json": true,
|
||||||
|
"but_a_policy_though": false
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
c.Assert(err, check.Equals, errEmptyPolicy)
|
c.Assert(err, check.Equals, errEmptyPolicy)
|
||||||
}
|
}
|
||||||
|
@ -49,12 +58,161 @@ func (s *Suite) TestParseInvalidCIDR(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestRuleInvalidGeneration(c *check.C) {
|
func (s *Suite) TestRuleInvalidGeneration(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_invalid.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
// Declare static groups of users beyond those in the identity service.
|
||||||
|
"groups": {
|
||||||
|
"group:example": [
|
||||||
|
"user1@example.com",
|
||||||
|
"user2@example.com",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Declare hostname aliases to use in place of IP addresses or subnets.
|
||||||
|
"hosts": {
|
||||||
|
"example-host-1": "100.100.100.100",
|
||||||
|
"example-host-2": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
// Define who is allowed to use which tags.
|
||||||
|
"tagOwners": {
|
||||||
|
// Everyone in the montreal-admins or global-admins group are
|
||||||
|
// allowed to tag servers as montreal-webserver.
|
||||||
|
"tag:montreal-webserver": [
|
||||||
|
"group:montreal-admins",
|
||||||
|
"group:global-admins",
|
||||||
|
],
|
||||||
|
// Only a few admins are allowed to create API servers.
|
||||||
|
"tag:api-server": [
|
||||||
|
"group:global-admins",
|
||||||
|
"example-host-1",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Access control lists.
|
||||||
|
"acls": [
|
||||||
|
// Engineering users, plus the president, can access port 22 (ssh)
|
||||||
|
// and port 3389 (remote desktop protocol) on all servers, and all
|
||||||
|
// ports on git-server or ci-server.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"group:engineering",
|
||||||
|
"president@example.com"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"*:22,3389",
|
||||||
|
"git-server:*",
|
||||||
|
"ci-server:*"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Allow engineer users to access any port on a device tagged with
|
||||||
|
// tag:production.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"group:engineers"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"tag:production:*"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Allow servers in the my-subnet host and 192.168.1.0/24 to access hosts
|
||||||
|
// on both networks.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"my-subnet",
|
||||||
|
"192.168.1.0/24"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"my-subnet:*",
|
||||||
|
"192.168.1.0/24:*"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Allow every user of your network to access anything on the network.
|
||||||
|
// Comment out this section if you want to define specific ACL
|
||||||
|
// restrictions above.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"*:*"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// All users in Montreal are allowed to access the Montreal web
|
||||||
|
// servers.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"group:montreal-users"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"tag:montreal-webserver:80,443"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// Montreal web servers are allowed to make outgoing connections to
|
||||||
|
// the API servers, but only on https port 443.
|
||||||
|
// In contrast, this doesn't grant API servers the right to initiate
|
||||||
|
// any connections.
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"tag:montreal-webserver"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"tag:api-server:443"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// Declare tests to check functionality of ACL rules
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"src": "user1@example.com",
|
||||||
|
"accept": [
|
||||||
|
"example-host-1:22",
|
||||||
|
"example-host-2:80"
|
||||||
|
],
|
||||||
|
"deny": [
|
||||||
|
"exapmle-host-2:100"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "user2@example.com",
|
||||||
|
"accept": [
|
||||||
|
"100.60.3.4:22"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.NotNil)
|
c.Assert(err, check.NotNil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestBasicRule(c *check.C) {
|
func (s *Suite) TestBasicRule(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_1.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"subnet-1",
|
||||||
|
"192.168.1.0/24"
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"*:22,3389",
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
||||||
|
@ -411,7 +569,27 @@ func (s *Suite) TestValidTagInvalidUser(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestPortRange(c *check.C) {
|
func (s *Suite) TestPortRange(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_range.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"subnet-1",
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"host-1:5400-5500",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
||||||
|
@ -425,7 +603,48 @@ func (s *Suite) TestPortRange(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestProtocolParsing(c *check.C) {
|
func (s *Suite) TestProtocolParsing(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_protocols.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"Action": "accept",
|
||||||
|
"src": [
|
||||||
|
"*",
|
||||||
|
],
|
||||||
|
"proto": "tcp",
|
||||||
|
"dst": [
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Action": "accept",
|
||||||
|
"src": [
|
||||||
|
"*",
|
||||||
|
],
|
||||||
|
"proto": "udp",
|
||||||
|
"dst": [
|
||||||
|
"host-1:53",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Action": "accept",
|
||||||
|
"src": [
|
||||||
|
"*",
|
||||||
|
],
|
||||||
|
"proto": "icmp",
|
||||||
|
"dst": [
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
||||||
|
@ -439,7 +658,27 @@ func (s *Suite) TestProtocolParsing(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestPortWildcard(c *check.C) {
|
func (s *Suite) TestPortWildcard(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_wildcards.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"Action": "accept",
|
||||||
|
"src": [
|
||||||
|
"*",
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
||||||
|
@ -455,7 +694,19 @@ func (s *Suite) TestPortWildcard(c *check.C) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestPortWildcardYAML(c *check.C) {
|
func (s *Suite) TestPortWildcardYAML(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_wildcards.yaml")
|
acl := []byte(`
|
||||||
|
---
|
||||||
|
hosts:
|
||||||
|
host-1: 100.100.100.100/32
|
||||||
|
subnet-1: 100.100.101.100/24
|
||||||
|
acls:
|
||||||
|
- action: accept
|
||||||
|
src:
|
||||||
|
- "*"
|
||||||
|
dst:
|
||||||
|
- host-1:*
|
||||||
|
`)
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "yaml")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
rules, err := app.aclPolicy.generateFilterRules([]Machine{}, false)
|
||||||
|
@ -493,9 +744,27 @@ func (s *Suite) TestPortUser(c *check.C) {
|
||||||
}
|
}
|
||||||
app.db.Save(&machine)
|
app.db.Save(&machine)
|
||||||
|
|
||||||
err = app.LoadACLPolicy(
|
acl := []byte(`
|
||||||
"./tests/acls/acl_policy_basic_user_as_user.hujson",
|
{
|
||||||
)
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"testuser",
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err = app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
machines, err := app.ListMachines()
|
machines, err := app.ListMachines()
|
||||||
|
@ -538,7 +807,33 @@ func (s *Suite) TestPortGroup(c *check.C) {
|
||||||
}
|
}
|
||||||
app.db.Save(&machine)
|
app.db.Save(&machine)
|
||||||
|
|
||||||
err = app.LoadACLPolicy("./tests/acls/acl_policy_basic_groups.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"groups": {
|
||||||
|
"group:example": [
|
||||||
|
"testuser",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
"hosts": {
|
||||||
|
"host-1": "100.100.100.100",
|
||||||
|
"subnet-1": "100.100.101.100/24",
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"action": "accept",
|
||||||
|
"src": [
|
||||||
|
"group:example",
|
||||||
|
],
|
||||||
|
"dst": [
|
||||||
|
"host-1:*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
err = app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
machines, err := app.ListMachines()
|
machines, err := app.ListMachines()
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
||||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||||
|
"github.com/juanfont/headscale"
|
||||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
zerolog "github.com/philip-bui/grpc-zerolog"
|
zerolog "github.com/philip-bui/grpc-zerolog"
|
||||||
|
@ -507,8 +508,10 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *mux.Router {
|
||||||
router.HandleFunc("/windows", h.WindowsConfigMessage).Methods(http.MethodGet)
|
router.HandleFunc("/windows", h.WindowsConfigMessage).Methods(http.MethodGet)
|
||||||
router.HandleFunc("/windows/tailscale.reg", h.WindowsRegConfig).
|
router.HandleFunc("/windows/tailscale.reg", h.WindowsRegConfig).
|
||||||
Methods(http.MethodGet)
|
Methods(http.MethodGet)
|
||||||
router.HandleFunc("/swagger", SwaggerUI).Methods(http.MethodGet)
|
|
||||||
router.HandleFunc("/swagger/v1/openapiv2.json", SwaggerAPIv1).
|
// TODO(kristoffer): move swagger into a package
|
||||||
|
router.HandleFunc("/swagger", headscale.SwaggerUI).Methods(http.MethodGet)
|
||||||
|
router.HandleFunc("/swagger/v1/openapiv2.json", headscale.SwaggerAPIv1).
|
||||||
Methods(http.MethodGet)
|
Methods(http.MethodGet)
|
||||||
|
|
||||||
if h.cfg.DERP.ServerEnabled {
|
if h.cfg.DERP.ServerEnabled {
|
||||||
|
@ -758,7 +761,7 @@ func (h *Headscale) Serve() error {
|
||||||
|
|
||||||
if h.cfg.ACL.PolicyPath != "" {
|
if h.cfg.ACL.PolicyPath != "" {
|
||||||
aclPath := AbsolutePathFromConfigPath(h.cfg.ACL.PolicyPath)
|
aclPath := AbsolutePathFromConfigPath(h.cfg.ACL.PolicyPath)
|
||||||
err := h.LoadACLPolicy(aclPath)
|
err := h.LoadACLPolicyFromPath(aclPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Failed to reload ACL policy")
|
log.Error().Err(err).Msg("Failed to reload ACL policy")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1212,7 +1212,31 @@ func TestHeadscale_generateGivenName(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestAutoApproveRoutes(c *check.C) {
|
func (s *Suite) TestAutoApproveRoutes(c *check.C) {
|
||||||
err := app.LoadACLPolicy("./tests/acls/acl_policy_autoapprovers.hujson")
|
acl := []byte(`
|
||||||
|
{
|
||||||
|
"tagOwners": {
|
||||||
|
"tag:exit": ["test"],
|
||||||
|
},
|
||||||
|
|
||||||
|
"groups": {
|
||||||
|
"group:test": ["test"]
|
||||||
|
},
|
||||||
|
|
||||||
|
"acls": [
|
||||||
|
{"action": "accept", "users": ["*"], "ports": ["*:*"]},
|
||||||
|
],
|
||||||
|
|
||||||
|
"autoApprovers": {
|
||||||
|
"exitNode": ["tag:exit"],
|
||||||
|
"routes": {
|
||||||
|
"10.10.0.0/16": ["group:test"],
|
||||||
|
"10.11.0.0/16": ["test"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := app.LoadACLPolicyFromBytes(acl, "hujson")
|
||||||
c.Assert(err, check.IsNil)
|
c.Assert(err, check.IsNil)
|
||||||
|
|
||||||
user, err := app.CreateUser("test")
|
user, err := app.CreateUser("test")
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
{
|
|
||||||
// Declare static groups of users beyond those in the identity service.
|
|
||||||
"groups": {
|
|
||||||
"group:example": [
|
|
||||||
"user1@example.com",
|
|
||||||
"user2@example.com",
|
|
||||||
],
|
|
||||||
"group:example2": [
|
|
||||||
"user1@example.com",
|
|
||||||
"user2@example.com",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Declare hostname aliases to use in place of IP addresses or subnets.
|
|
||||||
"hosts": {
|
|
||||||
"example-host-1": "100.100.100.100",
|
|
||||||
"example-host-2": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
// Define who is allowed to use which tags.
|
|
||||||
"tagOwners": {
|
|
||||||
// Everyone in the montreal-admins or global-admins group are
|
|
||||||
// allowed to tag servers as montreal-webserver.
|
|
||||||
"tag:montreal-webserver": [
|
|
||||||
"group:example",
|
|
||||||
],
|
|
||||||
// Only a few admins are allowed to create API servers.
|
|
||||||
"tag:production": [
|
|
||||||
"group:example",
|
|
||||||
"president@example.com",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Access control lists.
|
|
||||||
"acls": [
|
|
||||||
// Engineering users, plus the president, can access port 22 (ssh)
|
|
||||||
// and port 3389 (remote desktop protocol) on all servers, and all
|
|
||||||
// ports on git-server or ci-server.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:example2",
|
|
||||||
"192.168.1.0/24"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"*:22,3389",
|
|
||||||
"git-server:*",
|
|
||||||
"ci-server:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow engineer users to access any port on a device tagged with
|
|
||||||
// tag:production.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:example"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:production:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow servers in the my-subnet host and 192.168.1.0/24 to access hosts
|
|
||||||
// on both networks.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"example-host-2",
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"example-host-1:*",
|
|
||||||
"192.168.1.0/24:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow every user of your network to access anything on the network.
|
|
||||||
// Comment out this section if you want to define specific ACL
|
|
||||||
// restrictions above.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"*:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// All users in Montreal are allowed to access the Montreal web
|
|
||||||
// servers.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"example-host-1"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:montreal-webserver:80,443"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Montreal web servers are allowed to make outgoing connections to
|
|
||||||
// the API servers, but only on https port 443.
|
|
||||||
// In contrast, this doesn't grant API servers the right to initiate
|
|
||||||
// any connections.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"tag:montreal-webserver"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:api-server:443"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// Declare tests to check functionality of ACL rules
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"src": "user1@example.com",
|
|
||||||
"accept": [
|
|
||||||
"example-host-1:22",
|
|
||||||
"example-host-2:80"
|
|
||||||
],
|
|
||||||
"deny": [
|
|
||||||
"exapmle-host-2:100"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "user2@example.com",
|
|
||||||
"accept": [
|
|
||||||
"100.60.3.4:22"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// This ACL validates autoApprovers support for
|
|
||||||
// exit nodes and advertised routes
|
|
||||||
|
|
||||||
{
|
|
||||||
"tagOwners": {
|
|
||||||
"tag:exit": ["test"],
|
|
||||||
},
|
|
||||||
|
|
||||||
"groups": {
|
|
||||||
"group:test": ["test"]
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{"action": "accept", "users": ["*"], "ports": ["*:*"]},
|
|
||||||
],
|
|
||||||
|
|
||||||
"autoApprovers": {
|
|
||||||
"exitNode": ["tag:exit"],
|
|
||||||
"routes": {
|
|
||||||
"10.10.0.0/16": ["group:test"],
|
|
||||||
"10.11.0.0/16": ["test"],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// This ACL is a very basic example to validate the
|
|
||||||
// expansion of hosts
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"subnet-1",
|
|
||||||
"192.168.1.0/24"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"*:22,3389",
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// This ACL is used to test group expansion
|
|
||||||
|
|
||||||
{
|
|
||||||
"groups": {
|
|
||||||
"group:example": [
|
|
||||||
"testuser",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:example",
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// This ACL is used to test wildcards
|
|
||||||
|
|
||||||
{
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"Action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*",
|
|
||||||
],
|
|
||||||
"proto": "tcp",
|
|
||||||
"dst": [
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*",
|
|
||||||
],
|
|
||||||
"proto": "udp",
|
|
||||||
"dst": [
|
|
||||||
"host-1:53",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*",
|
|
||||||
],
|
|
||||||
"proto": "icmp",
|
|
||||||
"dst": [
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// This ACL is used to test the port range expansion
|
|
||||||
|
|
||||||
{
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"subnet-1",
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"host-1:5400-5500",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// This ACL is used to test namespace expansion
|
|
||||||
|
|
||||||
{
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"testuser",
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
// This ACL is used to test wildcards
|
|
||||||
|
|
||||||
{
|
|
||||||
"hosts": {
|
|
||||||
"host-1": "100.100.100.100",
|
|
||||||
"subnet-1": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
|
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"Action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*",
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"host-1:*",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
---
|
|
||||||
hosts:
|
|
||||||
host-1: 100.100.100.100/32
|
|
||||||
subnet-1: 100.100.101.100/24
|
|
||||||
acls:
|
|
||||||
- action: accept
|
|
||||||
src:
|
|
||||||
- "*"
|
|
||||||
dst:
|
|
||||||
- host-1:*
|
|
|
@ -1,125 +0,0 @@
|
||||||
{
|
|
||||||
// Declare static groups of users beyond those in the identity service.
|
|
||||||
"groups": {
|
|
||||||
"group:example": [
|
|
||||||
"user1@example.com",
|
|
||||||
"user2@example.com",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Declare hostname aliases to use in place of IP addresses or subnets.
|
|
||||||
"hosts": {
|
|
||||||
"example-host-1": "100.100.100.100",
|
|
||||||
"example-host-2": "100.100.101.100/24",
|
|
||||||
},
|
|
||||||
// Define who is allowed to use which tags.
|
|
||||||
"tagOwners": {
|
|
||||||
// Everyone in the montreal-admins or global-admins group are
|
|
||||||
// allowed to tag servers as montreal-webserver.
|
|
||||||
"tag:montreal-webserver": [
|
|
||||||
"group:montreal-admins",
|
|
||||||
"group:global-admins",
|
|
||||||
],
|
|
||||||
// Only a few admins are allowed to create API servers.
|
|
||||||
"tag:api-server": [
|
|
||||||
"group:global-admins",
|
|
||||||
"example-host-1",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Access control lists.
|
|
||||||
"acls": [
|
|
||||||
// Engineering users, plus the president, can access port 22 (ssh)
|
|
||||||
// and port 3389 (remote desktop protocol) on all servers, and all
|
|
||||||
// ports on git-server or ci-server.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:engineering",
|
|
||||||
"president@example.com"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"*:22,3389",
|
|
||||||
"git-server:*",
|
|
||||||
"ci-server:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow engineer users to access any port on a device tagged with
|
|
||||||
// tag:production.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:engineers"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:production:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow servers in the my-subnet host and 192.168.1.0/24 to access hosts
|
|
||||||
// on both networks.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"my-subnet",
|
|
||||||
"192.168.1.0/24"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"my-subnet:*",
|
|
||||||
"192.168.1.0/24:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Allow every user of your network to access anything on the network.
|
|
||||||
// Comment out this section if you want to define specific ACL
|
|
||||||
// restrictions above.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"*:*"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// All users in Montreal are allowed to access the Montreal web
|
|
||||||
// servers.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"group:montreal-users"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:montreal-webserver:80,443"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
// Montreal web servers are allowed to make outgoing connections to
|
|
||||||
// the API servers, but only on https port 443.
|
|
||||||
// In contrast, this doesn't grant API servers the right to initiate
|
|
||||||
// any connections.
|
|
||||||
{
|
|
||||||
"action": "accept",
|
|
||||||
"src": [
|
|
||||||
"tag:montreal-webserver"
|
|
||||||
],
|
|
||||||
"dst": [
|
|
||||||
"tag:api-server:443"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
// Declare tests to check functionality of ACL rules
|
|
||||||
"tests": [
|
|
||||||
{
|
|
||||||
"src": "user1@example.com",
|
|
||||||
"accept": [
|
|
||||||
"example-host-1:22",
|
|
||||||
"example-host-2:80"
|
|
||||||
],
|
|
||||||
"deny": [
|
|
||||||
"exapmle-host-2:100"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "user2@example.com",
|
|
||||||
"accept": [
|
|
||||||
"100.60.3.4:22"
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
{
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"valid_json": true,
|
|
||||||
"but_a_policy_though": false
|
|
||||||
}
|
|
Loading…
Reference in a new issue