Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/otelcol/auth/oauth2/oauth2_test.go
4096 views
1
package oauth2_test
2
3
import (
4
"context"
5
"fmt"
6
"net/http"
7
"net/http/httptest"
8
"testing"
9
"time"
10
11
"github.com/grafana/agent/component/otelcol/auth"
12
"github.com/grafana/agent/component/otelcol/auth/oauth2"
13
"github.com/grafana/agent/pkg/flow/componenttest"
14
"github.com/grafana/agent/pkg/river"
15
"github.com/grafana/agent/pkg/util"
16
"github.com/stretchr/testify/require"
17
"go.opentelemetry.io/collector/config/configauth"
18
"gotest.tools/assert"
19
)
20
21
// Test performs a oauth2 integration test which runs the otelcol.auth.oauth2
22
// component and ensures that it can be used for authentication.
23
func Test(t *testing.T) {
24
tests := []struct {
25
testName string
26
accessToken string
27
tokenType string
28
refreshToken string
29
configBuilder func(string) string
30
}{
31
{
32
"runWithRequiredParams",
33
"TestAccessToken",
34
"TestTokenType",
35
"TestRefreshToken",
36
func(srvProvidingTokensURL string) string {
37
return fmt.Sprintf(`
38
client_id = "someclientid"
39
client_secret = "someclientsecret"
40
token_url = "%s/oauth2/default/v1/token"
41
`, srvProvidingTokensURL)
42
},
43
},
44
{
45
"runWithOptionalParams",
46
"TestAccessToken",
47
"TestTokenType",
48
"TestRefreshToken",
49
func(srvProvidingTokensURL string) string {
50
return fmt.Sprintf(`
51
client_id = "someclientid2"
52
client_secret = "someclientsecret2"
53
token_url = "%s/oauth2/default/v1/token"
54
endpoint_params = {"audience" = ["someaudience"]}
55
scopes = ["api.metrics"]
56
timeout = "1s"
57
tls {
58
insecure = true
59
}
60
`, srvProvidingTokensURL)
61
},
62
},
63
}
64
65
//TODO: Could we call t.Parallel() here? I am not sure if httptest.NewServer() usage is thread safe.
66
// For now we do the tests synchronously because there aren't that many of them anyway.
67
for _, tt := range tests {
68
t.Run(tt.testName, func(t *testing.T) {
69
// Create an HTTP server which will assert that oauth2 auth has been injected
70
// into the request.
71
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
72
w.WriteHeader(http.StatusOK)
73
74
authHeader := r.Header.Get("Authorization")
75
expectedAuthHeader := fmt.Sprintf("%s %s", tt.tokenType, tt.accessToken)
76
assert.Equal(t, expectedAuthHeader, authHeader, "auth header didn't match")
77
78
//TODO: Also write checks for `endpoint_params`` and `scopes``
79
}))
80
defer srv.Close()
81
t.Logf("Created server which will require authentication on address %s", srv.URL)
82
83
srvProvidingTokens := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
84
w.WriteHeader(http.StatusOK)
85
w.Write([]byte(fmt.Sprintf("access_token=%s&token_type=%s&refresh_token=%s", tt.accessToken, tt.tokenType, tt.refreshToken)))
86
}))
87
defer srvProvidingTokens.Close()
88
t.Logf("Created server which will provide authentication tokens on address %s", srvProvidingTokens.URL)
89
90
ctx := componenttest.TestContext(t)
91
ctx, cancel := context.WithTimeout(ctx, time.Minute)
92
defer cancel()
93
94
l := util.TestLogger(t)
95
96
// Create and run our component
97
ctrl, err := componenttest.NewControllerFromID(l, "otelcol.auth.oauth2")
98
require.NoError(t, err)
99
100
cfg := tt.configBuilder(srvProvidingTokens.URL)
101
var args oauth2.Arguments
102
require.NoError(t, river.Unmarshal([]byte(cfg), &args))
103
104
go func() {
105
err := ctrl.Run(ctx, args)
106
require.NoError(t, err)
107
}()
108
109
require.NoError(t, ctrl.WaitRunning(time.Second), "component never started")
110
require.NoError(t, ctrl.WaitExports(time.Second), "component never exported anything")
111
112
// Get the authentication extension from our component and use it to make a
113
// request to our test server.
114
exports := ctrl.Exports().(auth.Exports)
115
require.NotNil(t, exports.Handler.Extension, "handler extension is nil")
116
117
clientAuth, ok := exports.Handler.Extension.(configauth.ClientAuthenticator)
118
require.True(t, ok, "handler does not implement configauth.ClientAuthenticator")
119
120
rt, err := clientAuth.RoundTripper(http.DefaultTransport)
121
require.NoError(t, err)
122
cli := &http.Client{Transport: rt}
123
124
// Wait until the request finishes. We don't assert anything else here; our
125
// HTTP handler won't write the response until it ensures that the oauth2 auth
126
// was found.
127
req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL, nil)
128
require.NoError(t, err)
129
resp, err := cli.Do(req)
130
require.NoError(t, err, "HTTP request failed")
131
require.Equal(t, http.StatusOK, resp.StatusCode)
132
})
133
}
134
}
135
136