1package ports
2
3import (
4 "strings"
5 "testing"
6
7 "github.com/stretchr/testify/require"
8
9 "github.com/bnema/vev/internal/domain"
10 "github.com/bnema/vev/internal/protocol"
11)
12
13func admissionTestPolicy() BrokerPolicy {
14 return BrokerPolicy{
15 ProtocolVersion: protocol.Version,
16 CatalogSchemaVersion: 3,
17 EnvironmentPolicy: protocol.EnvironmentPolicyClientOwned,
18 Transport: "unix-mux",
19 Trust: "same-user",
20 Launch: "explicit",
21 Isolation: "per-user",
22 }
23}
24
25func admissionTestTarget() protocol.ExactSessionTarget {
26 return protocol.ExactSessionTarget{LifecycleID: domain.SessionLifecycleID{1, 2, 3}, SessionName: "work"}
27}
28
29// TestSessionConnectionOriginValidateMatrix pins the closed origin taxonomy: the
30// two provisioned localities validate and Unknown plus every out-of-range value
31// is refused, so an admission can never inherit an implicit locality.
32func TestSessionConnectionOriginValidateMatrix(t *testing.T) {
33 tests := []struct {
34 name string
35 origin SessionConnectionOrigin
36 valid bool
37 }{
38 {name: "unknown", origin: SessionOriginUnknown, valid: false},
39 {name: "local", origin: SessionOriginLocal, valid: true},
40 {name: "remote", origin: SessionOriginRemote, valid: true},
41 {name: "out of range", origin: SessionConnectionOrigin(9), valid: false},
42 }
43 for _, tt := range tests {
44 t.Run(tt.name, func(t *testing.T) {
45 err := tt.origin.Validate()
46 if tt.valid {
47 require.NoError(t, err)
48 return
49 }
50 require.Error(t, err)
51 })
52 }
53}
54
55// TestSessionAdmissionValidateMatrix pins the closed admission contract: origin,
56// policy, purpose, admission variant, name, target, and environment bounds are
57// each enforced, and a shape that contradicts its purpose is refused rather than
58// narrowed.
59func TestSessionAdmissionValidateMatrix(t *testing.T) {
60 env := []string{"TERM=xterm"}
61 atEnvLimit := make([]string, BrokerMaxEnvEntries)
62 for i := range atEnvLimit {
63 atEnvLimit[i] = "K=v"
64 }
65 oversizeEnv := []string{"K=" + strings.Repeat("x", BrokerMaxEnvEntryBytes)}
66
67 base := SessionAdmission{Origin: SessionOriginLocal, Policy: admissionTestPolicy(), Purpose: BrokerStreamControl}
68
69 tests := []struct {
70 name string
71 admission SessionAdmission
72 valid bool
73 }{
74 {name: "control", admission: base, valid: true},
75 {name: "observation", admission: func() SessionAdmission {
76 a := base
77 a.Purpose = BrokerStreamObservation
78 return a
79 }(), valid: true},
80 {name: "exact attach", admission: func() SessionAdmission {
81 a := base
82 a.Purpose = BrokerStreamAttachment
83 a.Admission = BrokerAdmissionExact
84 a.Target = admissionTestTarget()
85 a.Env = append([]string(nil), env...)
86 return a
87 }(), valid: true},
88 {name: "named creation", admission: func() SessionAdmission {
89 a := base
90 a.Purpose = BrokerStreamAttachment
91 a.Admission = BrokerAdmissionCreateNamed
92 a.Name = "work"
93 return a
94 }(), valid: true},
95 {name: "ephemeral creation", admission: func() SessionAdmission {
96 a := base
97 a.Purpose = BrokerStreamAttachment
98 a.Admission = BrokerAdmissionCreateEphemeral
99 return a
100 }(), valid: true},
101 {name: "remote exact attach", admission: func() SessionAdmission {
102 a := base
103 a.Origin = SessionOriginRemote
104 a.Purpose = BrokerStreamAttachment
105 a.Admission = BrokerAdmissionExact
106 a.Target = admissionTestTarget()
107 return a
108 }(), valid: true},
109 {name: "environment at bound", admission: func() SessionAdmission {
110 a := base
111 a.Purpose = BrokerStreamAttachment
112 a.Admission = BrokerAdmissionExact
113 a.Target = admissionTestTarget()
114 a.Env = atEnvLimit
115 return a
116 }(), valid: true},
117
118 {name: "unknown origin", admission: func() SessionAdmission {
119 a := base
120 a.Origin = SessionOriginUnknown
121 return a
122 }(), valid: false},
123 {name: "invalid origin", admission: func() SessionAdmission {
124 a := base
125 a.Origin = SessionConnectionOrigin(7)
126 return a
127 }(), valid: false},
128 {name: "invalid policy", admission: func() SessionAdmission {
129 a := base
130 a.Policy.ProtocolVersion = 0
131 return a
132 }(), valid: false},
133 {name: "zero purpose", admission: func() SessionAdmission {
134 a := base
135 a.Purpose = 0
136 return a
137 }(), valid: false},
138 {name: "invalid purpose", admission: func() SessionAdmission {
139 a := base
140 a.Purpose = BrokerStreamPurpose(9)
141 return a
142 }(), valid: false},
143 {name: "attachment without admission", admission: func() SessionAdmission {
144 a := base
145 a.Purpose = BrokerStreamAttachment
146 return a
147 }(), valid: false},
148 {name: "exact without target", admission: func() SessionAdmission {
149 a := base
150 a.Purpose = BrokerStreamAttachment
151 a.Admission = BrokerAdmissionExact
152 return a
153 }(), valid: false},
154 {name: "exact with name", admission: func() SessionAdmission {
155 a := base
156 a.Purpose = BrokerStreamAttachment
157 a.Admission = BrokerAdmissionExact
158 a.Target = admissionTestTarget()
159 a.Name = "work"
160 return a
161 }(), valid: false},
162 {name: "named creation without name", admission: func() SessionAdmission {
163 a := base
164 a.Purpose = BrokerStreamAttachment
165 a.Admission = BrokerAdmissionCreateNamed
166 return a
167 }(), valid: false},
168 {name: "named creation with target", admission: func() SessionAdmission {
169 a := base
170 a.Purpose = BrokerStreamAttachment
171 a.Admission = BrokerAdmissionCreateNamed
172 a.Name = "work"
173 a.Target = admissionTestTarget()
174 return a
175 }(), valid: false},
176 {name: "ephemeral with name", admission: func() SessionAdmission {
177 a := base
178 a.Purpose = BrokerStreamAttachment
179 a.Admission = BrokerAdmissionCreateEphemeral
180 a.Name = "work"
181 return a
182 }(), valid: false},
183 {name: "ephemeral with target", admission: func() SessionAdmission {
184 a := base
185 a.Purpose = BrokerStreamAttachment
186 a.Admission = BrokerAdmissionCreateEphemeral
187 a.Target = admissionTestTarget()
188 return a
189 }(), valid: false},
190 {name: "control carries admission", admission: func() SessionAdmission {
191 a := base
192 a.Admission = BrokerAdmissionExact
193 return a
194 }(), valid: false},
195 {name: "control carries name", admission: func() SessionAdmission {
196 a := base
197 a.Name = "work"
198 return a
199 }(), valid: false},
200 {name: "control carries target", admission: func() SessionAdmission {
201 a := base
202 a.Target = admissionTestTarget()
203 return a
204 }(), valid: false},
205 {name: "control carries env", admission: func() SessionAdmission {
206 a := base
207 a.Env = append([]string(nil), env...)
208 return a
209 }(), valid: false},
210 {name: "observation carries env", admission: func() SessionAdmission {
211 a := base
212 a.Purpose = BrokerStreamObservation
213 a.Env = append([]string(nil), env...)
214 return a
215 }(), valid: false},
216 {name: "too many environment entries", admission: func() SessionAdmission {
217 a := base
218 a.Purpose = BrokerStreamAttachment
219 a.Admission = BrokerAdmissionExact
220 a.Target = admissionTestTarget()
221 a.Env = append(append([]string(nil), atEnvLimit...), "K=v")
222 return a
223 }(), valid: false},
224 {name: "oversize environment entry", admission: func() SessionAdmission {
225 a := base
226 a.Purpose = BrokerStreamAttachment
227 a.Admission = BrokerAdmissionExact
228 a.Target = admissionTestTarget()
229 a.Env = oversizeEnv
230 return a
231 }(), valid: false},
232 {name: "invalid utf8 environment entry", admission: func() SessionAdmission {
233 a := base
234 a.Purpose = BrokerStreamAttachment
235 a.Admission = BrokerAdmissionExact
236 a.Target = admissionTestTarget()
237 a.Env = []string{"K=\xff"}
238 return a
239 }(), valid: false},
240 }
241 for _, tt := range tests {
242 t.Run(tt.name, func(t *testing.T) {
243 err := tt.admission.Validate()
244 if tt.valid {
245 require.NoError(t, err)
246 return
247 }
248 require.Error(t, err)
249 })
250 }
251}
252
253// TestSessionAdmissionCloneIsDeep pins the defensive copy: mutating the clone's
254// environment or its nested values never changes the original, and a nil
255// environment stays nil.
256func TestSessionAdmissionCloneIsDeep(t *testing.T) {
257 original := SessionAdmission{
258 Origin: SessionOriginRemote, Policy: admissionTestPolicy(), Purpose: BrokerStreamAttachment,
259 Admission: BrokerAdmissionExact, Target: admissionTestTarget(), Env: []string{"TERM=xterm"},
260 }
261 clone := original.Clone()
262 require.Equal(t, original, clone)
263
264 clone.Env[0] = "TERM=changed"
265 clone.Policy.Trust = "changed"
266 clone.Target.SessionName = "changed"
267 require.Equal(t, "TERM=xterm", original.Env[0], "clone environment is independent")
268 require.Equal(t, "same-user", original.Policy.Trust)
269 require.Equal(t, "work", original.Target.SessionName)
270
271 empty := SessionAdmission{Origin: SessionOriginLocal, Policy: admissionTestPolicy(), Purpose: BrokerStreamControl}
272 require.Nil(t, empty.Clone().Env, "an absent environment stays nil")
273 require.Equal(t, empty, empty.Clone())
274}