Skip to content

Commit

Permalink
Convert token propagation integration test to plain unit test (#4162)
Browse files Browse the repository at this point in the history
## Which problem is this PR solving?
- `plugin/storage/integration/token_propagation_test.go` is using mock
ES server created in the test itself
- even though it also uses query service binary, it can be started
directly in the unit test

## Short description of the changes
- move the test to `cmd/query/app/token_propagation_test.go` as a unit
test
- simplify mock ES handler by relying on
`bearertoken.PropagationHandler`
- remove from scripts/es-integration-test.sh and simplify that script a
bit

Signed-off-by: Yuri Shkuro <[email protected]>
  • Loading branch information
yurishkuro authored Jan 16, 2023
1 parent bc25ce8 commit 65ad4fc
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 176 deletions.
138 changes: 138 additions & 0 deletions cmd/query/app/token_propagation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) 2019 The Jaeger Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package app

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"

"github.com/olivere/elastic"
"github.com/opentracing/opentracing-go"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"

"github.com/jaegertracing/jaeger/cmd/flags"
"github.com/jaegertracing/jaeger/cmd/query/app/querysvc"
"github.com/jaegertracing/jaeger/pkg/bearertoken"
"github.com/jaegertracing/jaeger/pkg/config"
"github.com/jaegertracing/jaeger/pkg/metrics"
"github.com/jaegertracing/jaeger/pkg/tenancy"
"github.com/jaegertracing/jaeger/plugin/storage/es"
"github.com/jaegertracing/jaeger/ports"
)

const (
bearerToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhZG1pbiIsIm5hbWUiOiJKb2huIERvZSIsImlhdCI"
bearerHeader = "Bearer " + bearerToken
)

type elasticsearchHandlerMock struct {
test *testing.T
}

func (h *elasticsearchHandlerMock) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if token, ok := bearertoken.GetBearerToken(r.Context()); ok && token == bearerToken {
// Return empty results, we don't care about the result here.
// we just need to make sure the token was propagated to the storage and the query-service returns 200
ret := new(elastic.SearchResult)
json_ret, _ := json.Marshal(ret)
w.Header().Add("Content-Type", "application/json; charset=UTF-8")
w.Write(json_ret)
return
}

// No token, return error!
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}

func runMockElasticsearchServer(t *testing.T) *httptest.Server {
handler := &elasticsearchHandlerMock{
test: t,
}
return httptest.NewServer(
bearertoken.PropagationHandler(zaptest.NewLogger(t), handler),
)
}

func runQueryService(t *testing.T, esURL string) *Server {
flagsSvc := flags.NewService(ports.QueryAdminHTTP)
flagsSvc.Logger = zaptest.NewLogger(t)

f := es.NewFactory()
v, command := config.Viperize(f.AddFlags)
require.NoError(t, command.ParseFlags([]string{
"--es.tls.enabled=false",
"--es.version=7",
"--es.server-urls=" + esURL,
}))
f.InitFromViper(v, flagsSvc.Logger)
// set AllowTokenFromContext manually because we don't register the respective CLI flag from query svc
f.Options.Primary.AllowTokenFromContext = true
require.NoError(t, f.Initialize(metrics.NullFactory, flagsSvc.Logger))

spanReader, err := f.CreateSpanReader()
require.NoError(t, err)

querySvc := querysvc.NewQueryService(spanReader, nil, querysvc.QueryServiceOptions{})
server, err := NewServer(flagsSvc.Logger, querySvc, nil,
&QueryOptions{GRPCHostPort: ":0", HTTPHostPort: ":0", BearerTokenPropagation: true},
tenancy.NewManager(&tenancy.Options{}),
opentracing.NoopTracer{},
)
require.NoError(t, err)
require.NoError(t, server.Start())
return server
}

func TestBearerTokenPropagation(t *testing.T) {
testCases := []struct {
name string
headerValue string
headerName string
}{
{name: "Bearer token", headerName: "Authorization", headerValue: bearerHeader},
{name: "Raw Bearer token", headerName: "Authorization", headerValue: bearerToken},
{name: "X-Forwarded-Access-Token", headerName: "X-Forwarded-Access-Token", headerValue: bearerHeader},
}

esSrv := runMockElasticsearchServer(t)
defer esSrv.Close()
t.Logf("mock ES server started on %s", esSrv.URL)

querySrv := runQueryService(t, esSrv.URL)
defer querySrv.Close()
queryAddr := querySrv.httpConn.Addr().String()
// Will try to load service names, this should return 200.
url := fmt.Sprintf("http://%s/api/services", queryAddr)

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
req, err := http.NewRequest("GET", url, nil)
require.NoError(t, err)
req.Header.Add(testCase.headerName, testCase.headerValue)

client := &http.Client{}
resp, err := client.Do(req)
require.NoError(t, err)
require.NotNil(t, resp)

assert.Equal(t, resp.StatusCode, http.StatusOK)
})
}
}
112 changes: 0 additions & 112 deletions plugin/storage/integration/token_propagation_test.go

This file was deleted.

77 changes: 13 additions & 64 deletions scripts/es-integration-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,6 @@ set -euxf -o pipefail

# use global variables to reflect status of db
db_is_up=
db_cid=

exit_trap_command="echo executing exit traps"
function cleanup {
eval "$exit_trap_command"
}
trap cleanup EXIT

function add_exit_trap {
local to_add=$1
exit_trap_command="$exit_trap_command; $to_add"
}

usage() {
echo $"Usage: $0 <elasticsearch|opensearch> <version>"
Expand Down Expand Up @@ -59,20 +47,6 @@ setup_opensearch() {
echo ${cid}
}

# bearer token propagaton test uses real query service, but starts a fake DB at 19200
setup_query() {
local distro=$1
local os=$(go env GOOS)
local arch=$(go env GOARCH)
local params=(
--es.tls.enabled=false
--es.version=7
--es.server-urls=http://127.0.0.1:19200
--query.bearer-token-propagation=true
)
SPAN_STORAGE_TYPE=${distro} ./cmd/query/query-${os}-${arch} ${params[@]}
}

wait_for_storage() {
local distro=$1
local url=$2
Expand Down Expand Up @@ -108,6 +82,8 @@ bring_up_storage() {
local distro=$1
local version=$2
local cid

echo "starting ${distro} ${version}"
for retry in 1 2 3
do
if [ ${distro} = "elasticsearch" ]; then
Expand All @@ -121,57 +97,30 @@ bring_up_storage() {
wait_for_storage ${distro} "http://localhost:9200" ${cid}
if [ ${db_is_up} = "1" ]; then
break
else
echo "ERROR: unable to start ${distro}"
exit 1
fi
done
db_cid=${cid}
if [ ${db_is_up} = "1" ]; then
trap "teardown_storage ${cid}" EXIT
else
echo "ERROR: unable to start ${distro}"
exit 1
fi
}

teardown_storage() {
local cid=$1
docker kill ${cid}
}

teardown_query() {
local pid=$1
kill -9 ${pid}
}

build_query() {
make build-crossdock-ui-placeholder
make build-query
}

run_integration_test() {
main() {
check_arg "$@"
local distro=$1
local version=$2

bring_up_storage ${distro} ${version}
STORAGE=${distro} make storage-integration-test
make index-cleaner-integration-test
make index-rollover-integration-test
}

run_token_propagation_test() {
local distro=$1
build_query
setup_query ${distro} &
local pid=$!
add_exit_trap "teardown_query ${pid}"
make token-propagation-integration-test
}

main() {
check_arg "$@"

echo "Preparing $1 $2"
bring_up_storage "$1" "$2"
add_exit_trap "teardown_storage ${db_cid}"

echo "Executing main integration tests"
run_integration_test "$1"

echo "Executing token propagation test"
run_token_propagation_test "$1"
}

main "$@"

0 comments on commit 65ad4fc

Please sign in to comment.