diff --git a/acls.go b/acls.go index e7dacdf6..014d1bd9 100644 --- a/acls.go +++ b/acls.go @@ -128,6 +128,67 @@ func (h *Headscale) ListACLPolicy() (*ACLPolicy, error) { return h.aclPolicy, nil } +func ACLProtoToStruct(v *v1.ACLPolicy) (*ACLPolicy, error) { + + // v := req.GetPolicy() + + // groups parsing + vgroups := v.GetGroups() + groups := make(map[string][]string, len(vgroups)) + for n,i := range vgroups { + groups[n] = i.GetGroup() + } + + // hosts parsing + vhosts := v.GetHosts() + hosts := make(map[string]netaddr.IPPrefix, len(vhosts)) + for n,i := range vhosts { + addr, err := netaddr.ParseIPPrefix(i) + if err != nil { + return nil, err + } + hosts[n] = addr + } + + // tag owners parsing + vtagowners := v.GetTagOwners() + tagowners := make(map[string][]string, len(vtagowners)) + for n,i := range vtagowners { + tagowners[n] = i.GetTagOwners() + } + + // ACLs parsing + vacls := (*v).GetAcls() + acls := make([]ACL, len(vacls)) + for n,i := range vacls { + acls[n] = ACL{ + Action: i.GetAction(), + Protocol: i.GetProtocol(), + Sources: i.GetSources(), + Destinations: i.GetDestinations(), + } + } + + // ACL Tests parsing + vtests := v.GetAclTest() + tests := make([]ACLTest, len(vtests)) + for n,i := range vtests { + tests[n] = ACLTest{ + Source: i.GetSource(), + Accept: i.GetAccept(), + Deny: i.GetDeny(), + } + } + + return &ACLPolicy{ + Groups: groups, + Hosts: hosts, + TagOwners: tagowners, + ACLs: acls, + Tests: tests, + }, nil +} + func (policy *ACLPolicy) toProto() *v1.ACLPolicy { protoACLPolicy := v1.ACLPolicy{ Groups: policy.Groups.toProto(), diff --git a/acls_types.go b/acls_types.go index 531cce4e..86649174 100644 --- a/acls_types.go +++ b/acls_types.go @@ -11,19 +11,19 @@ import ( // ACLPolicy represents a Tailscale ACL Policy. type ACLPolicy struct { - Groups Groups `json:"groups" yaml:"groups"` - Hosts Hosts `json:"hosts" yaml:"hosts"` - TagOwners TagOwners `json:"tagOwners" yaml:"tagOwners"` - ACLs []ACL `json:"acls" yaml:"acls"` - Tests []ACLTest `json:"tests" yaml:"tests"` + Groups Groups `json:"groups,omitempty" yaml:"groups,omitempty"` + Hosts Hosts `json:"hosts,omitempty" yaml:"hosts,omitempty"` + TagOwners TagOwners `json:"tagOwners,omitempty" yaml:"tagOwners,omitempty"` + ACLs []ACL `json:"acls,omitempty" yaml:"acls,omitempty"` + Tests []ACLTest `json:"tests,omitempty" yaml:"tests,omitempty"` } // ACL is a basic rule for the ACL Policy. type ACL struct { - Action string `json:"action" yaml:"action"` - Protocol string `json:"proto" yaml:"proto"` - Sources []string `json:"src" yaml:"src"` - Destinations []string `json:"dst" yaml:"dst"` + Action string `json:"action,omitempty" yaml:"action,omitempty"` + Protocol string `json:"proto,omitempty" yaml:"proto,omitempty"` + Sources []string `json:"src,omitempty" yaml:"src,omitempty"` + Destinations []string `json:"dst,omitempty" yaml:"dst,omitempty"` } // Groups references a series of alias in the ACL rules. @@ -37,9 +37,9 @@ type TagOwners map[string][]string // ACLTest is not implemented, but should be use to check if a certain rule is allowed. type ACLTest struct { - Source string `json:"src" yaml:"src"` - Accept []string `json:"accept" yaml:"accept"` - Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"` + Source string `json:"src,omitempty" yaml:"src,omitempty"` + Accept []string `json:"accept,omitempty" yaml:"accept,omitempty"` + Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"` } // UnmarshalJSON allows to parse the Hosts directly into netaddr objects. diff --git a/cmd/headscale/cli/acls.go b/cmd/headscale/cli/acls.go index 25a43d95..b7ed6c56 100644 --- a/cmd/headscale/cli/acls.go +++ b/cmd/headscale/cli/acls.go @@ -3,10 +3,9 @@ package cli import ( "fmt" - // "github.com/juanfont/headscale". + "github.com/juanfont/headscale" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/spf13/cobra" - ) func init() { @@ -40,7 +39,7 @@ var listAclsCmd = &cobra.Command{ if err != nil { ErrorOutput( err, - fmt.Sprintf("Error getting headscale app: %s", err), + fmt.Sprintf("Error getting ACL from server: %s", err), output, ) @@ -57,8 +56,19 @@ var listAclsCmd = &cobra.Command{ return } + policy, err := headscale.ACLProtoToStruct(response.Policy) + if err != nil { + ErrorOutput( + err, + fmt.Sprintf("Error parsing response from server: %s", err), + output, + ) + + return + } + SuccessOutput( - response.Policy, + policy, ``, output, )