mirror of
https://github.com/juanfont/headscale.git
synced 2025-02-08 10:18:01 +09:00
do not allow preauth keys to be deleted if assigned to node (#2396)
* do not allow preauth keys to be deleted if assigned to node Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * update changelog Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
d57a55c024
commit
9bd143852f
5 changed files with 54 additions and 4 deletions
|
@ -20,6 +20,10 @@
|
||||||
[#2350](https://github.com/juanfont/headscale/pull/2350)
|
[#2350](https://github.com/juanfont/headscale/pull/2350)
|
||||||
- Print Tailscale version instead of capability versions for outdated nodes
|
- Print Tailscale version instead of capability versions for outdated nodes
|
||||||
[#2391](https://github.com/juanfont/headscale/pull/2391)
|
[#2391](https://github.com/juanfont/headscale/pull/2391)
|
||||||
|
- Pre auth keys belonging to a user are no longer deleted with the user
|
||||||
|
[#2396](https://github.com/juanfont/headscale/pull/2396)
|
||||||
|
- Pre auth keys that are used by a node can no longer be deleted
|
||||||
|
[#2396](https://github.com/juanfont/headscale/pull/2396)
|
||||||
|
|
||||||
## 0.24.2 (2025-01-30)
|
## 0.24.2 (2025-01-30)
|
||||||
|
|
||||||
|
|
|
@ -582,6 +582,24 @@ COMMIT;
|
||||||
},
|
},
|
||||||
Rollback: func(db *gorm.DB) error { return nil },
|
Rollback: func(db *gorm.DB) error { return nil },
|
||||||
},
|
},
|
||||||
|
// Add back constraint so you cannot delete preauth keys that
|
||||||
|
// is still used by a node.
|
||||||
|
{
|
||||||
|
ID: "202501311657",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
err := tx.AutoMigrate(&types.PreAuthKey{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = tx.AutoMigrate(&types.Node{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Rollback: func(db *gorm.DB) error { return nil },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,13 @@ package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/juanfont/headscale/hscontrol/util"
|
"github.com/juanfont/headscale/hscontrol/util"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"gopkg.in/check.v1"
|
"gopkg.in/check.v1"
|
||||||
"tailscale.com/types/ptr"
|
"tailscale.com/types/ptr"
|
||||||
)
|
)
|
||||||
|
@ -175,3 +178,25 @@ func (*Suite) TestPreAuthKeyACLTags(c *check.C) {
|
||||||
sort.Sort(sort.StringSlice(gotTags))
|
sort.Sort(sort.StringSlice(gotTags))
|
||||||
c.Assert(gotTags, check.DeepEquals, tags)
|
c.Assert(gotTags, check.DeepEquals, tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCannotDeleteAssignedPreAuthKey(t *testing.T) {
|
||||||
|
db, err := newSQLiteTestDB()
|
||||||
|
require.NoError(t, err)
|
||||||
|
user, err := db.CreateUser(types.User{Name: "test8"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
key, err := db.CreatePreAuthKey(types.UserID(user.ID), false, false, nil, []string{"tag:good"})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
node := types.Node{
|
||||||
|
ID: 0,
|
||||||
|
Hostname: "testest",
|
||||||
|
UserID: user.ID,
|
||||||
|
RegisterMethod: util.RegisterMethodAuthKey,
|
||||||
|
AuthKeyID: ptr.To(key.ID),
|
||||||
|
}
|
||||||
|
db.DB.Save(&node)
|
||||||
|
|
||||||
|
err = db.DB.Delete(key).Error
|
||||||
|
require.ErrorContains(t, err, "constraint failed: FOREIGN KEY constraint failed")
|
||||||
|
}
|
||||||
|
|
|
@ -77,9 +77,12 @@ type Node struct {
|
||||||
|
|
||||||
ForcedTags []string `gorm:"serializer:json"`
|
ForcedTags []string `gorm:"serializer:json"`
|
||||||
|
|
||||||
// TODO(kradalby): This seems like irrelevant information?
|
// When a node has been created with a PreAuthKey, we need to
|
||||||
|
// prevent the preauthkey from being deleted before the node.
|
||||||
|
// The preauthkey can define "tags" of the node so we need it
|
||||||
|
// around.
|
||||||
AuthKeyID *uint64 `sql:"DEFAULT:NULL"`
|
AuthKeyID *uint64 `sql:"DEFAULT:NULL"`
|
||||||
AuthKey *PreAuthKey `gorm:"constraint:OnDelete:SET NULL;"`
|
AuthKey *PreAuthKey
|
||||||
|
|
||||||
LastSeen *time.Time
|
LastSeen *time.Time
|
||||||
Expiry *time.Time
|
Expiry *time.Time
|
||||||
|
|
|
@ -14,7 +14,7 @@ type PreAuthKey struct {
|
||||||
ID uint64 `gorm:"primary_key"`
|
ID uint64 `gorm:"primary_key"`
|
||||||
Key string
|
Key string
|
||||||
UserID uint
|
UserID uint
|
||||||
User User `gorm:"constraint:OnDelete:CASCADE;"`
|
User User `gorm:"constraint:OnDelete:SET NULL;"`
|
||||||
Reusable bool
|
Reusable bool
|
||||||
Ephemeral bool `gorm:"default:false"`
|
Ephemeral bool `gorm:"default:false"`
|
||||||
Used bool `gorm:"default:false"`
|
Used bool `gorm:"default:false"`
|
||||||
|
|
Loading…
Reference in a new issue