mirror of
https://github.com/openziti/ziti.git
synced 2026-09-11 13:29:03 +00:00
290 lines
11 KiB
Go
290 lines
11 KiB
Go
//go:build apitests
|
|
|
|
/*
|
|
Copyright NetFoundry Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package tests
|
|
|
|
import (
|
|
"math"
|
|
"net/http"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/openziti/edge-api/rest_model"
|
|
"github.com/openziti/foundation/v2/errorz"
|
|
"github.com/openziti/ziti/v2/common/eid"
|
|
)
|
|
|
|
func Test_Configs(t *testing.T) {
|
|
ctx := NewTestContext(t)
|
|
defer ctx.Teardown()
|
|
ctx.StartServer()
|
|
ctx.RequireAdminManagementApiLogin()
|
|
|
|
identityRole := eid.New()
|
|
nonAdminUserClientSession := ctx.AdminManagementSession.createUserAndLoginClientApi(false, s(identityRole), nil)
|
|
nonAdminUserManagementSession, err := nonAdminUserClientSession.CloneToManagementApi(ctx)
|
|
ctx.Req.NoError(err)
|
|
|
|
t.Run("create without name should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
config := ctx.newConfig(configType.Id, map[string]interface{}{"port": 22})
|
|
config.Name = ""
|
|
resp := ctx.AdminManagementSession.createEntity(config)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "name")
|
|
})
|
|
|
|
t.Run("create without data should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
config := ctx.newConfig(configType.Id, nil)
|
|
resp := ctx.AdminManagementSession.createEntity(config)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "data")
|
|
})
|
|
|
|
t.Run("create with invalid data should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
|
|
config := &rest_model.ConfigCreate{
|
|
ConfigTypeID: &configType.Id,
|
|
Data: "invalid",
|
|
Name: ToPtr(uuid.NewString()),
|
|
}
|
|
|
|
resp, err := ctx.AdminManagementSession.newAuthenticatedRequest().SetBody(config).Post("/configs")
|
|
ctx.NoError(err)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "data")
|
|
})
|
|
|
|
t.Run("create without type should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
config := ctx.newConfig("", map[string]interface{}{"port": 22})
|
|
resp := ctx.AdminManagementSession.createEntity(config)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "type")
|
|
})
|
|
|
|
t.Run("create with invalid config type should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
config := ctx.newConfig(eid.New(), map[string]interface{}{"port": 22})
|
|
resp := ctx.AdminManagementSession.createEntity(config)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "type")
|
|
})
|
|
|
|
t.Run("create should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
|
|
now := time.Now()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": float64(22)})
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
|
|
entityJson = ctx.AdminManagementSession.validateEntityWithLookup(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
})
|
|
|
|
t.Run("create with nested values should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
now := time.Now()
|
|
config := ctx.newConfig(configType.Id, map[string]interface{}{
|
|
"port": float64(22),
|
|
"hostname": "ssh.globotech.bizniz",
|
|
"enabled": true,
|
|
"nested": map[string]interface{}{
|
|
"neato": false,
|
|
"count": 123.32,
|
|
"scrappy": "appley",
|
|
"nesting weird names ?": map[string]interface{}{
|
|
"valuable": false,
|
|
"questionable": true,
|
|
"Snoodgrass": float64(321321312),
|
|
},
|
|
},
|
|
})
|
|
config.Tags = map[string]interface{}{"org": "na", "deprecated": false}
|
|
config.Id = ctx.AdminManagementSession.requireCreateEntity(config)
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
|
|
entityJson = ctx.AdminManagementSession.validateEntityWithLookup(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
})
|
|
|
|
t.Run("lookup non-existent config as admin should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
ctx.RequireNotFoundError(ctx.AdminManagementSession.query("configs/" + eid.New()))
|
|
})
|
|
|
|
t.Run("lookup config as non-admin should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": 22})
|
|
|
|
ctx.requireUnauthorizedError(nonAdminUserManagementSession.query("configs/" + config.Id))
|
|
})
|
|
|
|
t.Run("update config should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
|
|
now := time.Now()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": float64(22)})
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
createdAt := ctx.validateDateFieldsForCreate(now, entityJson)
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
now = time.Now()
|
|
config.Data = map[string]interface{}{"snafu": false}
|
|
ctx.AdminManagementSession.requireUpdateEntity(config)
|
|
jsonConfig := ctx.AdminManagementSession.validateUpdate(config)
|
|
ctx.validateDateFieldsForUpdate(now, createdAt, jsonConfig)
|
|
})
|
|
|
|
t.Run("patch config should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
now := time.Now()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": float64(22)})
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
createdAt := ctx.validateDateFieldsForCreate(now, entityJson)
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
newName := eid.New()
|
|
config.Name = newName
|
|
config.Data = map[string]interface{}{"foo": "bar"}
|
|
config.Tags = map[string]interface{}{"baz": "bam"}
|
|
ctx.AdminManagementSession.requirePatchEntity(config, "name")
|
|
|
|
config.Data = map[string]interface{}{"port": float64(22)} // data should not have gotten updated
|
|
config.Tags = nil // tags should not be updated
|
|
jsonConfig := ctx.AdminManagementSession.validateUpdate(config)
|
|
ctx.validateDateFieldsForUpdate(now, createdAt, jsonConfig)
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
config.Name = eid.New()
|
|
config.Data = map[string]interface{}{"foo": "bar"}
|
|
config.Tags = map[string]interface{}{"baz": "bam"}
|
|
ctx.AdminManagementSession.requirePatchEntity(config, "data")
|
|
|
|
config.Name = newName // name should not be updated
|
|
config.Tags = nil // tags should not be updated
|
|
ctx.AdminManagementSession.validateUpdate(config)
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
config.Name = eid.New()
|
|
config.Data = map[string]interface{}{"bim": "bam"}
|
|
config.Tags = map[string]interface{}{"enlightened": false}
|
|
ctx.AdminManagementSession.requirePatchEntity(config, "tags")
|
|
|
|
config.Name = newName // name should not be updated
|
|
config.Data = map[string]interface{}{"foo": "bar"} // data should not have gotten updated
|
|
ctx.AdminManagementSession.validateUpdate(config)
|
|
|
|
time.Sleep(time.Millisecond * 10)
|
|
config.Name = eid.New()
|
|
config.Data = map[string]interface{}{"bim": "bom"}
|
|
config.Tags = map[string]interface{}{"enlightened": true}
|
|
ctx.AdminManagementSession.requirePatchEntity(config, "name", "data", "tags")
|
|
ctx.AdminManagementSession.validateUpdate(config)
|
|
})
|
|
|
|
t.Run("update of type config should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": float64(22)})
|
|
ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
|
|
configType2 := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
config.sendType = false
|
|
config.ConfigTypeId = configType2.Id
|
|
ctx.AdminManagementSession.requireUpdateEntity(config)
|
|
|
|
config.ConfigTypeId = configType.Id
|
|
ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
|
|
config.ConfigTypeId = configType2.Id
|
|
ctx.AdminManagementSession.requirePatchEntity(config, "name", "type")
|
|
|
|
config.ConfigTypeId = configType.Id
|
|
ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
})
|
|
|
|
t.Run("delete should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.AdminManagementSession.requireCreateNewConfigType()
|
|
now := time.Now()
|
|
config := ctx.AdminManagementSession.requireCreateNewConfig(configType.Id, map[string]interface{}{"port": float64(22)})
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
|
|
ctx.AdminManagementSession.requireDeleteEntity(config)
|
|
ctx.RequireNotFoundError(ctx.AdminManagementSession.query("configs/" + config.Id))
|
|
})
|
|
|
|
t.Run("create config type with non-object schema should fail", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
ctx.testContextChanged(t)
|
|
resp := ctx.AdminManagementSession.createEntityOfType("config-types", map[string]interface{}{
|
|
"name": eid.New(),
|
|
"schema": "not-object",
|
|
})
|
|
standardErrorJsonResponseTests(resp, errorz.CouldNotValidateCode, http.StatusBadRequest, t)
|
|
})
|
|
|
|
t.Run("create config type with schema should pass", func(t *testing.T) {
|
|
ctx.testContextChanged(t)
|
|
configType := ctx.newConfigType()
|
|
configType.Schema = map[string]interface{}{
|
|
"$id": "http://ziti-edge.netfoundry.io/schemas/test.config.json",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": []interface{}{
|
|
"hostname",
|
|
"port",
|
|
},
|
|
"properties": map[string]interface{}{
|
|
"hostname": map[string]interface{}{
|
|
"type": "string",
|
|
},
|
|
"port": map[string]interface{}{
|
|
"type": "integer",
|
|
"minimum": float64(0),
|
|
"maximum": float64(math.MaxUint16),
|
|
},
|
|
},
|
|
}
|
|
configType.Id = ctx.AdminManagementSession.requireCreateEntity(configType)
|
|
|
|
config := ctx.newConfig(configType.Id, map[string]interface{}{"port": 22})
|
|
resp := ctx.AdminManagementSession.createEntity(config)
|
|
ctx.requireFieldError(resp.StatusCode(), resp.Body(), errorz.CouldNotValidateCode, "(root)")
|
|
|
|
now := time.Now()
|
|
config = ctx.newConfig(configType.Id, map[string]interface{}{
|
|
"hostname": "ssh.globotech.bizniz",
|
|
"port": float64(22),
|
|
})
|
|
config.Id = ctx.AdminManagementSession.requireCreateEntity(config)
|
|
entityJson := ctx.AdminManagementSession.validateEntityWithQuery(config)
|
|
ctx.validateDateFieldsForCreate(now, entityJson)
|
|
})
|
|
}
|