policy/v2, servertest: add validation matrix and grant shape captures

SaaS answers for sshTests sources, tests semantics, failure reports,
duplicate destinations, empty and allow-all policies, and refusals.
ACL and SSH compat checks are keyed per check; differences listed.
This commit is contained in:
Kristoffer Dalby committed 2026-11-02 16:09:00 +01:00
1 parent c69c47409a
commit 389f0e137d
53 files changed
+223215 -220

No files matched your search

@@ -38,7 +38,7 @@ import (
// knownPolicyTesterDivergences lists checks where headscale's evaluator
// differs from Tailscale SaaS, keyed <test_id>/<check>.
var knownPolicyTesterDivergences = map[string]string{ //nolint:gosec // strings here are human-readable notes, not credentials
"policytest-accept-fail-autogroup-tagged-src-tag-dst/breakdown": "TEST_SRC_SHAPE: SaaS reports autogroup:tagged as an unknown tests source; headscale evaluates it",
"policytest-accept-fail-autogroup-tagged-src-tag-dst/breakdown": "TEST_SRC_SHAPE: SaaS refuses autogroup:tagged as a tests source as an unknown user or host; headscale evaluates it",
"policytest-accept-fail-proto-icmp-not-allowed/breakdown": testEntryErrors,
"policytest-proto-icmp/breakdown": testEntryErrors,
@@ -46,11 +46,21 @@ var knownPolicyTesterDivergences = map[string]string{ //nolint:gosec // strings
"policytest-dst-unknown-group/breakdown": testUnknownAlias,
"policytest-src-unknown-group/breakdown": testUnknownAlias,
"policytest-src-unknown-user-email/breakdown": testUnknownAlias,
"policytest-src-cidr-accept/verdict": testSrcShape,
"policytest-src-cidr-deny/breakdown": testSrcShape,
"policytest-src-wildcard-accept/breakdown": testSrcShape,
"policytest-src-wildcard-deny/verdict": testSrcShape,
"policytest-dst-multinode-partial-accept/verdict": "TEST_DST_EVERY_NODE: SaaS accepts only when every node of the dst alias is reached; headscale when one is",
"policytest-report-both-blocks/label": sshTestNodeLabel,
}
const (
testEntryErrors = "TEST_ENTRY_ERRORS: SaaS reports the first shape error of a tests entry, headscale every one"
testUnknownAlias = "TEST_UNKNOWN_ALIAS: SaaS reports a test naming an unknown user or group as not reached, headscale as an evaluation error"
testSrcShape = "TEST_SRC_SHAPE: SaaS refuses a CIDR or \"*\" as a tests source as an unknown user or host; headscale evaluates it"
)
// TestPolicyTesterCompat replays every capture under
+28 -1
View File
@@ -23,9 +23,36 @@ var knownSSHTesterDivergences = map[string]string{
"sshtest-mixed-acls-tcp22-allow-no-ssh-rule/label": sshTestNodeLabel,
"sshtest-user-localpart-domain-mismatch/label": sshTestNodeLabel,
"sshtest-user-nonroot-blocks-root/label": sshTestNodeLabel,
"sshtest-fail-label-host-alias/label": sshTestNodeLabel,
"sshtest-fail-label-ip-dst/label": sshTestNodeLabel,
"sshtest-fail-label-same-node-twice/label": sshTestNodeLabel,
"sshtest-fail-label-user-dst/label": sshTestNodeLabel,
"sshtest-repeated-names/label": sshTestNodeLabel,
"sshtest-report-multi/label": sshTestNodeLabel,
"sshtest-src-unassigned-ip-accept/label": sshTestNodeLabel,
"sshtest-src-cidr24-deny/message": sshTestSrcRange,
"sshtest-src-cidr31-empty-accept/message": sshTestSrcRange,
"sshtest-src-cidr31-empty-deny/verdict": sshTestSrcRange,
"sshtest-src-cidr31-hole-accept/message": sshTestSrcRange,
"sshtest-src-cidr31-members-accept/verdict": sshTestSrcRange,
"sshtest-src-hosts-cidr-deny/verdict": sshTestSrcRange,
"sshtest-fail-label-autogroup-member/message": sshTestDstMember,
"sshtest-check-reason-mixed-alias/message": sshTestDstMember,
"sshtest-fail-label-same-node-twice/breakdown": "SSHTEST_PER_ALIAS: SaaS reports each dst alias, also two naming one node; headscale checks each node once",
"sshtest-fail-label-ip-no-device/breakdown": sshTestNoDevice,
"sshtest-report-multi/breakdown": "SSHTEST_PER_ALIAS+SSHTEST_NO_DEVICE: SaaS reports one line per dst alias and a deviceless alias as not reached; headscale one per node and an error",
"sshtest-src-unassigned-ip-accept/breakdown": "SSHTEST_SRC_LABEL: SaaS labels a single-address source as written, headscale as a /32 prefix",
}
const sshTestNodeLabel = "SSHTEST_NODE_LABEL: headscale names each failing dst node by hostname; SaaS names the dst as written"
const (
sshTestNodeLabel = "SSHTEST_NODE_LABEL: headscale names each failing dst node by hostname; SaaS names the dst as written"
sshTestSrcRange = "SSHTEST_SRC_RANGE: SaaS refuses a CIDR, or a host alias holding one, as an sshTests source when parsing; headscale evaluates it"
sshTestDstMember = "SSHTEST_DST_MEMBER: SaaS refuses autogroup:member as an sshTests destination when parsing; headscale evaluates it"
sshTestNoDevice = "SSHTEST_NO_DEVICE: SaaS reports a dst that selects no device as not reached; headscale as an error"
)
func TestSSHTesterCompat(t *testing.T) {
t.Parallel()
@@ -201,6 +201,47 @@ func loadACLTestFile(t *testing.T, path string) *testcapture.Capture {
return c
}
// aclSkipReasons lists checks where headscale differs from SaaS, keyed
// <test_id>[/<node>]/<check>.
var aclSkipReasons = map[string]string{
"acl-err10/refused": routeHostBits,
"acl-err11/refused": routeHostBits,
"acl-tagowner-undefined-nested/message": tagOwnerUndefinedText,
"acl-tagowner-undefined-nested-deep/message": tagOwnerUndefinedText,
"acl-n01/beedrill/filter": allowAllForm,
"acl-n01/bulbasaur/filter": allowAllForm,
"acl-n01/charmander/filter": allowAllForm,
"acl-n01/ivysaur/filter": allowAllForm,
"acl-n01/kakuna/filter": allowAllForm,
"acl-n01/squirtle/filter": allowAllForm,
"acl-n01/venusaur/filter": allowAllForm,
"acl-n01/weedle/filter": allowAllForm,
"acl-dup-src-dst/beedrill/filter": aclDstDedupe,
"acl-dup-src-dst/bulbasaur/filter": aclDstDedupe,
"acl-dup-src-dst/charmander/filter": aclDstDedupe,
"acl-dup-src-dst/ivysaur/filter": aclDstDedupe,
"acl-dup-src-dst/kakuna/filter": aclDstDedupe,
"acl-dup-src-dst/squirtle/filter": aclDstDedupe,
"acl-dup-src-dst/venusaur/filter": aclDstDedupe,
"acl-dup-src-dst/weedle/filter": aclDstDedupe,
"acl-dxp-dup-ports/beedrill/filter": aclDstDedupe,
"acl-self-plus-dsts/kakuna/filter": srcAddressForm,
"acl-self-plus-dsts/beedrill/filter": "FILTER_ADDRESS_FORM+ACL_DST_DEDUPE: sources listed one by one, a repeated destination written once",
"acl-self-plus-dsts/bulbasaur/filter": "FILTER_ADDRESS_FORM+SELF_DST_REPEAT: sources listed one by one, the autogroup:self destination written once per source alias",
}
const (
routeHostBits = "ROUTE_HOST_BITS: SaaS refuses an autoApprovers route with host bits; headscale accepts it"
tagOwnerUndefinedText = "TAG_OWNER_UNDEFINED_TEXT: SaaS names the owning tag and its undefined owner in one line; headscale words it differently"
allowAllForm = "ALLOW_ALL_FORM: SaaS writes the allow-all default's sources as the tailnet ranges, headscale as \"*\""
aclDstDedupe = "ACL_DST_DEDUPE: SaaS writes a destination repeated within one ACL once, headscale once per mention"
srcAddressForm = "FILTER_ADDRESS_FORM: SaaS lists contiguous source addresses one by one, headscale as a range"
)
// TestACLCompat is a data-driven test that loads all ACL-*.json test files
// and compares headscale's ACL engine output against the expected behavior.
//
@@ -254,64 +295,40 @@ func testACLError(t *testing.T, tf *testcapture.Capture) {
policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy)
pol, err := unmarshalPolicy(policyJSON)
if err != nil {
// Parse-time error.
if tf.Input.APIResponseBody != nil {
wantMsg := tf.Input.APIResponseBody.Message
if wantMsg != "" {
assertACLErrorContains(
t, err, wantMsg, tf.TestID,
)
}
if err == nil {
err = pol.validate()
}
key := tf.TestID + "/"
compatCheck(t, aclSkipReasons, key+"refused", func() string {
if err == nil {
return "SaaS refused; the policy parsed and validated"
}
return ""
})
if err == nil {
compatChecksNotRun(t, aclSkipReasons, key+"message")
return
}
err = pol.validate()
if err != nil {
if tf.Input.APIResponseBody != nil {
wantMsg := tf.Input.APIResponseBody.Message
if wantMsg != "" {
assertACLErrorContains(
t, err, wantMsg, tf.TestID,
)
}
// An emitter that differs is aligned, not papered over with a
// translation table.
var want string
if tf.Input.APIResponseBody != nil {
want = tf.Input.APIResponseBody.Message
}
compatCheck(t, aclSkipReasons, key+"message", func() string {
if strings.Contains(err.Error(), want) {
return ""
}
return
}
t.Errorf(
"%s: expected error but policy parsed and validated successfully",
tf.TestID,
)
}
// assertACLErrorContains requires that headscale's error contains the
// Tailscale SaaS error message exactly. Divergence means an emitter
// needs to be aligned, not papered over with a translation table.
func assertACLErrorContains(
t *testing.T,
err error,
wantMsg string,
testID string,
) {
t.Helper()
errStr := err.Error()
if strings.Contains(errStr, wantMsg) {
return
}
t.Errorf(
"%s: error message mismatch\n"+
" want (tailscale): %q\n"+
" got (headscale): %q",
testID,
wantMsg,
errStr,
)
return fmt.Sprintf("want (tailscale): %q\ngot (headscale): %q", want, err.Error())
})
}
// testACLSuccess verifies that a valid policy produces the expected
@@ -348,6 +365,8 @@ func testACLSuccess(
pm, err := NewPolicyManager(policyJSON, users, nodes.ViewSlice())
require.NoError(t, err, "%s: policy manager should load the policy", tf.TestID)
opts := append(cmpOptions(), cmpopts.EquateEmpty())
for nodeName, capture := range tf.Captures {
t.Run(nodeName, func(t *testing.T) {
node := findNodeByGivenName(nodes, nodeName)
@@ -360,49 +379,35 @@ func testACLSuccess(
return
}
// Compile headscale filter rules for this node
compiledRules := pol.compileFilterRulesForNode(
users,
node.View(),
nodes.ViewSlice(),
)
gotRules := policyutil.ReduceFilterRules(
node.View(),
compiledRules,
)
wantRules := capture.PacketFilterRules
// Compare
opts := append(
cmpOptions(),
cmpopts.EquateEmpty(),
)
if diff := cmp.Diff(
wantRules,
gotRules,
opts...,
); diff != "" {
t.Errorf(
"%s/%s: filter rules mismatch (-want +got):\n%s",
tf.TestID,
nodeName,
diff,
)
}
compatCheck(t, aclSkipReasons, tf.TestID+"/"+nodeName+"/filter", func() string {
var diffs []string
pmRules, err := pm.FilterForNode(node.View())
require.NoError(t, err)
// Only the manager installs the allow-all default of a
// policy with neither acls nor grants.
if pol.ACLs != nil || pol.Grants != nil {
gotRules := policyutil.ReduceFilterRules(
node.View(),
pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()),
)
if diff := cmp.Diff(wantRules, pmRules, opts...); diff != "" {
t.Errorf(
"%s/%s: policy manager filter rules mismatch (-want +got):\n%s",
tf.TestID,
nodeName,
diff,
)
}
if diff := cmp.Diff(wantRules, gotRules, opts...); diff != "" {
diffs = append(diffs, "filter rules mismatch (-want +got):\n"+diff)
}
}
pmRules, err := pm.FilterForNode(node.View())
if err != nil {
return err.Error()
}
if diff := cmp.Diff(wantRules, pmRules, opts...); diff != "" {
diffs = append(diffs, "policy manager filter rules mismatch (-want +got):\n"+diff)
}
return strings.Join(diffs, "\n")
})
})
}
}
@@ -121,21 +121,30 @@ func TestSSHForwardingDataCompat(t *testing.T) {
}
// sshSkipReasons documents captures the upstream control plane accepts
// but headscale cannot yet represent. Each entry names the feature gap.
// but headscale cannot yet represent, keyed <test_id> for the whole capture
// or <test_id>/<node>/<check>. Each entry names the feature gap.
var sshSkipReasons = map[string]string{
"ssh-b5": "headscale has no passkey authentication; user:*@passkey wildcard unsupported",
"ssh-d10": "headscale has no passkey authentication; user:*@passkey wildcard unsupported",
"ssh-duplicate-rules/beedrill/ssh-rules": sshUIDZero,
"ssh-duplicate-rules/kakuna/ssh-rules": sshUIDZero,
"ssh-equal-src-aliases/beedrill/ssh-rules": sshUIDZero,
}
const sshUIDZero = `SSH_UID_ZERO: SaaS maps login "0" to no local user in every rule; headscale leaves it out`
// sshRejectSkipReasons documents captures the upstream control plane
// rejects for reasons headscale cannot apply. Each entry names the
// feature gap.
// rejects for reasons headscale cannot apply, keyed <test_id> for the whole
// capture or <test_id>/<check>. Each entry names the feature gap.
var sshRejectSkipReasons = map[string]string{
"ssh-b4": "headscale has no associated-tailnet-domains config; user:*@domain / localpart:*@domain are not domain-validated",
"ssh-d1": "headscale has no associated-tailnet-domains config; user:*@domain / localpart:*@domain are not domain-validated",
"ssh-e1": "headscale has no associated-tailnet-domains config; user:*@domain / localpart:*@domain are not domain-validated",
"ssh-e2": "headscale has no associated-tailnet-domains config; user:*@domain / localpart:*@domain are not domain-validated",
"ssh-malformed-user-localpart-multi-glob": "headscale has no associated-tailnet-domains config; user:*@domain / localpart:*@domain are not domain-validated",
"ssh-check-tag-src/refused": "SSH_CHECK_TAG_SRC: SaaS refuses a check rule with a tag source; headscale accepts it",
}
// TestSSHDataCompat loads every ssh-*.hujson capture, parses the policy
@@ -188,33 +197,7 @@ func TestSSHDataCompat(t *testing.T) {
return
}
pm, parseErr := NewPolicyManager(policyJSON, users, nodes.ViewSlice())
var got error
switch {
case parseErr != nil:
got = parseErr
default:
_, setErr := pm.SetPolicy(policyJSON)
got = setErr
}
require.Error(t, got, "tailscale rejected; headscale must reject too")
if tf.Input.APIResponseBody == nil ||
tf.Input.APIResponseBody.Message == "" {
return
}
want := tf.Input.APIResponseBody.Message
if !strings.Contains(got.Error(), want) {
t.Errorf(
"error body mismatch\n tailscale wants: %q\n headscale got: %q",
want,
got.Error(),
)
}
testSSHRefusal(t, tf, users, nodes)
return
}
@@ -243,106 +226,134 @@ func TestSSHDataCompat(t *testing.T) {
require.NotNilf(t, node,
"golden node %s not found in test setup", nodeName)
// Compile headscale SSH policy for this node
gotSSH, err := pol.compileSSHPolicy(
"https://unused",
users,
node.View(),
nodes.ViewSlice(),
)
require.NoError(
t,
err,
"%s/%s: failed to compile SSH policy",
tf.TestID,
nodeName,
)
// Nil and empty SSHPolicy differ on the wire: nil
// keeps the client's previous rules, empty clears
// them. Take presence from the captured netmap.
wantSSH := &tailcfg.SSHPolicy{Rules: capture.SSHRules}
if capture.Netmap != nil && capture.Netmap.SSHPolicy == nil {
wantSSH = nil
}
// Compare headscale output against Tailscale expected.
// EquateEmpty treats nil and empty slices as equal.
// Sort principals within rules (order doesn't matter).
// Do NOT sort rules — order matters (first-match-wins).
//
opts := cmp.Options{
cmpopts.SortSlices(func(a, b *tailcfg.SSHPrincipal) bool {
return a.NodeIP < b.NodeIP
}),
cmpopts.EquateEmpty(),
}
if diff := cmp.Diff(wantSSH, gotSSH, opts...); diff != "" {
t.Errorf(
"%s/%s: SSH policy mismatch (-tailscale +headscale):\n%s",
tf.TestID,
nodeName,
diff,
)
}
pmSSH, err := pm.SSHPolicy("https://unused", node.View())
require.NoError(t, err)
if diff := cmp.Diff(wantSSH, pmSSH, opts...); diff != "" {
t.Errorf(
"%s/%s: policy manager SSH policy mismatch (-tailscale +headscale):\n%s",
tf.TestID,
nodeName,
diff,
)
}
// EquateEmpty hides "rules":null vs "rules":[];
// pin the captured shape separately.
if capture.Netmap != nil && capture.Netmap.SSHPolicy != nil {
for _, got := range []*tailcfg.SSHPolicy{gotSSH, pmSSH} {
if got != nil {
assert.Equalf(t,
capture.Netmap.SSHPolicy.Rules == nil,
got.Rules == nil,
"%s/%s: rules null-vs-[] mismatch", tf.TestID, nodeName,
)
}
}
}
// Separate presence check: the fields ignored by
// the diff above must still be populated on matching
// rules. This catches regressions where headscale
// would silently drop the HoldAndDelegate URL or
// flip Accept to false while we are not looking.
if wantSSH != nil && gotSSH != nil {
for i, wantRule := range wantSSH.Rules {
if i >= len(gotSSH.Rules) {
break
}
gotRule := gotSSH.Rules[i]
if wantRule.Action == nil || gotRule.Action == nil {
continue
}
wantIsCheck := wantRule.Action.HoldAndDelegate != ""
gotIsCheck := gotRule.Action.HoldAndDelegate != ""
assert.Equalf(t, wantIsCheck, gotIsCheck,
"%s/%s rule %d: HoldAndDelegate presence mismatch",
tf.TestID, nodeName, i,
)
}
}
compatCheck(t, sshSkipReasons, tf.TestID+"/"+nodeName+"/ssh-rules", func() string {
return sshRulesMismatch(pol, pm, users, nodes, node, capture)
})
})
}
})
}
}
// testSSHRefusal replays a policy SaaS refused: headscale must refuse it
// too, with the captured message in its error.
func testSSHRefusal(t *testing.T, tf *testcapture.Capture, users types.Users, nodes types.Nodes) {
t.Helper()
policyJSON := []byte(tf.Input.FullPolicy)
pm, err := NewPolicyManager(policyJSON, users, nodes.ViewSlice())
if err == nil {
_, err = pm.SetPolicy(policyJSON)
}
key := tf.TestID + "/"
compatCheck(t, sshRejectSkipReasons, key+"refused", func() string {
if err == nil {
return "tailscale rejected; headscale accepted"
}
return ""
})
if err == nil {
compatChecksNotRun(t, sshRejectSkipReasons, key+"message")
return
}
var want string
if tf.Input.APIResponseBody != nil {
want = tf.Input.APIResponseBody.Message
}
compatCheck(t, sshRejectSkipReasons, key+"message", func() string {
if strings.Contains(err.Error(), want) {
return ""
}
return fmt.Sprintf("tailscale wants: %q\nheadscale got: %q", want, err.Error())
})
}
// sshRulesMismatch compares the SSH policy headscale compiles for node,
// directly and through the manager, with the captured one; "" is a match.
func sshRulesMismatch(
pol *Policy,
pm *PolicyManager,
users types.Users,
nodes types.Nodes,
node *types.Node,
capture testcapture.Node,
) string {
gotSSH, err := pol.compileSSHPolicy("https://unused", users, node.View(), nodes.ViewSlice())
if err != nil {
return fmt.Sprintf("failed to compile SSH policy: %v", err)
}
pmSSH, err := pm.SSHPolicy("https://unused", node.View())
if err != nil {
return fmt.Sprintf("policy manager SSH policy: %v", err)
}
// Nil and empty SSHPolicy differ on the wire: nil keeps the client's
// previous rules, empty clears them. Take presence from the captured
// netmap.
wantSSH := &tailcfg.SSHPolicy{Rules: capture.SSHRules}
if capture.Netmap != nil && capture.Netmap.SSHPolicy == nil {
wantSSH = nil
}
// EquateEmpty treats nil and empty slices as equal. Sort principals
// within rules (order doesn't matter). Do NOT sort rules — order
// matters (first-match-wins).
opts := cmp.Options{
cmpopts.SortSlices(func(a, b *tailcfg.SSHPrincipal) bool {
return a.NodeIP < b.NodeIP
}),
cmpopts.EquateEmpty(),
}
var diffs []string
for name, got := range map[string]*tailcfg.SSHPolicy{"compiled": gotSSH, "policy manager": pmSSH} {
if diff := cmp.Diff(wantSSH, got, opts...); diff != "" {
diffs = append(diffs, fmt.Sprintf("%s SSH policy mismatch (-tailscale +headscale):\n%s", name, diff))
}
// EquateEmpty hides "rules":null vs "rules":[]; pin the captured
// shape separately.
if capture.Netmap != nil && capture.Netmap.SSHPolicy != nil && got != nil &&
(capture.Netmap.SSHPolicy.Rules == nil) != (got.Rules == nil) {
diffs = append(diffs, name+": rules null-vs-[] mismatch")
}
}
// The fields ignored by the diff above must still be populated on
// matching rules, so a dropped HoldAndDelegate URL is caught.
if wantSSH != nil && gotSSH != nil {
for i, wantRule := range wantSSH.Rules {
if i >= len(gotSSH.Rules) {
break
}
gotRule := gotSSH.Rules[i]
if wantRule.Action == nil || gotRule.Action == nil {
continue
}
if (wantRule.Action.HoldAndDelegate != "") != (gotRule.Action.HoldAndDelegate != "") {
diffs = append(diffs, fmt.Sprintf("rule %d: HoldAndDelegate presence mismatch", i))
}
}
}
slices.Sort(diffs)
return strings.Join(diffs, "\n")
}
// sshLocalUser maps sshUser to a local user the way tailssh does for one
// rule: an exact entry wins, then "*"; "" means the rule does not apply.
func sshLocalUser(users map[string]string, sshUser string) string {
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,158 @@
// acl-tagowner-undefined-nested-deep
//
// acl tag owner chain ends in an undefined tag
//
// Steps: 1
// Captured at: 2026-10-17T15:28:34Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "acl-tagowner-undefined-nested-deep",
"description": "acl tag owner chain ends in an undefined tag",
"category": "acl",
"captured_at": "2026-10-17T15:28:34.8172913Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "tagOwners[\"tag:own-x\"]: \"tag:ghost\": does not exist"},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"acl-tagowner-undefined-nested-deep\",\n\t\"category\": \"acl\",\n\t\"description\": \"acl tag owner chain ends in an undefined tag\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:own-x\": [\"tag:ghost\"], \"tag:own-y\": [\"tag:own-x\"]}}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/acl-tagowner-undefined-nested-deep.hujson",
"full_policy": {"tagOwners": {"tag:own-x": ["tag:ghost"], "tag:own-y": ["tag:own-x"]}}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:28:38.252239486Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"tagOwners": {"tag:own-x": ["tag:ghost"], "tag:own-y": ["tag:own-x"]}},
"status": 200,
"response": {"message": "tagOwners[\"tag:own-x\"]: \"tag:ghost\": does not exist"}
}]
}]
}
@@ -0,0 +1,158 @@
// acl-tagowner-undefined-nested
//
// acl tag owner names an undefined tag
//
// Steps: 1
// Captured at: 2026-10-17T15:28:42Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "acl-tagowner-undefined-nested",
"description": "acl tag owner names an undefined tag",
"category": "acl",
"captured_at": "2026-10-17T15:28:42.290026187Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "tagOwners[\"tag:own-x\"]: \"tag:ghost\": does not exist"},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"acl-tagowner-undefined-nested\",\n\t\"category\": \"acl\",\n\t\"description\": \"acl tag owner names an undefined tag\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:own-x\": [\"tag:ghost\"]}}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/acl-tagowner-undefined-nested.hujson",
"full_policy": {"tagOwners": {"tag:own-x": ["tag:ghost"]}}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:28:45.764792824Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"tagOwners": {"tag:own-x": ["tag:ghost"]}},
"status": 200,
"response": {"message": "tagOwners[\"tag:own-x\"]: \"tag:ghost\": does not exist"}
}]
}]
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,172 @@
// policytest-addr-port-pairing
//
// tests addr port pairing
//
// Steps: 1
// Captured at: 2026-10-17T15:33:25Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-addr-port-pairing",
"description": "tests addr port pairing",
"category": "policytest",
"captured_at": "2026-10-17T15:33:25.960291925Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"input": {
"api_response_code": 200,
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"policytest-addr-port-pairing\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests addr port pairing\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"thor@example.org\"],\n\t\t\"dst\": [\"100.64.0.16:22\", \"100.64.0.15:80\"]\n\t}], \"tests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"accept\": [\"100.64.0.16:22\", \"100.64.0.15:80\"],\n\t\t\"deny\": [\"100.64.0.16:80\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-addr-port-pairing.hujson",
"full_policy": {"acls": [{
"action": "accept",
"dst": ["100.64.0.16:22", "100.64.0.15:80"],
"src": ["thor@example.org"]
}], "tests": [{
"accept": ["100.64.0.16:22", "100.64.0.15:80"],
"deny": ["100.64.0.16:80"],
"src": "thor@example.org"
}]}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:33:29.448383136Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"acls": [{
"action": "accept",
"dst": ["100.64.0.16:22", "100.64.0.15:80"],
"src": ["thor@example.org"]
}], "tests": [{
"accept": ["100.64.0.16:22", "100.64.0.15:80"],
"deny": ["100.64.0.16:80"],
"src": "thor@example.org"
}]},
"status": 200,
"response": {}
}]
}]
}
@@ -0,0 +1,178 @@
// policytest-dst-multinode-partial-accept
//
// tests dst multinode partial accept
//
// Steps: 1
// Captured at: 2026-10-17T15:33:33Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-dst-multinode-partial-accept",
"description": "tests dst multinode partial accept",
"category": "policytest",
"captured_at": "2026-10-17T15:33:33.49112159Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[acl test error]: address \"tag:exit:22\" (protocol \"tcp\"): want: Accept, got: Drop"
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-dst-multinode-partial-accept\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests dst multinode partial accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\"tag:exit\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"thor@example.org\"],\n\t\t\t\"dst\": [\"100.64.0.4:22\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"thor@example.org\", \"accept\": [\"tag:exit:22\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-dst-multinode-partial-accept.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["100.64.0.4:22"],
"src": ["thor@example.org"]
}],
"tagOwners": {"tag:exit": ["odin@example.com"]},
"tests": [{"accept": ["tag:exit:22"], "src": "thor@example.org"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:33:36.955324456Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["100.64.0.4:22"],
"src": ["thor@example.org"]
}],
"tagOwners": {"tag:exit": ["odin@example.com"]},
"tests": [{"accept": ["tag:exit:22"], "src": "thor@example.org"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:exit:22\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// policytest-ports-partial-accept
//
// tests ports partial accept
//
// Steps: 1
// Captured at: 2026-10-17T15:33:48Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-ports-partial-accept",
"description": "tests ports partial accept",
"category": "policytest",
"captured_at": "2026-10-17T15:33:48.461755003Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{
"user": "thor@example.org",
"errors": ["[acl test error]: address tag:server:22,80: invalid port \"22,80\""]
}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"policytest-ports-partial-accept\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests ports partial accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\"],\n\t\t\t\"dst\": [\"tag:server:22\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"thor@example.org\", \"accept\": [\"tag:server:22,80\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-ports-partial-accept.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22,80"], "src": "thor@example.org"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:33:52.035935501Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22,80"], "src": "thor@example.org"}]
},
"status": 200,
"response": {"data": [{
"errors": ["[acl test error]: address tag:server:22,80: invalid port \"22,80\""],
"user": "thor@example.org"
}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,188 @@
// policytest-ports-split-across-rules
//
// tests ports split across rules
//
// Steps: 1
// Captured at: 2026-10-17T15:33:56Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-ports-split-across-rules",
"description": "tests ports split across rules",
"category": "policytest",
"captured_at": "2026-10-17T15:33:56.075952561Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{
"user": "thor@example.org",
"errors": ["[acl test error]: address tag:server:22,80: invalid port \"22,80\""]
}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-ports-split-across-rules\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests ports split across rules\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"thor@example.org\"],\n\t\t\t\"dst\": [\"tag:server:22\"]\n\t\t}, {\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"thor@example.org\"],\n\t\t\t\"dst\": [\"tag:server:80\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"thor@example.org\", \"accept\": [\"tag:server:22,80\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-ports-split-across-rules.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["thor@example.org"]
}, {
"action": "accept",
"dst": ["tag:server:80"],
"src": ["thor@example.org"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22,80"], "src": "thor@example.org"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:33:59.535729954Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["thor@example.org"]
}, {
"action": "accept",
"dst": ["tag:server:80"],
"src": ["thor@example.org"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22,80"], "src": "thor@example.org"}]
},
"status": 200,
"response": {"data": [{
"errors": ["[acl test error]: address tag:server:22,80: invalid port \"22,80\""],
"user": "thor@example.org"
}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,176 @@
// policytest-repeated-failing-assertion
//
// tests repeated failing assertion
//
// Steps: 1
// Captured at: 2026-10-17T15:34:03Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-repeated-failing-assertion",
"description": "tests repeated failing assertion",
"category": "policytest",
"captured_at": "2026-10-17T15:34:03.576159335Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop"
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-repeated-failing-assertion\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests repeated failing assertion\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"accept\": [\"tag:server:443\", \"tag:server:443\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-repeated-failing-assertion.hujson",
"full_policy": {"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}], "tagOwners": {"tag:server": ["odin@example.com"]}, "tests": [
{"accept": ["tag:server:443", "tag:server:443"], "src": "thor@example.org"}
]}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:07.066121414Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}], "tagOwners": {"tag:server": ["odin@example.com"]}, "tests": [
{"accept": ["tag:server:443", "tag:server:443"], "src": "thor@example.org"}
]},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,200 @@
// policytest-report-both-blocks
//
// tests and sshTests both failing
//
// Steps: 1
// Captured at: 2026-10-17T15:34:11Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-report-both-blocks",
"description": "tests and sshTests both failing",
"category": "policytest",
"captured_at": "2026-10-17T15:34:11.105265589Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop"
]}, {"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"ubuntu\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"policytest-report-both-blocks\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests and sshTests both failing\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\"],\n\t\t\t\"dst\": [\"tag:server:22\"]\n\t\t}],\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"thor@example.org\", \"accept\": [\"tag:server:80\"]}],\n\t\t\"sshTests\": [{\n\t\t\t\"src\": \"thor@example.org\",\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"accept\": [\"ubuntu\"]\n\t\t}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-report-both-blocks.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member"],
"users": ["root"]
}],
"sshTests": [
{"accept": ["ubuntu"], "dst": ["tag:server"], "src": "thor@example.org"}
],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:80"], "src": "thor@example.org"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:14.577225595Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member"],
"users": ["root"]
}],
"sshTests": [
{"accept": ["ubuntu"], "dst": ["tag:server"], "src": "thor@example.org"}
],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:80"], "src": "thor@example.org"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "thor@example.org"}, {"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"ubuntu\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// policytest-report-hosts-src
//
// tests report hosts src
//
// Steps: 1
// Captured at: 2026-10-17T15:34:18Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-report-hosts-src",
"description": "tests report hosts src",
"category": "policytest",
"captured_at": "2026-10-17T15:34:18.620130265Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "edge", "errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop"
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-report-hosts-src\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests report hosts src\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"hosts\": {\"edge\": \"100.64.0.17\"},\n\t\t\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\"],\n\t\t\t\"dst\": [\"tag:server:22\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"edge\", \"accept\": [\"tag:server:80\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-report-hosts-src.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"hosts": {"edge": "100.64.0.17"},
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:80"], "src": "edge"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:22.457220353Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"hosts": {"edge": "100.64.0.17"},
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:80"], "src": "edge"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "edge"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,204 @@
// policytest-report-multi
//
// tests report multi
//
// Steps: 1
// Captured at: 2026-10-17T15:34:26Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-report-multi",
"description": "tests report multi",
"category": "policytest",
"captured_at": "2026-10-17T15:34:26.502691753Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:prod:22\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Drop, got: Accept"
]}, {"user": "tag:client", "errors": [
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Accept, got: Drop"
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"policytest-report-multi\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests report multi\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:client\": [\"odin@example.com\"],\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [\n\t\t{\n\t\t\t\"src\": \"thor@example.org\",\n\t\t\t\"accept\": [\"tag:server:80\", \"tag:server:443\", \"tag:prod:22\"],\n\t\t\t\"deny\": [\"tag:server:22\"]\n\t\t},\n\t\t{\"src\": \"tag:client\", \"accept\": [\"tag:server:22\"]},\n\t\t{\"src\": \"thor@example.org\", \"accept\": [\"tag:server:22\"]}\n\t]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-report-multi.hujson",
"full_policy": {"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}], "tagOwners": {
"tag:client": ["odin@example.com"],
"tag:prod": ["odin@example.com"],
"tag:server": ["odin@example.com"]
}, "tests": [
{
"accept": ["tag:server:80", "tag:server:443", "tag:prod:22"],
"deny": ["tag:server:22"],
"src": "thor@example.org"
},
{"accept": ["tag:server:22"], "src": "tag:client"},
{"accept": ["tag:server:22"], "src": "thor@example.org"}
]}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:29.974707902Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}], "tagOwners": {
"tag:client": ["odin@example.com"],
"tag:prod": ["odin@example.com"],
"tag:server": ["odin@example.com"]
}, "tests": [
{
"accept": ["tag:server:80", "tag:server:443", "tag:prod:22"],
"deny": ["tag:server:22"],
"src": "thor@example.org"
},
{"accept": ["tag:server:22"], "src": "tag:client"},
{"accept": ["tag:server:22"], "src": "thor@example.org"}
]},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:server:80\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:443\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:prod:22\" (protocol \"tcp\"): want: Accept, got: Drop",
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Drop, got: Accept"
], "user": "thor@example.org"}, {"errors": [
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "tag:client"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,178 @@
// policytest-src-cidr-accept
//
// tests src cidr accept
//
// Steps: 1
// Captured at: 2026-10-17T15:34:34Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-src-cidr-accept",
"description": "tests src cidr accept",
"category": "policytest",
"captured_at": "2026-10-17T15:34:34.016712574Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "100.64.0.0/24", "errors": [
"[acl test error]: user or host is invalid: unknown user or host: \"100.64.0.0/24\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-src-cidr-accept\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests src cidr accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [{\"src\": \"100.64.0.0/24\", \"accept\": [\"tag:server:22\"]}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-src-cidr-accept.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "100.64.0.0/24"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:39.916553813Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "100.64.0.0/24"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: user or host is invalid: unknown user or host: \"100.64.0.0/24\""
], "user": "100.64.0.0/24"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,178 @@
// policytest-src-cidr-deny
//
// tests src cidr deny
//
// Steps: 1
// Captured at: 2026-10-17T15:34:43Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-src-cidr-deny",
"description": "tests src cidr deny",
"category": "policytest",
"captured_at": "2026-10-17T15:34:43.957942044Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "100.64.0.0/24", "errors": [
"[acl test error]: user or host is invalid: unknown user or host: \"100.64.0.0/24\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-src-cidr-deny\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests src cidr deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [{\"src\": \"100.64.0.0/24\", \"deny\": [\"tag:server:22\"]}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-src-cidr-deny.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"deny": ["tag:server:22"], "src": "100.64.0.0/24"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:49.901744538Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"deny": ["tag:server:22"], "src": "100.64.0.0/24"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: user or host is invalid: unknown user or host: \"100.64.0.0/24\""
], "user": "100.64.0.0/24"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// policytest-src-group-partial-accept
//
// tests src group partial accept
//
// Steps: 1
// Captured at: 2026-10-17T15:34:53Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-src-group-partial-accept",
"description": "tests src group partial accept",
"category": "policytest",
"captured_at": "2026-10-17T15:34:53.941679022Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "group:g", "errors": [
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Accept, got: Drop"
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-src-group-partial-accept\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests src group partial accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"groups\": {\"group:g\": [\"thor@example.org\", \"odin@example.com\"]},\n\t\t\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]},\n\t\t\"acls\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"thor@example.org\"],\n\t\t\t\"dst\": [\"tag:server:22\"]\n\t\t}],\n\t\t\"tests\": [{\"src\": \"group:g\", \"accept\": [\"tag:server:22\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-src-group-partial-accept.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["thor@example.org"]
}],
"groups": {"group:g": ["thor@example.org", "odin@example.com"]},
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "group:g"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:34:59.824715554Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["thor@example.org"]
}],
"groups": {"group:g": ["thor@example.org", "odin@example.com"]},
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "group:g"}]
},
"status": 200,
"response": {"data": [{"errors": [
"[acl test error]: address \"tag:server:22\" (protocol \"tcp\"): want: Accept, got: Drop"
], "user": "group:g"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// policytest-src-wildcard-accept
//
// tests src wildcard accept
//
// Steps: 1
// Captured at: 2026-10-17T15:35:23Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-src-wildcard-accept",
"description": "tests src wildcard accept",
"category": "policytest",
"captured_at": "2026-10-17T15:35:23.824239589Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{
"user": "*",
"errors": ["[acl test error]: user or host is invalid: unknown user or host: \"*\""]
}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"policytest-src-wildcard-accept\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests src wildcard accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [{\"src\": \"*\", \"accept\": [\"tag:server:22\"]}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-src-wildcard-accept.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "*"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:35:29.892346502Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"accept": ["tag:server:22"], "src": "*"}]
},
"status": 200,
"response": {"data": [{
"errors": ["[acl test error]: user or host is invalid: unknown user or host: \"*\""],
"user": "*"
}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// policytest-src-wildcard-deny
//
// tests src wildcard deny
//
// Steps: 1
// Captured at: 2026-10-17T15:35:33Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "policytest-src-wildcard-deny",
"description": "tests src wildcard deny",
"category": "policytest",
"captured_at": "2026-10-17T15:35:33.930899455Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{
"user": "*",
"errors": ["[acl test error]: user or host is invalid: unknown user or host: \"*\""]
}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"policytest-src-wildcard-deny\",\n\t\"category\": \"policytest\",\n\t\"description\": \"tests src wildcard deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\"tag:server\": [\"odin@example.com\"]}, \"acls\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server:22\"]\n\t}], \"tests\": [{\"src\": \"*\", \"deny\": [\"tag:server:22\"]}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/policytest-src-wildcard-deny.hujson",
"full_policy": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"deny": ["tag:server:22"], "src": "*"}]
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:35:39.829258485Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"acls": [{
"action": "accept",
"dst": ["tag:server:22"],
"src": ["autogroup:member"]
}],
"tagOwners": {"tag:server": ["odin@example.com"]},
"tests": [{"deny": ["tag:server:22"], "src": "*"}]
},
"status": 200,
"response": {"data": [{
"errors": ["[acl test error]: user or host is invalid: unknown user or host: \"*\""],
"user": "*"
}], "message": "test(s) failed"}
}]
}]
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,184 @@
// sshtest-check-reason-mixed-alias
//
// sshTests check reason across one alias
//
// Steps: 1
// Captured at: 2026-10-17T15:37:59Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-check-reason-mixed-alias",
"description": "sshTests check reason across one alias",
"category": "sshtest",
"captured_at": "2026-10-17T15:37:59.005109759Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests dst contains disallowed element \"autogroup:member\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-check-reason-mixed-alias\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests check reason across one alias\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"autogroup:self\"],\n\t\t\"users\": [\"root\"]\n\t}], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"autogroup:member\"],\n\t\t\"check\": [\"root\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-check-reason-mixed-alias.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["autogroup:self"],
"src": ["autogroup:member"],
"users": ["root"]
}],
"sshTests": [{
"check": ["root"],
"dst": ["autogroup:member"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:02.343638216Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["autogroup:self"],
"src": ["autogroup:member"],
"users": ["root"]
}],
"sshTests": [{
"check": ["root"],
"dst": ["autogroup:member"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests dst contains disallowed element \"autogroup:member\""}
}]
}]
}
@@ -0,0 +1,174 @@
// sshtest-fail-label-autogroup-member
//
// sshTests failure label, dst autogroup:member
//
// Steps: 1
// Captured at: 2026-10-17T15:38:06Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-autogroup-member",
"description": "sshTests failure label, dst autogroup:member",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:06.406798406Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests dst contains disallowed element \"autogroup:member\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-fail-label-autogroup-member\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst autogroup:member\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"autogroup:member\"],\n\t\t\"accept\": [\"root\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-autogroup-member.hujson",
"full_policy": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["autogroup:member"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:09.868923644Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["autogroup:member"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests dst contains disallowed element \"autogroup:member\""}
}]
}]
}
@@ -0,0 +1,172 @@
// sshtest-fail-label-host-alias
//
// sshTests failure label, dst srv
//
// Steps: 1
// Captured at: 2026-10-17T15:38:13Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-host-alias",
"description": "sshTests failure label, dst srv",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:13.909222096Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"srv\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-fail-label-host-alias\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst srv\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"hosts\": {\"srv\": \"100.64.0.16\"},\n\t\t\"tagOwners\": {\n\t\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [],\n\t\t\"sshTests\": [{\"src\": \"thor@example.org\", \"dst\": [\"srv\"], \"accept\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-host-alias.hujson",
"full_policy": {
"hosts": {"srv": "100.64.0.16"},
"ssh": [],
"sshTests": [{"accept": ["root"], "dst": ["srv"], "src": "thor@example.org"}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:17.391518329Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"hosts": {"srv": "100.64.0.16"},
"ssh": [],
"sshTests": [{"accept": ["root"], "dst": ["srv"], "src": "thor@example.org"}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"srv\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,174 @@
// sshtest-fail-label-ip-dst
//
// sshTests failure label, dst 100.64.0.16
//
// Steps: 1
// Captured at: 2026-10-17T15:38:21Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-ip-dst",
"description": "sshTests failure label, dst 100.64.0.16",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:21.4302842Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.16\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-fail-label-ip-dst\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst 100.64.0.16\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [], \"sshTests\": [\n\t\t{\"src\": \"thor@example.org\", \"dst\": [\"100.64.0.16\"], \"accept\": [\"root\"]}\n\t]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-ip-dst.hujson",
"full_policy": {
"ssh": [],
"sshTests": [
{"accept": ["root"], "dst": ["100.64.0.16"], "src": "thor@example.org"}
],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:24.873246757Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [],
"sshTests": [
{"accept": ["root"], "dst": ["100.64.0.16"], "src": "thor@example.org"}
],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.16\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,174 @@
// sshtest-fail-label-ip-no-device
//
// sshTests failure label, dst 100.64.0.200
//
// Steps: 1
// Captured at: 2026-10-17T15:38:28Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-ip-no-device",
"description": "sshTests failure label, dst 100.64.0.200",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:28.913905373Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.200\" at \"100.64.0.200\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-fail-label-ip-no-device\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst 100.64.0.200\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"100.64.0.200\"],\n\t\t\"accept\": [\"root\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-ip-no-device.hujson",
"full_policy": {
"ssh": [],
"sshTests": [
{"accept": ["root"], "dst": ["100.64.0.200"], "src": "thor@example.org"}
],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:32.382383425Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [],
"sshTests": [
{"accept": ["root"], "dst": ["100.64.0.200"], "src": "thor@example.org"}
],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.200\" at \"100.64.0.200\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,180 @@
// sshtest-fail-label-same-node-twice
//
// sshTests failure label, dst tag:server 100.64.0.16
//
// Steps: 1
// Captured at: 2026-10-17T15:38:36Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-same-node-twice",
"description": "sshTests failure label, dst tag:server 100.64.0.16",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:36.422725633Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.16\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-fail-label-same-node-twice\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst tag:server 100.64.0.16\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"tag:server\", \"100.64.0.16\"],\n\t\t\"accept\": [\"root\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-same-node-twice.hujson",
"full_policy": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["tag:server", "100.64.0.16"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:39.882907279Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["tag:server", "100.64.0.16"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"100.64.0.16\" at \"100.64.0.16\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,178 @@
// sshtest-fail-label-user-dst
//
// sshTests failure label, dst odin@example.com
//
// Steps: 1
// Captured at: 2026-10-17T15:38:43Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-fail-label-user-dst",
"description": "sshTests failure label, dst odin@example.com",
"category": "sshtest",
"captured_at": "2026-10-17T15:38:43.923541634Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"odin@example.com\" at \"100.64.0.1\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-fail-label-user-dst\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests failure label, dst odin@example.com\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:prod\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"odin@example.com\"],\n\t\t\"accept\": [\"root\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-fail-label-user-dst.hujson",
"full_policy": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["odin@example.com"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:38:47.356166918Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [],
"sshTests": [{
"accept": ["root"],
"dst": ["odin@example.com"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:prod": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"odin@example.com\" at \"100.64.0.1\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,192 @@
// sshtest-repeated-names
//
// sshTests repeated failing login name
//
// Steps: 1
// Captured at: 2026-10-17T15:39:16Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-repeated-names",
"description": "sshTests repeated failing login name",
"category": "sshtest",
"captured_at": "2026-10-17T15:39:16.862821789Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n{\n\t\"id\": \"sshtest-repeated-names\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests repeated failing login name\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"]\n\t}, \"ssh\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\"dst\": [\"tag:server\"],\n\t\t\"users\": [\"root\"]\n\t}], \"sshTests\": [{\n\t\t\"src\": \"thor@example.org\",\n\t\t\"dst\": [\"tag:server\"],\n\t\t\"accept\": [\"nobody\", \"nobody\", \"nobody\"]\n\t}]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-repeated-names.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{
"accept": ["nobody", "nobody", "nobody"],
"dst": ["tag:server"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:39:22.851954139Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{
"accept": ["nobody", "nobody", "nobody"],
"dst": ["tag:server"],
"src": "thor@example.org"
}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"nobody\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,218 @@
// sshtest-report-multi
//
// sshTests several failures in one answer
//
// Steps: 1
// Captured at: 2026-10-17T15:39:26Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-report-multi",
"description": "sshTests several failures in one answer",
"category": "sshtest",
"captured_at": "2026-10-17T15:39:26.892716215Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"ubuntu\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"admin\": want: \"accept\" got: \"deny\""
]}, {"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"deny\" got: \"accept\""
]}, {"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"check\" got: \"accept\""
]}, {"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:exit\" at \"100.64.0.7\", ssh user \"root\": want: \"check\" got: \"deny\""
]}, {"user": "thor@example.org", "errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:unused\" at \"100.64.0.8\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n \n{\n\t\"id\": \"sshtest-report-multi\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests several failures in one answer\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\"tagOwners\": {\n\t\t\"tag:exit\": [\"odin@example.com\"],\n\t\t\"tag:server\": [\"odin@example.com\"],\n\t\t\"tag:unused\": [\"odin@example.com\"]\n\t}, \"ssh\": [{\n\t\t\"action\": \"accept\",\n\t\t\"src\": [\"autogroup:member\"],\n\t\t\"dst\": [\"tag:server\"],\n\t\t\"users\": [\"root\"]\n\t}], \"sshTests\": [\n\t\t{\n\t\t\t\"src\": \"thor@example.org\",\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"accept\": [\"ubuntu\", \"admin\"]\n\t\t},\n\t\t{\"src\": \"thor@example.org\", \"dst\": [\"tag:server\"], \"deny\": [\"root\"]},\n\t\t{\"src\": \"thor@example.org\", \"dst\": [\"tag:server\"], \"check\": [\"root\"]},\n\t\t{\"src\": \"thor@example.org\", \"dst\": [\"tag:exit\"], \"check\": [\"root\"]},\n\t\t{\"src\": \"thor@example.org\", \"dst\": [\"tag:unused\"], \"accept\": [\"root\"]}\n\t]}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-report-multi.hujson",
"full_policy": {"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member"],
"users": ["root"]
}], "sshTests": [
{
"accept": ["ubuntu", "admin"],
"dst": ["tag:server"],
"src": "thor@example.org"
},
{"deny": ["root"], "dst": ["tag:server"], "src": "thor@example.org"},
{"check": ["root"], "dst": ["tag:server"], "src": "thor@example.org"},
{"check": ["root"], "dst": ["tag:exit"], "src": "thor@example.org"},
{"accept": ["root"], "dst": ["tag:unused"], "src": "thor@example.org"}
], "tagOwners": {
"tag:exit": ["odin@example.com"],
"tag:server": ["odin@example.com"],
"tag:unused": ["odin@example.com"]
}}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:39:32.80519066Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member"],
"users": ["root"]
}], "sshTests": [
{
"accept": ["ubuntu", "admin"],
"dst": ["tag:server"],
"src": "thor@example.org"
},
{"deny": ["root"], "dst": ["tag:server"], "src": "thor@example.org"},
{"check": ["root"], "dst": ["tag:server"], "src": "thor@example.org"},
{"check": ["root"], "dst": ["tag:exit"], "src": "thor@example.org"},
{"accept": ["root"], "dst": ["tag:unused"], "src": "thor@example.org"}
], "tagOwners": {
"tag:exit": ["odin@example.com"],
"tag:server": ["odin@example.com"],
"tag:unused": ["odin@example.com"]
}},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"ubuntu\": want: \"accept\" got: \"deny\"",
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"admin\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}, {"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"deny\" got: \"accept\""
], "user": "thor@example.org"}, {"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:server\" at \"100.64.0.1\", ssh user \"root\": want: \"check\" got: \"accept\""
], "user": "thor@example.org"}, {"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:exit\" at \"100.64.0.7\", ssh user \"root\": want: \"check\" got: \"deny\""
], "user": "thor@example.org"}, {"errors": [
"[ssh test error]: src \"thor@example.org\" at \"100.64.0.0\", dst \"tag:unused\" at \"100.64.0.8\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "thor@example.org"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,176 @@
// sshtest-src-cidr24-deny
//
// sshTests src 100.64.0.0/24 deny
//
// Steps: 1
// Captured at: 2026-10-17T15:39:36Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-cidr24-deny",
"description": "sshTests src 100.64.0.0/24 deny",
"category": "sshtest",
"captured_at": "2026-10-17T15:39:36.850367612Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"100.64.0.0/24\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-cidr24-deny\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.0/24 deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.0/24\", \"dst\": [\"tag:server\"], \"deny\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-cidr24-deny.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.0/24"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:39:42.809965868Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.0/24"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"100.64.0.0/24\""}
}]
}]
}
@@ -0,0 +1,176 @@
// sshtest-src-cidr31-empty-accept
//
// sshTests src 100.64.0.20/31 accept
//
// Steps: 1
// Captured at: 2026-10-17T15:39:46Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-cidr31-empty-accept",
"description": "sshTests src 100.64.0.20/31 accept",
"category": "sshtest",
"captured_at": "2026-10-17T15:39:46.848554928Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"100.64.0.20/31\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-cidr31-empty-accept\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.20/31 accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.20/31\", \"dst\": [\"tag:server\"], \"accept\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-cidr31-empty-accept.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.20/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:39:52.841075349Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.20/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"100.64.0.20/31\""}
}]
}]
}
@@ -0,0 +1,176 @@
// sshtest-src-cidr31-empty-deny
//
// sshTests src 100.64.0.20/31 deny
//
// Steps: 1
// Captured at: 2026-10-17T15:39:56Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-cidr31-empty-deny",
"description": "sshTests src 100.64.0.20/31 deny",
"category": "sshtest",
"captured_at": "2026-10-17T15:39:56.885368865Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"100.64.0.20/31\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-cidr31-empty-deny\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.20/31 deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.20/31\", \"dst\": [\"tag:server\"], \"deny\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-cidr31-empty-deny.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.20/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:02.716729606Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.20/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"100.64.0.20/31\""}
}]
}]
}
@@ -0,0 +1,176 @@
// sshtest-src-cidr31-hole-accept
//
// sshTests src 100.64.0.8/31 accept
//
// Steps: 1
// Captured at: 2026-10-17T15:40:06Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-cidr31-hole-accept",
"description": "sshTests src 100.64.0.8/31 accept",
"category": "sshtest",
"captured_at": "2026-10-17T15:40:06.75580611Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"100.64.0.8/31\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n \n{\n\t\"id\": \"sshtest-src-cidr31-hole-accept\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.8/31 accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.8/31\", \"dst\": [\"tag:server\"], \"accept\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-cidr31-hole-accept.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.8/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:12.798572114Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.8/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"100.64.0.8/31\""}
}]
}]
}
@@ -0,0 +1,176 @@
// sshtest-src-cidr31-members-accept
//
// sshTests src 100.64.0.18/31 accept
//
// Steps: 1
// Captured at: 2026-10-17T15:40:16Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-cidr31-members-accept",
"description": "sshTests src 100.64.0.18/31 accept",
"category": "sshtest",
"captured_at": "2026-10-17T15:40:16.839706203Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"100.64.0.18/31\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-cidr31-members-accept\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.18/31 accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.18/31\", \"dst\": [\"tag:server\"], \"accept\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-cidr31-members-accept.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.18/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:22.821269192Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.18/31"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"100.64.0.18/31\""}
}]
}]
}
@@ -0,0 +1,178 @@
// sshtest-src-hosts-cidr-deny
//
// sshTests src lan deny
//
// Steps: 1
// Captured at: 2026-10-17T15:40:26Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-hosts-cidr-deny",
"description": "sshTests src lan deny",
"category": "sshtest",
"captured_at": "2026-10-17T15:40:26.860167841Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "SSH tests src contains disallowed element \"lan\""},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-hosts-cidr-deny\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src lan deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"hosts\": {\"lan\": \"192.168.1.0/24\"},\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"lan\", \"dst\": [\"tag:server\"], \"deny\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-hosts-cidr-deny.hujson",
"full_policy": {
"hosts": {"lan": "192.168.1.0/24"},
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "lan"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:32.697293024Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"hosts": {"lan": "192.168.1.0/24"},
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "lan"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"message": "SSH tests src contains disallowed element \"lan\""}
}]
}]
}
@@ -0,0 +1,180 @@
// sshtest-src-unassigned-ip-accept
//
// sshTests src 100.64.0.30 accept
//
// Steps: 1
// Captured at: 2026-10-17T15:40:36Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-unassigned-ip-accept",
"description": "sshTests src 100.64.0.30 accept",
"category": "sshtest",
"captured_at": "2026-10-17T15:40:36.737078179Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"error": true,
"input": {
"api_response_code": 400,
"api_response_body": {"message": "test(s) failed", "data": [{"user": "100.64.0.30", "errors": [
"[ssh test error]: src \"100.64.0.30\" at \"100.64.0.30\", dst \"tag:server\" at \"100.64.0.0\", ssh user \"root\": want: \"accept\" got: \"deny\""
]}]},
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-unassigned-ip-accept\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.30 accept\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.30\", \"dst\": [\"tag:server\"], \"accept\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-unassigned-ip-accept.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.30"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:42.809879318Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"accept": ["root"], "dst": ["tag:server"], "src": "100.64.0.30"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {"data": [{"errors": [
"[ssh test error]: src \"100.64.0.30\" at \"100.64.0.30\", dst \"tag:server\" at \"100.64.0.0\", ssh user \"root\": want: \"accept\" got: \"deny\""
], "user": "100.64.0.30"}], "message": "test(s) failed"}
}]
}]
}
@@ -0,0 +1,174 @@
// sshtest-src-unassigned-ip-deny
//
// sshTests src 100.64.0.30 deny
//
// Steps: 1
// Captured at: 2026-10-17T15:40:46Z
// tool version: tscap/e3511f1
// schema version: 1
{
"schema_version": 1,
"test_id": "sshtest-src-unassigned-ip-deny",
"description": "sshTests src 100.64.0.30 deny",
"category": "sshtest",
"captured_at": "2026-10-17T15:40:46.849529382Z",
"tool_version": "tscap/e3511f1",
"tailnet": "odin@example.com",
"input": {
"api_response_code": 200,
"tailnet": {
"dns": {"magic_dns": false, "nameservers": [], "search_paths": [], "split_dns": {}},
"settings": {}
},
"scenario_hujson": " \n \n \n \n{\n\t\"id\": \"sshtest-src-unassigned-ip-deny\",\n\t\"category\": \"sshtest\",\n\t\"description\": \"sshTests src 100.64.0.30 deny\",\n\t\"topology\": \"../../_topologies/grant.hujson\",\n\t\"tailnet\": {\n\t\t\"dns\": {\"magic_dns\": false, \"nameservers\": [], \"search_paths\": [], \"split_dns\": {}},\n\t\t\"settings\": {}\n\t},\n\t\"options\": {\"capture\": \"none\"},\n\t\"policy\": {\n\t\t\"tagOwners\": {\n\t\t\t\"tag:router\": [\"odin@example.com\"],\n\t\t\t\"tag:server\": [\"odin@example.com\"]\n\t\t},\n\t\t\"ssh\": [{\n\t\t\t\"action\": \"accept\",\n\t\t\t\"src\": [\"autogroup:member\", \"tag:router\"],\n\t\t\t\"dst\": [\"tag:server\"],\n\t\t\t\"users\": [\"root\"]\n\t\t}],\n\t\t\"sshTests\": [{\"src\": \"100.64.0.30\", \"dst\": [\"tag:server\"], \"deny\": [\"root\"]}]\n\t}\n}\n",
"scenario_path": "scenarios/grant-matrix/grant/sshtest-src-unassigned-ip-deny.hujson",
"full_policy": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.30"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
}
},
"topology": {"users": [
{"id": 1, "name": "odin", "email": "odin@example.com"},
{"id": 2, "name": "thor", "email": "thor@example.org"},
{"id": 3, "name": "freya", "email": "freya@example.com"}
], "nodes": {"beedrill": {
"hostname": "beedrill",
"tags": ["tag:server"],
"ipv4": "100.64.0.16",
"ipv6": "fd7a:115c:a1e0::10",
"routable_ips": [],
"approved_routes": []
}, "blastoise": {
"hostname": "blastoise",
"tags": ["tag:exit", "tag:router"],
"ipv4": "100.64.0.9",
"ipv6": "fd7a:115c:a1e0::9",
"routable_ips": ["10.33.0.0/16", "0.0.0.0/0", "::/0"],
"approved_routes": []
}, "bulbasaur": {
"hostname": "bulbasaur",
"tags": [],
"ipv4": "100.64.0.19",
"ipv6": "fd7a:115c:a1e0::13",
"user": "odin",
"routable_ips": [],
"approved_routes": []
}, "charmander": {
"hostname": "charmander",
"tags": ["tag:exit"],
"ipv4": "100.64.0.4",
"ipv6": "fd7a:115c:a1e0::4",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "fearow": {
"hostname": "fearow",
"tags": ["tag:fearow"],
"ipv4": "100.64.0.12",
"ipv6": "fd7a:115c:a1e0::c",
"routable_ips": ["10.55.0.0/16"],
"approved_routes": []
}, "ivysaur": {
"hostname": "ivysaur",
"tags": [],
"ipv4": "100.64.0.17",
"ipv6": "fd7a:115c:a1e0::11",
"user": "thor",
"routable_ips": [],
"approved_routes": []
}, "kakuna": {
"hostname": "kakuna",
"tags": ["tag:prod"],
"ipv4": "100.64.0.15",
"ipv6": "fd7a:115c:a1e0::f",
"routable_ips": [],
"approved_routes": []
}, "pidgeotto": {
"hostname": "pidgeotto",
"tags": ["tag:pidgeotto"],
"ipv4": "100.64.0.3",
"ipv6": "fd7a:115c:a1e0::3",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "pidgey": {
"hostname": "pidgey",
"tags": ["tag:pidgey"],
"ipv4": "100.64.0.2",
"ipv6": "fd7a:115c:a1e0::2",
"routable_ips": ["0.0.0.0/0", "::/0"],
"approved_routes": []
}, "raticate": {
"hostname": "raticate",
"tags": ["tag:group-b"],
"ipv4": "100.64.0.6",
"ipv6": "fd7a:115c:a1e0::6",
"routable_ips": [],
"approved_routes": []
}, "rattata": {
"hostname": "rattata",
"tags": ["tag:group-a"],
"ipv4": "100.64.0.5",
"ipv6": "fd7a:115c:a1e0::5",
"routable_ips": [],
"approved_routes": []
}, "spearow": {
"hostname": "spearow",
"tags": ["tag:spearow"],
"ipv4": "100.64.0.11",
"ipv6": "fd7a:115c:a1e0::b",
"routable_ips": ["10.44.0.0/16"],
"approved_routes": []
}, "squirtle": {
"hostname": "squirtle",
"tags": ["tag:router"],
"ipv4": "100.64.0.13",
"ipv6": "fd7a:115c:a1e0::d",
"routable_ips": ["10.33.0.0/16"],
"approved_routes": []
}, "venusaur": {
"hostname": "venusaur",
"tags": [],
"ipv4": "100.64.0.18",
"ipv6": "fd7a:115c:a1e0::12",
"user": "freya",
"routable_ips": [],
"approved_routes": []
}, "weedle": {
"hostname": "weedle",
"tags": ["tag:client"],
"ipv4": "100.64.0.14",
"ipv6": "fd7a:115c:a1e0::e",
"routable_ips": [],
"approved_routes": []
}}},
"captures": {},
"steps": [{
"name": "validate",
"at": "2026-10-17T15:40:52.804301851Z",
"result": "observed",
"actions": [{
"kind": "api",
"principal": "admin",
"method": "POST",
"path": "/tailnet/-/acl/validate",
"header": {"Content-Type": "application/hujson"},
"body": {
"ssh": [{
"action": "accept",
"dst": ["tag:server"],
"src": ["autogroup:member", "tag:router"],
"users": ["root"]
}],
"sshTests": [{"deny": ["root"], "dst": ["tag:server"], "src": "100.64.0.30"}],
"tagOwners": {"tag:router": ["odin@example.com"], "tag:server": ["odin@example.com"]}
},
"status": 200,
"response": {}
}]
}]
}
+13
View File
@@ -316,6 +316,19 @@ var rejectedPolicySkipReasons = map[string]string{
"ssh-e1/refused": noTailnetDomains,
"ssh-e2/refused": noTailnetDomains,
"ssh-malformed-user-localpart-multi-glob/refused": noTailnetDomains,
"acl-err10/refused": "ROUTE_HOST_BITS: headscale accepts an autoApprovers route with host bits",
"acl-err11/refused": "ROUTE_HOST_BITS: headscale accepts an autoApprovers route with host bits",
"ssh-check-tag-src/refused": "SSH_CHECK_TAG_SRC: headscale accepts a check rule with a tag source",
"policytest-src-cidr-accept/refused": "TEST_SRC_SHAPE: headscale evaluates a CIDR tests source",
"policytest-src-wildcard-deny/refused": "TEST_SRC_SHAPE: headscale evaluates \"*\" as a tests source",
"policytest-dst-multinode-partial-accept/refused": "TEST_DST_EVERY_NODE: headscale accepts when one node of the dst alias is reached",
"sshtest-src-cidr31-empty-deny/refused": "SSHTEST_SRC_RANGE: headscale evaluates a CIDR sshTests source",
"sshtest-src-cidr31-members-accept/refused": "SSHTEST_SRC_RANGE: headscale evaluates a CIDR sshTests source",
"sshtest-src-hosts-cidr-deny/refused": "SSHTEST_SRC_RANGE: headscale evaluates a host alias holding a CIDR as an sshTests source",
}
const noTailnetDomains = "NO_TAILNET_DOMAINS: headscale does not check user:*@domain or localpart:*@domain against the tailnet's domains"
+4 -4
View File
@@ -428,9 +428,9 @@ func convertCapturePolicy(t *testing.T, c *testcapture.Capture) []byte {
// convertPolicyEmails replaces each SaaS email in policy with the "<name>@"
// form that resolves to the users [createCaptureUsers] creates. Fails the
// test if none of the known SaaS emails are present: that would mean the
// capture was regenerated with a new identity and captureUserNames needs
// updating.
// test if the policy names a user but none of the known SaaS emails: that
// would mean the capture was regenerated with a new identity and
// captureUserNames needs updating.
func convertPolicyEmails(t *testing.T, testID, policy string) []byte {
t.Helper()
@@ -447,7 +447,7 @@ func convertPolicyEmails(t *testing.T, testID, policy string) []byte {
require.True(
t,
substituted,
substituted || !strings.Contains(s, "@"),
"%s: no known SaaS email found in policy; update captureUserNames",
testID,
)