Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/otelcol/auth/sigv4/sigv4_test.go
4096 views
1
package sigv4_test
2
3
import (
4
"context"
5
"fmt"
6
"net/http"
7
"net/http/httptest"
8
"strings"
9
"testing"
10
"time"
11
12
"github.com/grafana/agent/component/otelcol/auth"
13
"github.com/grafana/agent/component/otelcol/auth/sigv4"
14
"github.com/grafana/agent/pkg/flow/componenttest"
15
"github.com/grafana/agent/pkg/river"
16
"github.com/grafana/agent/pkg/util"
17
"github.com/stretchr/testify/assert"
18
"github.com/stretchr/testify/require"
19
"go.opentelemetry.io/collector/config/configauth"
20
)
21
22
// Test performs a basic integration test which runs the otelcol.auth.sigv4
23
// component and ensures that it can be used for authentication.
24
func Test(t *testing.T) {
25
type TestDefinition struct {
26
testName string
27
awsAccessKeyId string
28
awsSecredAccessKey string
29
region string
30
service string
31
assumeRoleARN string
32
assumeRoleSessionName string
33
assumeRoleStsRegion string
34
riverConfig string
35
}
36
37
tests := []TestDefinition{
38
{
39
testName: "Test1",
40
awsAccessKeyId: "example_access_key_id",
41
awsSecredAccessKey: "example_secret_access_key",
42
region: "example_region",
43
service: "example_service",
44
assumeRoleARN: "",
45
assumeRoleSessionName: "role_session_name",
46
assumeRoleStsRegion: "",
47
riverConfig: "",
48
},
49
{
50
testName: "Test2",
51
awsAccessKeyId: "example_access_key_id",
52
awsSecredAccessKey: "example_secret_access_key",
53
region: "example_region",
54
service: "example_service",
55
assumeRoleARN: "",
56
assumeRoleSessionName: "",
57
assumeRoleStsRegion: "region",
58
riverConfig: "",
59
},
60
{
61
testName: "Test3",
62
awsAccessKeyId: "example_access_key_id",
63
awsSecredAccessKey: "example_secret_access_key",
64
region: "example_region",
65
service: "",
66
assumeRoleARN: "",
67
assumeRoleSessionName: "",
68
assumeRoleStsRegion: "",
69
riverConfig: "",
70
},
71
{
72
testName: "Test4",
73
awsAccessKeyId: "example_access_key_id",
74
awsSecredAccessKey: "example_secret_access_key",
75
region: "",
76
service: "example_service",
77
assumeRoleARN: "",
78
assumeRoleSessionName: "",
79
assumeRoleStsRegion: "",
80
riverConfig: "",
81
},
82
}
83
84
{
85
var tt = &tests[0]
86
tt.riverConfig = fmt.Sprintf(`
87
assume_role {
88
session_name = "%s"
89
}
90
region = "%s"
91
service = "%s"
92
`, tt.assumeRoleSessionName, tt.region, tt.service)
93
}
94
{
95
var tt = &tests[1]
96
tt.riverConfig = fmt.Sprintf(`
97
assume_role {
98
sts_region = "%s"
99
}
100
region = "%s"
101
service = "%s"
102
`, tt.assumeRoleStsRegion, tt.region, tt.service)
103
}
104
{
105
var tt = &tests[2]
106
tt.riverConfig = fmt.Sprintf(`
107
region = "%s"
108
`, tt.region)
109
}
110
{
111
var tt = &tests[3]
112
tt.riverConfig = fmt.Sprintf(`
113
service = "%s"
114
`, tt.service)
115
}
116
117
for _, tt := range tests {
118
// Create an HTTP server which will assert that sigv4 auth has been injected
119
// into the request.
120
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
121
// The date looks like "20230306T125949Z;"
122
dateTimeSplit := strings.Split(r.Header.Get("X-Amz-Date"), "T")
123
assert.Equal(t, len(dateTimeSplit), 2)
124
date := dateTimeSplit[0]
125
assert.Equal(t, len(date), 8)
126
127
authHeaderSplit := strings.Split(r.Header.Get("Authorization"), " ")
128
129
assert.Equal(t, authHeaderSplit[0], "AWS4-HMAC-SHA256")
130
131
credential := fmt.Sprintf("Credential=%s/%s/%s/%s/aws4_request,", tt.awsAccessKeyId, date, tt.region, tt.service)
132
assert.Equal(t, authHeaderSplit[1], credential)
133
134
assert.Equal(t, authHeaderSplit[2], "SignedHeaders=host;x-amz-date,")
135
136
signatureSplit := strings.Split(authHeaderSplit[3], "=")
137
assert.Equal(t, 2, len(signatureSplit))
138
assert.Equal(t, "Signature", signatureSplit[0])
139
140
// SHA256 will always produce a 64 character string
141
require.Equal(t, 64, len(signatureSplit[1]))
142
143
w.WriteHeader(http.StatusOK)
144
}))
145
defer srv.Close()
146
147
t.Setenv("AWS_ACCESS_KEY_ID", tt.awsAccessKeyId)
148
t.Setenv("AWS_SECRET_ACCESS_KEY", tt.awsSecredAccessKey)
149
150
ctx := componenttest.TestContext(t)
151
ctx, cancel := context.WithTimeout(ctx, time.Minute)
152
defer cancel()
153
154
l := util.TestLogger(t)
155
156
// Create and run our component
157
ctrl, err := componenttest.NewControllerFromID(l, "otelcol.auth.sigv4")
158
require.NoError(t, err)
159
160
cfg := tt.riverConfig
161
t.Logf("River configuration: %s", cfg)
162
var args sigv4.Arguments
163
require.NoError(t, river.Unmarshal([]byte(cfg), &args))
164
165
go func() {
166
err := ctrl.Run(ctx, args)
167
require.NoError(t, err)
168
}()
169
170
require.NoError(t, ctrl.WaitRunning(time.Second), "component never started")
171
require.NoError(t, ctrl.WaitExports(time.Second), "component never exported anything")
172
173
// Get the authentication extension from our component and use it to make a
174
// request to our test server.
175
exports := ctrl.Exports().(auth.Exports)
176
require.NotNil(t, exports.Handler.Extension, "handler extension is nil")
177
178
clientAuth, ok := exports.Handler.Extension.(configauth.ClientAuthenticator)
179
require.True(t, ok, "handler does not implement configauth.ClientAuthenticator")
180
181
rt, err := clientAuth.RoundTripper(http.DefaultTransport)
182
require.NoError(t, err)
183
cli := &http.Client{Transport: rt}
184
185
// Wait until the request finishes. We don't assert anything else here; our
186
// HTTP handler won't write the response until it ensures that the sigv4
187
// data is set.
188
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL, nil)
189
require.NoError(t, err)
190
resp, err := cli.Do(req)
191
require.NoError(t, err, "HTTP request failed")
192
require.Equal(t, http.StatusOK, resp.StatusCode)
193
}
194
}
195
196