Skip to content

Commit

Permalink
[OGE-4982] Return error code in user gRPC and make ACL endpoint idemp…
Browse files Browse the repository at this point in the history
…otent (#18)
  • Loading branch information
goncalo-rodrigues authored Aug 10, 2023
1 parent 8f601f1 commit 2a68324
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 11 deletions.
22 changes: 19 additions & 3 deletions acls.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,31 @@ func (h *Headscale) generateSSHRules(policy *ACLPolicy) ([]*tailcfg.SSHRule, err
return rules, nil
}

// CreateUserACLPolicy creates an acl policy for the given user.
func (h *Headscale) CreateUserACLPolicy(
// CreateOrUpdateUserACLPolicy creates an acl policy for the given user.
func (h *Headscale) CreateOrUpdateUserACLPolicy(
userID uint,
policy ACLPolicy,
) (*UserACLPolicy, error) {
existingUserPolicy := UserACLPolicy{UserID: userID}
if err := h.db.Where("user_id = ?", userID).First(&existingUserPolicy).Error; err == nil {
// already exists, just update
existingUserPolicy.ACLPolicy = policy
if err := h.db.Save(&existingUserPolicy).Error; err != nil {
log.Error().
Str("func", "CreateOrUpdateUserACLPolicy").
Err(err).
Msg("Could not update user acl policy")

return nil, err
}

return &existingUserPolicy, nil
}

userACLPolicy := UserACLPolicy{ACLPolicy: policy, UserID: userID}
if err := h.db.Create(&userACLPolicy).Error; err != nil {
log.Error().
Str("func", "CreateUserACLPolicy").
Str("func", "CreateOrUpdateUserACLPolicy").
Err(err).
Msg("Could not create user acl policy")

Expand Down
39 changes: 35 additions & 4 deletions acls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (s *Suite) TestValidExpandTagOwnersInSources(c *check.C) {
}
app.db.Save(&machine)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
Groups: Groups{"group:test": []string{"user1", "user2"}},
TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}},
ACLs: []ACL{
Expand All @@ -148,6 +148,37 @@ func (s *Suite) TestValidExpandTagOwnersInSources(c *check.C) {
c.Assert(rules[0].SrcIPs[0], check.Equals, "100.64.0.1")
}

func (s *Suite) TestCreateUserAclPolicy(c *check.C) {
user, err := app.CreateUser("user1")
c.Assert(err, check.IsNil)

_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
Groups: Groups{"group:test": []string{"user1", "user2"}},
TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}},
ACLs: []ACL{
{
Action: "accept",
Sources: []string{"tag:test"},
Destinations: []string{"*:*"},
},
},
})
c.Assert(err, check.IsNil)

_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
Groups: Groups{"group:test": []string{"user1", "user2"}},
TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}},
ACLs: []ACL{
{
Action: "accept",
Sources: []string{"tag:test"},
Destinations: []string{"*:80"},
},
},
})
c.Assert(err, check.IsNil)
}

// this test should validate that we can expand a group in a TagOWner section and
// match properly the IP's of the related hosts. The owner is valid and the tag is also valid.
// the tag is matched in the Destinations section.
Expand Down Expand Up @@ -180,7 +211,7 @@ func (s *Suite) TestValidExpandTagOwnersInDestinations(c *check.C) {
}
app.db.Save(&machine)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
Groups: Groups{"group:test": []string{"user1", "user2"}},
TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}},
ACLs: []ACL{
Expand Down Expand Up @@ -229,7 +260,7 @@ func (s *Suite) TestInvalidTagValidUser(c *check.C) {
}
app.db.Save(&machine)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
TagOwners: TagOwners{"tag:test": []string{"user1"}},
ACLs: []ACL{
{
Expand Down Expand Up @@ -299,7 +330,7 @@ func (s *Suite) TestValidTagInvalidUser(c *check.C) {
}
app.db.Save(&machine)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
TagOwners: TagOwners{"tag:webapp": []string{"user1"}},
ACLs: []ACL{
{
Expand Down
6 changes: 5 additions & 1 deletion grpcv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package headscale

import (
"context"
"errors"
"fmt"
"strings"
"time"
Expand Down Expand Up @@ -44,6 +45,9 @@ func (api headscaleV1APIServer) CreateUser(
) (*v1.CreateUserResponse, error) {
user, err := api.h.CreateUser(request.GetName())
if err != nil {
if errors.Is(err, ErrUserExists) {
return nil, status.Error(codes.AlreadyExists, err.Error())
}
return nil, err
}

Expand Down Expand Up @@ -573,7 +577,7 @@ func (api headscaleV1APIServer) CreateACLPolicy(
return nil, err
}

_, err = api.h.CreateUserACLPolicy(user.ID, aclPolicy)
_, err = api.h.CreateOrUpdateUserACLPolicy(user.ID, aclPolicy)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (s *Suite) TestListPeers(c *check.C) {
user, err := app.CreateUser("test")
c.Assert(err, check.IsNil)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
ACLs: []ACL{
{
Action: "accept",
Expand Down Expand Up @@ -251,7 +251,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) {
}

//
_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
ACLs: []ACL{
{
Action: "accept",
Expand Down Expand Up @@ -1193,7 +1193,7 @@ func (s *Suite) TestAutoApproveRoutes(c *check.C) {
user, err := app.CreateUser("test")
c.Assert(err, check.IsNil)

_, err = app.CreateUserACLPolicy(user.ID, ACLPolicy{
_, err = app.CreateOrUpdateUserACLPolicy(user.ID, ACLPolicy{
Groups: Groups{"group:test": []string{"test"}},
TagOwners: TagOwners{"tag:exit": []string{"test"}},
ACLs: []ACL{
Expand Down

0 comments on commit 2a68324

Please sign in to comment.