mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-29 02:51:29 +02:00
"Create Setup Key as on-off with more than one usage" asserted the old behaviour directly: a key was created, and the response reported a usage limit of 1 rather than the 3 that was asked for. That is the case this change refuses, so the expectation becomes the rejection. The case keeps its place in the table rather than being deleted, since it is the one that says what happens when the request contradicts the key type.
1143 lines
31 KiB
Go
1143 lines
31 KiB
Go
//go:build integration
|
|
|
|
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/netbirdio/netbird/management/server/http/testing/testing_tools"
|
|
"github.com/netbirdio/netbird/management/server/http/testing/testing_tools/channel"
|
|
"github.com/netbirdio/netbird/shared/management/http/api"
|
|
)
|
|
|
|
func Test_SetupKeys_Create(t *testing.T) {
|
|
truePointer := true
|
|
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{
|
|
name: "Regular user",
|
|
userId: testing_tools.TestUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin user",
|
|
userId: testing_tools.TestAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Owner user",
|
|
userId: testing_tools.TestOwnerId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Regular service user",
|
|
userId: testing_tools.TestServiceUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin service user",
|
|
userId: testing_tools.TestServiceAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Blocked user",
|
|
userId: testing_tools.BlockedUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Other user",
|
|
userId: testing_tools.OtherUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Invalid token",
|
|
userId: testing_tools.InvalidToken,
|
|
expectResponse: false,
|
|
},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
expectedResponse *api.SetupKey
|
|
requestBody *api.CreateSetupKeyRequest
|
|
requestType string
|
|
requestPath string
|
|
userId string
|
|
}{
|
|
{
|
|
name: "Create Setup Key",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: nil,
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "reusable",
|
|
UsageLimit: 0,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.NewKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 0,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Create Setup Key with already existing name",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: nil,
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.ExistingKeyName,
|
|
Type: "one-off",
|
|
UsageLimit: 0,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
// The key used to be created anyway, with its usage limit quietly
|
|
// reduced to 1, so the caller was told a key they had not asked for
|
|
// was what they asked for.
|
|
name: "Create Setup Key as one-off with more than one usage",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: nil,
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "one-off",
|
|
UsageLimit: 3,
|
|
},
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
},
|
|
{
|
|
name: "Create Setup Key with expiration in the past",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: nil,
|
|
ExpiresIn: -testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "one-off",
|
|
UsageLimit: 0,
|
|
},
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Create Setup Key with AutoGroups that do exist",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "reusable",
|
|
UsageLimit: 1,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.NewKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Create Setup Key for ephemeral peers",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: []string{},
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "reusable",
|
|
Ephemeral: &truePointer,
|
|
UsageLimit: 1,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{},
|
|
Ephemeral: true,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.NewKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Create Setup Key with AutoGroups that do not exist",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: []string{"someGroupID"},
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "reusable",
|
|
UsageLimit: 0,
|
|
},
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Create Setup Key with nil AutoGroups",
|
|
requestType: http.MethodPost,
|
|
requestPath: "/api/setup-keys",
|
|
requestBody: &api.CreateSetupKeyRequest{
|
|
AutoGroups: nil,
|
|
ExpiresIn: testing_tools.ExpiresIn,
|
|
Name: testing_tools.NewKeyName,
|
|
Type: "reusable",
|
|
UsageLimit: 0,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.NewKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 0,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
for _, user := range users {
|
|
t.Run(user.name+" - "+tc.name, func(t *testing.T) {
|
|
apiHandler, am, done := channel.BuildApiBlackBoxWithDBState(t, "../testdata/setup_keys.sql", nil, true)
|
|
|
|
body, err := json.Marshal(tc.requestBody)
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal request body: %v", err)
|
|
}
|
|
req := testing_tools.BuildRequest(t, body, tc.requestType, tc.requestPath, user.userId)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, tc.expectedStatus, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
got := &api.SetupKey{}
|
|
if err := json.Unmarshal(content, &got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
gotID := got.Id
|
|
validateCreatedKey(t, tc.expectedResponse, got)
|
|
|
|
// Verify setup key exists in DB via gorm
|
|
db := testing_tools.GetDB(t, am.GetStore())
|
|
dbKey := testing_tools.VerifySetupKeyInDB(t, db, gotID)
|
|
assert.Equal(t, tc.expectedResponse.Name, dbKey.Name)
|
|
assert.Equal(t, tc.expectedResponse.Revoked, dbKey.Revoked)
|
|
assert.Equal(t, tc.expectedResponse.UsageLimit, dbKey.UsageLimit)
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout waiting for peerShouldNotReceiveUpdate")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func Test_SetupKeys_Update(t *testing.T) {
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{
|
|
name: "Regular user",
|
|
userId: testing_tools.TestUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin user",
|
|
userId: testing_tools.TestAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Owner user",
|
|
userId: testing_tools.TestOwnerId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Regular service user",
|
|
userId: testing_tools.TestServiceUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin service user",
|
|
userId: testing_tools.TestServiceAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Blocked user",
|
|
userId: testing_tools.BlockedUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Other user",
|
|
userId: testing_tools.OtherUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Invalid token",
|
|
userId: testing_tools.InvalidToken,
|
|
expectResponse: false,
|
|
},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
expectedResponse *api.SetupKey
|
|
requestBody *api.SetupKeyRequest
|
|
requestType string
|
|
requestPath string
|
|
requestId string
|
|
}{
|
|
{
|
|
name: "Add existing Group to existing Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId, testing_tools.NewGroupId},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId, testing_tools.NewGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Add non-existing Group to existing Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId, "someGroupId"},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Add existing Group to non-existing Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: "someId",
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId, testing_tools.NewGroupId},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusNotFound,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Remove existing Group from existing Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Remove existing Group to non-existing Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: "someID",
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusNotFound,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Revoke existing valid Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Revoked: true,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "revoked",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Revoke existing revoked Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.RevokedKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Revoked: true,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "revoked",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 3,
|
|
UsedTimes: 0,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Un-Revoke existing revoked Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.RevokedKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Revoked: false,
|
|
},
|
|
expectedStatus: http.StatusUnprocessableEntity,
|
|
expectedResponse: nil,
|
|
},
|
|
{
|
|
name: "Revoke existing expired Setup Key",
|
|
requestType: http.MethodPut,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.ExpiredKeyId,
|
|
requestBody: &api.SetupKeyRequest{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Revoked: true,
|
|
},
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: true,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "expired",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Now(),
|
|
UsageLimit: 5,
|
|
UsedTimes: 1,
|
|
Valid: false,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
for _, user := range users {
|
|
t.Run(user.name+" - "+tc.name, func(t *testing.T) {
|
|
apiHandler, am, done := channel.BuildApiBlackBoxWithDBState(t, "../testdata/setup_keys.sql", nil, true)
|
|
|
|
body, err := json.Marshal(tc.requestBody)
|
|
if err != nil {
|
|
t.Fatalf("Failed to marshal request body: %v", err)
|
|
}
|
|
|
|
req := testing_tools.BuildRequest(t, body, tc.requestType, strings.Replace(tc.requestPath, "{id}", tc.requestId, 1), user.userId)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, tc.expectedStatus, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
got := &api.SetupKey{}
|
|
if err := json.Unmarshal(content, &got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
gotID := got.Id
|
|
gotRevoked := got.Revoked
|
|
gotUsageLimit := got.UsageLimit
|
|
validateCreatedKey(t, tc.expectedResponse, got)
|
|
|
|
// Verify updated setup key in DB via gorm
|
|
db := testing_tools.GetDB(t, am.GetStore())
|
|
dbKey := testing_tools.VerifySetupKeyInDB(t, db, gotID)
|
|
assert.Equal(t, gotRevoked, dbKey.Revoked)
|
|
assert.Equal(t, gotUsageLimit, dbKey.UsageLimit)
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout waiting for peerShouldNotReceiveUpdate")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func Test_SetupKeys_Get(t *testing.T) {
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{
|
|
name: "Regular user",
|
|
userId: testing_tools.TestUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin user",
|
|
userId: testing_tools.TestAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Owner user",
|
|
userId: testing_tools.TestOwnerId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Regular service user",
|
|
userId: testing_tools.TestServiceUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin service user",
|
|
userId: testing_tools.TestServiceAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Blocked user",
|
|
userId: testing_tools.BlockedUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Other user",
|
|
userId: testing_tools.OtherUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Invalid token",
|
|
userId: testing_tools.InvalidToken,
|
|
expectResponse: false,
|
|
},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
expectedResponse *api.SetupKey
|
|
requestType string
|
|
requestPath string
|
|
requestId string
|
|
}{
|
|
{
|
|
name: "Get existing valid Setup Key",
|
|
requestType: http.MethodGet,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Get existing expired Setup Key",
|
|
requestType: http.MethodGet,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.ExpiredKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: true,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "expired",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 5,
|
|
UsedTimes: 1,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Get existing revoked Setup Key",
|
|
requestType: http.MethodGet,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.RevokedKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "revoked",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 3,
|
|
UsedTimes: 0,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Get non-existing Setup Key",
|
|
requestType: http.MethodGet,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: "someId",
|
|
expectedStatus: http.StatusNotFound,
|
|
expectedResponse: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
for _, user := range users {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
apiHandler, am, done := channel.BuildApiBlackBoxWithDBState(t, "../testdata/setup_keys.sql", nil, true)
|
|
|
|
req := testing_tools.BuildRequest(t, []byte{}, tc.requestType, strings.Replace(tc.requestPath, "{id}", tc.requestId, 1), user.userId)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, tc.expectedStatus, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
got := &api.SetupKey{}
|
|
if err := json.Unmarshal(content, &got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
gotID := got.Id
|
|
gotName := got.Name
|
|
gotRevoked := got.Revoked
|
|
validateCreatedKey(t, tc.expectedResponse, got)
|
|
|
|
// Verify setup key in DB via gorm
|
|
db := testing_tools.GetDB(t, am.GetStore())
|
|
dbKey := testing_tools.VerifySetupKeyInDB(t, db, gotID)
|
|
assert.Equal(t, gotName, dbKey.Name)
|
|
assert.Equal(t, gotRevoked, dbKey.Revoked)
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout waiting for peerShouldNotReceiveUpdate")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func Test_SetupKeys_GetAll(t *testing.T) {
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{
|
|
name: "Regular user",
|
|
userId: testing_tools.TestUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin user",
|
|
userId: testing_tools.TestAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Owner user",
|
|
userId: testing_tools.TestOwnerId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Regular service user",
|
|
userId: testing_tools.TestServiceUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin service user",
|
|
userId: testing_tools.TestServiceAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Blocked user",
|
|
userId: testing_tools.BlockedUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Other user",
|
|
userId: testing_tools.OtherUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Invalid token",
|
|
userId: testing_tools.InvalidToken,
|
|
expectResponse: false,
|
|
},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
expectedResponse []*api.SetupKey
|
|
requestType string
|
|
requestPath string
|
|
}{
|
|
{
|
|
name: "Get all Setup Keys",
|
|
requestType: http.MethodGet,
|
|
requestPath: "/api/setup-keys",
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: []*api.SetupKey{
|
|
{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "revoked",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 3,
|
|
UsedTimes: 0,
|
|
Valid: false,
|
|
},
|
|
{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: true,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "expired",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 5,
|
|
UsedTimes: 1,
|
|
Valid: false,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
for _, user := range users {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
apiHandler, am, done := channel.BuildApiBlackBoxWithDBState(t, "../testdata/setup_keys.sql", nil, true)
|
|
|
|
req := testing_tools.BuildRequest(t, []byte{}, tc.requestType, tc.requestPath, user.userId)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, tc.expectedStatus, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
got := []api.SetupKey{}
|
|
if err := json.Unmarshal(content, &got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
sort.Slice(got, func(i, j int) bool {
|
|
return got[i].UsageLimit < got[j].UsageLimit
|
|
})
|
|
|
|
sort.Slice(tc.expectedResponse, func(i, j int) bool {
|
|
return tc.expectedResponse[i].UsageLimit < tc.expectedResponse[j].UsageLimit
|
|
})
|
|
|
|
db := testing_tools.GetDB(t, am.GetStore())
|
|
for i := range tc.expectedResponse {
|
|
gotID := got[i].Id
|
|
gotName := got[i].Name
|
|
gotRevoked := got[i].Revoked
|
|
validateCreatedKey(t, tc.expectedResponse[i], &got[i])
|
|
|
|
// Verify each setup key in DB via gorm
|
|
dbKey := testing_tools.VerifySetupKeyInDB(t, db, gotID)
|
|
assert.Equal(t, gotName, dbKey.Name)
|
|
assert.Equal(t, gotRevoked, dbKey.Revoked)
|
|
}
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout waiting for peerShouldNotReceiveUpdate")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func Test_SetupKeys_Delete(t *testing.T) {
|
|
users := []struct {
|
|
name string
|
|
userId string
|
|
expectResponse bool
|
|
}{
|
|
{
|
|
name: "Regular user",
|
|
userId: testing_tools.TestUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin user",
|
|
userId: testing_tools.TestAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Owner user",
|
|
userId: testing_tools.TestOwnerId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Regular service user",
|
|
userId: testing_tools.TestServiceUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Admin service user",
|
|
userId: testing_tools.TestServiceAdminId,
|
|
expectResponse: true,
|
|
},
|
|
{
|
|
name: "Blocked user",
|
|
userId: testing_tools.BlockedUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Other user",
|
|
userId: testing_tools.OtherUserId,
|
|
expectResponse: false,
|
|
},
|
|
{
|
|
name: "Invalid token",
|
|
userId: testing_tools.InvalidToken,
|
|
expectResponse: false,
|
|
},
|
|
}
|
|
|
|
tt := []struct {
|
|
name string
|
|
expectedStatus int
|
|
expectedResponse *api.SetupKey
|
|
requestType string
|
|
requestPath string
|
|
requestId string
|
|
}{
|
|
{
|
|
name: "Delete existing valid Setup Key",
|
|
requestType: http.MethodDelete,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.TestKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "valid",
|
|
Type: "one-off",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 1,
|
|
UsedTimes: 0,
|
|
Valid: true,
|
|
},
|
|
},
|
|
{
|
|
name: "Delete existing expired Setup Key",
|
|
requestType: http.MethodDelete,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.ExpiredKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: true,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: false,
|
|
State: "expired",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 5,
|
|
UsedTimes: 1,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Delete existing revoked Setup Key",
|
|
requestType: http.MethodDelete,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: testing_tools.RevokedKeyId,
|
|
expectedStatus: http.StatusOK,
|
|
expectedResponse: &api.SetupKey{
|
|
AutoGroups: []string{testing_tools.TestGroupId},
|
|
Ephemeral: false,
|
|
Expires: time.Time{},
|
|
Id: "",
|
|
Key: "",
|
|
LastUsed: time.Time{},
|
|
Name: testing_tools.ExistingKeyName,
|
|
Revoked: true,
|
|
State: "revoked",
|
|
Type: "reusable",
|
|
UpdatedAt: time.Date(2021, time.August, 19, 20, 46, 20, 0, time.UTC),
|
|
UsageLimit: 3,
|
|
UsedTimes: 0,
|
|
Valid: false,
|
|
},
|
|
},
|
|
{
|
|
name: "Delete non-existing Setup Key",
|
|
requestType: http.MethodDelete,
|
|
requestPath: "/api/setup-keys/{id}",
|
|
requestId: "someId",
|
|
expectedStatus: http.StatusNotFound,
|
|
expectedResponse: nil,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tt {
|
|
for _, user := range users {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
apiHandler, am, done := channel.BuildApiBlackBoxWithDBState(t, "../testdata/setup_keys.sql", nil, true)
|
|
|
|
req := testing_tools.BuildRequest(t, []byte{}, tc.requestType, strings.Replace(tc.requestPath, "{id}", tc.requestId, 1), user.userId)
|
|
|
|
recorder := httptest.NewRecorder()
|
|
|
|
apiHandler.ServeHTTP(recorder, req)
|
|
|
|
content, expectResponse := testing_tools.ReadResponse(t, recorder, tc.expectedStatus, user.expectResponse)
|
|
if !expectResponse {
|
|
return
|
|
}
|
|
got := &api.SetupKey{}
|
|
if err := json.Unmarshal(content, &got); err != nil {
|
|
t.Fatalf("Sent content is not in correct json format; %v", err)
|
|
}
|
|
|
|
// Verify setup key deleted from DB via gorm
|
|
db := testing_tools.GetDB(t, am.GetStore())
|
|
testing_tools.VerifySetupKeyNotInDB(t, db, got.Id)
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(time.Second):
|
|
t.Error("timeout waiting for peerShouldNotReceiveUpdate")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func validateCreatedKey(t *testing.T, expectedKey *api.SetupKey, got *api.SetupKey) {
|
|
t.Helper()
|
|
|
|
if (got.Expires.After(time.Now().Add(-1*time.Minute)) && got.Expires.Before(time.Now().Add(testing_tools.ExpiresIn*time.Second))) ||
|
|
got.Expires.After(time.Date(2300, 01, 01, 0, 0, 0, 0, time.Local)) ||
|
|
got.Expires.Before(time.Date(1950, 01, 01, 0, 0, 0, 0, time.Local)) {
|
|
got.Expires = time.Time{}
|
|
expectedKey.Expires = time.Time{}
|
|
}
|
|
|
|
if got.Id == "" {
|
|
t.Fatalf("Expected key to have an ID")
|
|
}
|
|
got.Id = ""
|
|
|
|
if got.Key == "" {
|
|
t.Fatalf("Expected key to have a key")
|
|
}
|
|
got.Key = ""
|
|
|
|
if got.UpdatedAt.After(time.Now().Add(-1*time.Minute)) && got.UpdatedAt.Before(time.Now().Add(+1*time.Minute)) {
|
|
got.UpdatedAt = time.Time{}
|
|
expectedKey.UpdatedAt = time.Time{}
|
|
}
|
|
|
|
expectedKey.UpdatedAt = expectedKey.UpdatedAt.In(time.UTC)
|
|
got.UpdatedAt = got.UpdatedAt.In(time.UTC)
|
|
|
|
assert.Equal(t, expectedKey, got)
|
|
}
|