功能:扩展云管资源运维、账号授权及监控管理
This commit is contained in:
1 parent
eef485306f
commit
6134d49c16
87 files changed
+29498
-126
No files matched your search
@@ -0,0 +1,173 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func policyTemplate(t *testing.T, f *fixture, admin string) string {
|
||||
t.Helper()
|
||||
status, out := f.request("POST", "/terminal-policy-templates", admin, map[string]any{"name": "办公策略", "version": "1.0", "heartbeatInterval": 30, "commandPollInterval": 5, "desktopRefreshInterval": 20}, "")
|
||||
expect(t, 201, status, out)
|
||||
return out["id"].(string)
|
||||
}
|
||||
func policyCap(t *testing.T, f *fixture, device string, protocol int) {
|
||||
t.Helper()
|
||||
status, out := f.request("POST", "/terminal/heartbeat", device, map[string]any{"agentVersion": "qt-platform/0.3.0", "policyProtocol": protocol}, "")
|
||||
expect(t, 200, status, out)
|
||||
}
|
||||
func TestPolicyDispatchActualReceiptsAndHistory(t *testing.T) {
|
||||
f := newFixture(t)
|
||||
admin := f.login("admin")
|
||||
id, device, _ := lifecycleDevice(t, f, admin, "POLICY-001")
|
||||
template := policyTemplate(t, f, admin)
|
||||
status, out := f.request("GET", "/terminal/config", device, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
if out["heartbeatInterval"] != float64(30) || out["configVersion"] != float64(1) || out["deploymentId"] != "" {
|
||||
t.Fatal(out)
|
||||
}
|
||||
body := map[string]any{"templateId": template, "targetMode": "devices", "terminalIds": []string{id}}
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "policy-1")
|
||||
expect(t, 409, status, out)
|
||||
policyCap(t, f, device, 1)
|
||||
// Offline capable devices must queue without pretending to have applied.
|
||||
if _, err := f.db.Exec("UPDATE terminals SET last_seen=now()-interval '5 minutes' WHERE id=$1", id); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
status, first := f.request("POST", "/terminal-policy-deployments", admin, body, "policy-1")
|
||||
expect(t, 202, status, first)
|
||||
deployment := first["id"].(string)
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "policy-1")
|
||||
expect(t, 202, status, out)
|
||||
if out["id"] != deployment {
|
||||
t.Fatal("duplicate dispatch", out)
|
||||
}
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+deployment+"/results", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
row := out["items"].([]any)[0].(map[string]any)
|
||||
if row["status"] != "pending" || row["online"] != false || row["acknowledgedAt"] != nil {
|
||||
t.Fatal(row)
|
||||
}
|
||||
status, out = f.request("GET", "/terminal/config", device, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
if out["commandPollInterval"] != float64(5) || out["desktopRefreshInterval"] != float64(20) || out["deploymentId"] != deployment {
|
||||
t.Fatal(out)
|
||||
}
|
||||
version := out["configVersion"]
|
||||
ack := map[string]any{"deploymentId": deployment, "configVersion": version, "status": "failed", "errorCode": "persist_failed"}
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, ack, "")
|
||||
expect(t, 200, status, out)
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+deployment+"/results", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
row = out["items"].([]any)[0].(map[string]any)
|
||||
if row["status"] != "failed" || row["errorCode"] != "persist_failed" {
|
||||
t.Fatal(row)
|
||||
}
|
||||
delete(ack, "errorCode")
|
||||
ack["status"] = "applied"
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, ack, "")
|
||||
expect(t, 200, status, out)
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, ack, "")
|
||||
expect(t, 200, status, out)
|
||||
// A later deployment gets a new revision, even when restoring the same template.
|
||||
status, second := f.request("POST", "/terminal-policy-deployments", admin, body, "policy-2")
|
||||
expect(t, 202, status, second)
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, ack, "")
|
||||
expect(t, 409, status, out)
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+deployment+"/results", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
row = out["items"].([]any)[0].(map[string]any)
|
||||
if row["status"] != "applied" || row["configVersion"] != version {
|
||||
t.Fatal("history changed", row)
|
||||
}
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+second["id"].(string)+"/results", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
row = out["items"].([]any)[0].(map[string]any)
|
||||
if row["status"] != "pending" || row["configVersion"] == version {
|
||||
t.Fatal(row)
|
||||
}
|
||||
// Resetting identity requires a fresh application and capability report.
|
||||
status, out = f.request("POST", "/terminals/"+id+"/reactivate", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, ack, "")
|
||||
expect(t, 401, status, out)
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "policy-3")
|
||||
expect(t, 409, status, out)
|
||||
}
|
||||
|
||||
func TestPolicyValidationRBACAndGroupSnapshot(t *testing.T) {
|
||||
f := newFixture(t)
|
||||
admin := f.login("admin")
|
||||
viewer := f.login("viewer")
|
||||
operator := f.login("operator")
|
||||
template := policyTemplate(t, f, admin)
|
||||
valid := map[string]any{"name": "办公策略", "version": "1.0", "heartbeatInterval": 30, "commandPollInterval": 5, "desktopRefreshInterval": 20}
|
||||
status, out := f.request("POST", "/terminal-policy-templates", admin, valid, "")
|
||||
expect(t, 409, status, out)
|
||||
for _, field := range []string{"heartbeatInterval", "commandPollInterval", "desktopRefreshInterval"} {
|
||||
in := map[string]any{}
|
||||
for k, v := range valid {
|
||||
in[k] = v
|
||||
}
|
||||
in["version"] = "invalid-" + field
|
||||
in[field] = 0
|
||||
status, out = f.request("POST", "/terminal-policy-templates", admin, in, "")
|
||||
expect(t, 400, status, out)
|
||||
}
|
||||
id, device, _ := lifecycleDevice(t, f, admin, "POLICY-GROUP-001")
|
||||
policyCap(t, f, device, 1)
|
||||
body := map[string]any{"templateId": template, "targetMode": "group", "group": "原分组"}
|
||||
for _, role := range []string{viewer, operator} {
|
||||
status, out = f.request("POST", "/terminal-policy-templates", role, valid, "")
|
||||
expect(t, 403, status, out)
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", role, body, "rbac-policy")
|
||||
expect(t, 403, status, out)
|
||||
for _, path := range []string{"/terminal-policy-templates", "/terminal-policy-states", "/terminal-policy-deployments"} {
|
||||
status, out = f.request("GET", path, role, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
}
|
||||
}
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "")
|
||||
expect(t, 400, status, out)
|
||||
status, first := f.request("POST", "/terminal-policy-deployments", admin, body, "group-1")
|
||||
expect(t, 202, status, first)
|
||||
_, late, _ := lifecycleDevice(t, f, admin, "POLICY-GROUP-002")
|
||||
policyCap(t, f, late, 1)
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+first["id"].(string)+"/results", viewer, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
if len(out["items"].([]any)) != 1 {
|
||||
t.Fatal("group membership retroactively changed", out)
|
||||
}
|
||||
body["group"] = "不存在"
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "group-1")
|
||||
expect(t, 409, status, out)
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "empty")
|
||||
expect(t, 400, status, out)
|
||||
for i, bad := range []map[string]any{
|
||||
{"templateId": template, "targetMode": "devices", "terminalIds": []string{id, "missing"}},
|
||||
{"templateId": template, "targetMode": "devices", "terminalIds": []string{id}, "group": "原分组"},
|
||||
{"templateId": template, "targetMode": "group", "group": "原分组", "terminalIds": []string{id}},
|
||||
} {
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, bad, fmt.Sprint("invalid", i))
|
||||
expect(t, 400, status, out)
|
||||
}
|
||||
// Downgraded clients explicitly revoke their capability on the next heartbeat.
|
||||
policyCap(t, f, late, 0)
|
||||
body["group"] = "原分组"
|
||||
status, out = f.request("POST", "/terminal-policy-deployments", admin, body, "unsupported")
|
||||
expect(t, 409, status, out)
|
||||
var revision int
|
||||
if err := f.db.Get(&revision, "SELECT config_version FROM terminals WHERE id=$1", id); err != nil || revision != 2 {
|
||||
t.Fatal("partial group dispatch", revision, err)
|
||||
}
|
||||
status, out = f.request("POST", "/terminal/config/ack", device, map[string]any{"deploymentId": first["id"], "configVersion": 2, "status": "failed", "errorCode": "token=secret"}, "")
|
||||
expect(t, 400, status, out)
|
||||
// Replacing an unapplied configuration preserves that outcome as superseded.
|
||||
status, second := f.request("POST", "/terminal-policy-deployments", admin, map[string]any{"templateId": template, "targetMode": "devices", "terminalIds": []string{id}}, "replace")
|
||||
expect(t, 202, status, second)
|
||||
status, out = f.request("GET", "/terminal-policy-deployments/"+first["id"].(string)+"/results", admin, nil, "")
|
||||
expect(t, 200, status, out)
|
||||
if out["items"].([]any)[0].(map[string]any)["status"] != "superseded" {
|
||||
t.Fatal(out)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user