-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathengine_test.go
More file actions
120 lines (87 loc) · 3.8 KB
/
engine_test.go
File metadata and controls
120 lines (87 loc) · 3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2026 Hyperscale. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package security_test
import (
"context"
"errors"
"testing"
"github.com/hyperscale-stack/security"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEngineReturnsErrNoExtractorWhenNoneConfigured(t *testing.T) {
e := security.NewEngine(security.NewManager())
ctx, auth, err := e.Process(context.Background(), newMapCarrier())
assert.ErrorIs(t, err, security.ErrNoExtractor)
assert.Equal(t, security.Anonymous(), auth)
got, _ := security.FromContext(ctx)
assert.Equal(t, security.Anonymous(), got, "context must carry Anonymous on error")
}
func TestEngineFallsThroughToAnonymousWhenNoExtractorFinds(t *testing.T) {
first := scriptedExtractor{} // (nil, nil) -> "did not apply"
second := scriptedExtractor{} // same
e := security.NewEngine(security.NewManager(), first, second)
ctx, auth, err := e.Process(context.Background(), newMapCarrier())
require.NoError(t, err)
assert.Equal(t, security.Anonymous(), auth)
got, _ := security.FromContext(ctx)
assert.Equal(t, security.Anonymous(), got,
"Engine stores Anonymous explicitly so downstream code can always read it")
}
func TestEngineShortCircuitsOnExtractorError(t *testing.T) {
boom := errors.New("malformed header")
first := scriptedExtractor{err: boom}
second := &countingExtractor{}
e := security.NewEngine(security.NewManager(), first, second)
_, _, err := e.Process(context.Background(), newMapCarrier())
assert.ErrorIs(t, err, boom)
assert.Zero(t, second.calls, "subsequent extractors must not run after an error")
}
func TestEngineHandsExtractedToManager(t *testing.T) {
pending := newFakeAuth("alice").withCredentials("p4ssw0rd")
authed := newFakeAuth("alice").withAuthenticated()
extractor := scriptedExtractor{auth: pending}
authn := &scriptedAuthenticator{name: "basic", result: authed}
e := security.NewEngine(security.NewManager(authn), extractor)
ctx, got, err := e.Process(context.Background(), newMapCarrier())
require.NoError(t, err)
assert.Equal(t, Authentication(authed), got)
stored, ok := security.FromContext(ctx)
assert.True(t, ok)
assert.Equal(t, Authentication(authed), stored)
}
func TestEnginePropagatesManagerError(t *testing.T) {
pending := newFakeAuth("alice").withCredentials("bad")
extractor := scriptedExtractor{auth: pending}
authn := &scriptedAuthenticator{name: "basic", err: security.ErrInvalidCredentials}
e := security.NewEngine(security.NewManager(authn), extractor)
ctx, got, err := e.Process(context.Background(), newMapCarrier())
assert.ErrorIs(t, err, security.ErrInvalidCredentials)
assert.Equal(t, Authentication(pending), got,
"failed auth returns the pre-authentication value so adapters can craft a challenge")
stored, _ := security.FromContext(ctx)
assert.Equal(t, Authentication(pending), stored)
}
func TestEngineSpanRecordsExtractorAndAuthenticationFlags(t *testing.T) {
authed := newFakeAuth("alice").withAuthenticated()
extractor := scriptedExtractor{auth: newFakeAuth("alice").withCredentials("ok")}
authn := &scriptedAuthenticator{name: "basic", result: authed}
e := security.NewEngine(security.NewManager(authn), extractor, scriptedExtractor{})
spans := spanRecorder(func() {
_, _, err := e.Process(context.Background(), newMapCarrier())
require.NoError(t, err)
})
require.GreaterOrEqual(t, len(spans), 1)
var engineSpan int = -1
for i, s := range spans {
if s.Name() == "security.Engine.Process" {
engineSpan = i
break
}
}
require.GreaterOrEqual(t, engineSpan, 0, "engine span must be emitted")
span := spans[engineSpan]
assert.Equal(t, "2", findAttr(span.Attributes(), security.AttrExtractorsCount))
assert.Equal(t, "true", findAttr(span.Attributes(), security.AttrAuthenticated))
}