Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jobs:
needs:
- test
steps:
- uses: ory/ci/checkout@master
- uses: ory/ci/docs/cli-next@master
with:
token: ${{ secrets.ORY_BOT_PAT }}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ require (
github.com/urfave/negroni v1.0.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
gocloud.dev v0.20.0
golang.org/x/crypto v0.45.0
Expand Down Expand Up @@ -267,7 +268,6 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
go.opentelemetry.io/otel/exporters/zipkin v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
Expand Down Expand Up @@ -566,8 +564,6 @@ github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP
github.com/knadh/koanf/parsers/yaml v0.1.0/go.mod h1:cvbUDC7AL23pImuQP0oRw/hPuccrNBS2bps8asS0CwY=
github.com/knadh/koanf/providers/posflag v0.1.0 h1:mKJlLrKPcAP7Ootf4pBZWJ6J+4wHYujwipe7Ie3qW6U=
github.com/knadh/koanf/providers/posflag v0.1.0/go.mod h1:SYg03v/t8ISBNrMBRMlojH8OsKowbkXV7giIbBVgbz0=
github.com/knadh/koanf/providers/rawbytes v0.1.0 h1:dpzgu2KO6uf6oCb4aP05KDmKmAmI51k5pe8RYKQ0qME=
github.com/knadh/koanf/providers/rawbytes v0.1.0/go.mod h1:mMTB1/IcJ/yE++A2iEZbY1MLygX7vttU+C+S/YmPu9c=
github.com/knadh/koanf/v2 v2.2.2 h1:ghbduIkpFui3L587wavneC9e3WIliCgiCgdxYO/wd7A=
github.com/knadh/koanf/v2 v2.2.2/go.mod h1:abWQc0cBXLSF/PSOMCB/SK+T13NXDsPvOksbpi5e/9Q=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down
9 changes: 7 additions & 2 deletions pipeline/authz/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/pkg/errors"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

"github.com/ory/x/httpx"
"github.com/ory/x/otelx"
Expand Down Expand Up @@ -50,9 +51,11 @@ type AuthorizerRemote struct {

// NewAuthorizerRemote creates a new AuthorizerRemote.
func NewAuthorizerRemote(c configuration.Provider, d interface{ Tracer() trace.Tracer }) *AuthorizerRemote {
client := httpx.NewResilientClient().StandardClient()
client.Transport = otelhttp.NewTransport(client.Transport)
return &AuthorizerRemote{
c: c,
client: httpx.NewResilientClient().StandardClient(),
client: client,
t: x.NewTemplate("remote"),
tracer: d.Tracer(),
}
Expand Down Expand Up @@ -177,10 +180,12 @@ func (a *AuthorizerRemote) Config(config json.RawMessage) (*AuthorizerRemoteConf
return nil, err
}
timeout := time.Millisecond * duration
a.client = httpx.NewResilientClient(
client := httpx.NewResilientClient(
httpx.ResilientClientWithMaxRetryWait(maxWait),
httpx.ResilientClientWithConnectionTimeout(timeout),
).StandardClient()
client.Transport = otelhttp.NewTransport(client.Transport)
a.client = client

return &c, nil
}
9 changes: 7 additions & 2 deletions pipeline/authz/remote_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/pkg/errors"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

"github.com/ory/x/httpx"
"github.com/ory/x/otelx"
Expand Down Expand Up @@ -56,9 +57,11 @@ type AuthorizerRemoteJSON struct {

// NewAuthorizerRemoteJSON creates a new AuthorizerRemoteJSON.
func NewAuthorizerRemoteJSON(c configuration.Provider, d interface{ Tracer() trace.Tracer }) *AuthorizerRemoteJSON {
client := httpx.NewResilientClient().StandardClient()
client.Transport = otelhttp.NewTransport(client.Transport)
return &AuthorizerRemoteJSON{
c: c,
client: httpx.NewResilientClient().StandardClient(),
client: client,
t: x.NewTemplate("remote_json"),
tracer: d.Tracer(),
}
Expand Down Expand Up @@ -187,10 +190,12 @@ func (a *AuthorizerRemoteJSON) Config(config json.RawMessage) (*AuthorizerRemote
return nil, err
}
timeout := time.Millisecond * duration
a.client = httpx.NewResilientClient(
client := httpx.NewResilientClient(
httpx.ResilientClientWithMaxRetryWait(maxWait),
httpx.ResilientClientWithConnectionTimeout(timeout),
).StandardClient()
client.Transport = otelhttp.NewTransport(client.Transport)
a.client = client

return &c, nil
}
39 changes: 39 additions & 0 deletions pipeline/authz/remote_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package authz_test
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
Expand All @@ -15,6 +16,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/sjson"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"

"github.com/ory/x/configx"
"github.com/ory/x/logrusx"
Expand Down Expand Up @@ -360,3 +364,38 @@ func TestAuthorizerRemoteJSONConfig(t *testing.T) {
})
}
}

// This test must NOT use t.Parallel() because it mutates global OTEL state.
func TestAuthorizerRemoteJSONTracePropagation(t *testing.T) {
// Set up a real tracer provider so otelhttp.NewTransport creates sampled spans.
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))

prevTP := otel.GetTracerProvider()
prevProp := otel.GetTextMapPropagator()
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
t.Cleanup(func() {
otel.SetTracerProvider(prevTP)
otel.SetTextMapPropagator(prevProp)
_ = tp.Shutdown(context.Background())
})

var gotTraceparent string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotTraceparent = r.Header.Get("Traceparent")
w.WriteHeader(http.StatusOK)
}))
defer server.Close()

config := json.RawMessage(fmt.Sprintf(`{"remote":%q,"payload":"{}"}`, server.URL))

p, err := configuration.NewKoanfProvider(context.Background(), nil, logrusx.New("", ""))
require.NoError(t, err)

a := NewAuthorizerRemoteJSON(p, otelx.NewNoop())
r, err := http.NewRequestWithContext(context.Background(), "", "", nil)
require.NoError(t, err)
err = a.Authorize(r, &authn.AuthenticationSession{}, config, &rule.Rule{})
require.NoError(t, err)
assert.NotEmpty(t, gotTraceparent, "expected traceparent header to be propagated to remote_json authorizer endpoint")
}
40 changes: 40 additions & 0 deletions pipeline/authz/remote_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package authz_test
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
Expand All @@ -15,6 +16,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/sjson"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
sdktrace "go.opentelemetry.io/otel/sdk/trace"

"github.com/ory/x/configx"
"github.com/ory/x/logrusx"
Expand Down Expand Up @@ -281,3 +285,39 @@ func TestAuthorizerRemoteValidate(t *testing.T) {
})
}
}

// This test must NOT use t.Parallel() because it mutates global OTEL state.
func TestAuthorizerRemoteTracePropagation(t *testing.T) {
// Set up a real tracer provider so otelhttp.NewTransport creates sampled spans.
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))

prevTP := otel.GetTracerProvider()
prevProp := otel.GetTextMapPropagator()
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.TraceContext{})
t.Cleanup(func() {
otel.SetTracerProvider(prevTP)
otel.SetTextMapPropagator(prevProp)
_ = tp.Shutdown(context.Background())
})

var gotTraceparent string
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotTraceparent = r.Header.Get("Traceparent")
w.WriteHeader(http.StatusOK)
}))
defer server.Close()

config := json.RawMessage(fmt.Sprintf(`{"remote":%q}`, server.URL))

p, err := configuration.NewKoanfProvider(context.Background(), nil, logrusx.New("", ""))
require.NoError(t, err)

a := NewAuthorizerRemote(p, otelx.NewNoop())
r, err := http.NewRequestWithContext(context.Background(), "POST", "", nil)
require.NoError(t, err)
r.Header.Set("Content-Type", "text/plain")
err = a.Authorize(r, &authn.AuthenticationSession{}, config, &rule.Rule{})
require.NoError(t, err)
assert.NotEmpty(t, gotTraceparent, "expected traceparent header to be propagated to remote authorizer endpoint")
}
Loading