Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
7 changes: 7 additions & 0 deletions themis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ token:
- key: uuid
header: X-Midt-Uuid
parameter: uuid
pathValues:
- key: mac
header: X-Midt-Mac-Address
parameter: mac
remote:
method: GET
url: https://localhost:443/device/{mac}/claims?format=json
partnerID:
claim: partner-id
metadata: pid
Expand Down
11 changes: 8 additions & 3 deletions token/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ type Request struct {
// metadata is available to lower levels of infrastructure used by the Factory.
Metadata map[string]interface{}

// PathValues holds non-claim information about the request, usually garnered from the original HTTP request. This
// PathValues is available to remote claim builders.
PathValues map[string]interface{}

// TLS represents the state of any underlying TLS connection.
// For non-tls connections, this field is unset.
TLS *tls.ConnectionState
Expand All @@ -42,9 +46,10 @@ type Request struct {
// NewRequest returns an empty, fully initialized token Request
func NewRequest() *Request {
return &Request{
Logger: sallust.Default(),
Claims: make(map[string]interface{}),
Metadata: make(map[string]interface{}),
Logger: sallust.Default(),
Claims: make(map[string]interface{}),
Metadata: make(map[string]interface{}),
PathValues: make(map[string]interface{}),
}
}

Expand Down
8 changes: 8 additions & 0 deletions token/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ type PartnerID struct {
// is set and thus the partner id won't be transmitted to remote systems.
Metadata string

// PathValue is the name of the path value key for the partner id. If unset, no path value
// is set and thus the partner id won't be transmitted to remote systems via url path value.
PathValue string

// Header is the HTTP header containing the partner id
Header string

Expand Down Expand Up @@ -200,6 +204,10 @@ type Options struct {
// Metadata describes non-claim data, which can be statically configured or supplied via a request
Metadata []Value

// PathValues holds non-claim information about the request, usually garnered from the original HTTP request. This
// PathValues is available to remote claim builders.
PathValues []Value

// PartnerID is the optional partner id configuration. If unset, no partner id processing is
// performed, though a partner id may still be configured as part of the claims.
PartnerID *PartnerID
Expand Down
40 changes: 39 additions & 1 deletion token/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func metadataSetter(key string, value interface{}, tr *Request) {
tr.Metadata[key] = value
}

func pathValuesSetter(key string, value interface{}, tr *Request) {
tr.PathValues[key] = value
}

type headerParameterRequestBuilder struct {
key string
header string
Expand Down Expand Up @@ -204,6 +208,10 @@ func (prb partnerIDRequestBuilder) Build(original *http.Request, tr *Request) er
if len(prb.Metadata) > 0 {
tr.Metadata[prb.Metadata] = partnerID
}

if len(prb.PathValue) > 0 {
tr.PathValues[prb.PathValue] = partnerID
}
}

return nil
Expand Down Expand Up @@ -282,7 +290,37 @@ func NewRequestBuilders(o Options) (RequestBuilders, error) {
}
}

if o.PartnerID != nil && (len(o.PartnerID.Claim) > 0 || len(o.PartnerID.Metadata) > 0) {
for _, value := range o.PathValues {
switch {
case len(value.Key) == 0:
return nil, ErrMissingKey

case len(value.Header) > 0 || len(value.Parameter) > 0:
if len(value.Variable) > 0 {
return nil, ErrVariableNotAllowed
}

rb = append(rb,
headerParameterRequestBuilder{
key: value.Key,
header: http.CanonicalHeaderKey(value.Header),
parameter: value.Parameter,
setter: pathValuesSetter,
},
)

case len(value.Variable) > 0:
rb = append(rb,
variableRequestBuilder{
key: value.Key,
variable: value.Variable,
setter: pathValuesSetter,
},
)
}
}

if o.PartnerID != nil && (len(o.PartnerID.Claim) > 0 || len(o.PartnerID.Metadata) > 0 || len(o.PartnerID.PathValue) > 0) {
rb = append(rb,
partnerIDRequestBuilder{
PartnerID: *o.PartnerID,
Expand Down
110 changes: 90 additions & 20 deletions token/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@ func testNewRequestBuildersInvalidMetadata(t *testing.T) {
assert.Empty(rb)
}

func testNewRequestBuildersInvalidPathValues(t *testing.T) {
assert := assert.New(t)
rb, err := NewRequestBuilders(Options{
PathValues: []Value{
{
Key: "bad",
Header: "xxx",
Parameter: "yyy",
Variable: "zzz",
},
},
})

assert.Equal(ErrVariableNotAllowed, err)
assert.Empty(rb)
}
func testNewRequestBuildersSuccess(t *testing.T) {
testData := []struct {
options Options
Expand Down Expand Up @@ -89,16 +105,24 @@ func testNewRequestBuildersSuccess(t *testing.T) {
Header: "X-Missing",
},
},
PathValues: []Value{
{
Key: "fromHeader",
Header: "X-PathVlaue",
},
},
PartnerID: &PartnerID{
Claim: "partner-id-claim",
Metadata: "partner-id-metadata",
Header: "X-Midt-Partner-ID",
Claim: "partner-id-claim",
Metadata: "partner-id-metadata",
PathValue: "partner-id-pathValue",
Header: "X-Midt-Partner-ID",
},
},
uri: "/test",
header: http.Header{
"X-Claim": []string{"foo"},
"X-Metadata": []string{"bar"},
"X-PathVlaue": []string{"foobar"},
"X-Midt-Partner-ID": []string{"test"},
},
expected: &Request{
Expand All @@ -111,6 +135,10 @@ func testNewRequestBuildersSuccess(t *testing.T) {
"fromHeader": "bar",
"partner-id-metadata": "test",
},
PathValues: map[string]any{
"fromHeader": "foobar",
"partner-id-pathValue": "test",
},
},
},
{
Expand All @@ -135,13 +163,24 @@ func testNewRequestBuildersSuccess(t *testing.T) {
Parameter: "missing",
},
},
PathValues: []Value{
{
Key: "fromParameter",
Parameter: "pathValue",
},
{
Key: "missing",
Parameter: "missing",
},
},
PartnerID: &PartnerID{
Claim: "partner-id-claim",
Metadata: "partner-id-metadata",
PathValue: "partner-id-pathValue",
Parameter: "pid",
},
},
uri: "/test?pid=test&claim=foo&metadata=bar",
uri: "/test?pid=test&claim=foo&metadata=bar&pathValue=foobar",
expected: &Request{
Logger: sallust.Default(),
Claims: map[string]interface{}{
Expand All @@ -152,6 +191,10 @@ func testNewRequestBuildersSuccess(t *testing.T) {
"fromParameter": "bar",
"partner-id-metadata": "test",
},
PathValues: map[string]any{
"fromParameter": "foobar",
"partner-id-pathValue": "test",
},
},
},
{
Expand All @@ -168,17 +211,25 @@ func testNewRequestBuildersSuccess(t *testing.T) {
Variable: "metadata",
},
},
PathValues: []Value{
{
Key: "fromVariable",
Variable: "pathValues",
},
},
PartnerID: &PartnerID{
Claim: "partner-id-claim",
Metadata: "partner-id-metadata",
PathValue: "partner-id-pathValue",
Parameter: "pid",
Default: "test",
},
},
uri: "/test/foo/bar",
urlVariables: map[string]string{
"claim": "foo",
"metadata": "bar",
"claim": "foo",
"metadata": "bar",
"pathValues": "foobar",
},
expected: &Request{
Logger: sallust.Default(),
Expand All @@ -190,6 +241,10 @@ func testNewRequestBuildersSuccess(t *testing.T) {
"fromVariable": "bar",
"partner-id-metadata": "test",
},
PathValues: map[string]any{
"fromVariable": "foobar",
"partner-id-pathValue": "test",
},
},
},
{
Expand All @@ -206,11 +261,18 @@ func testNewRequestBuildersSuccess(t *testing.T) {
Variable: "metadata",
},
},
PathValues: []Value{
{
Key: "fromVariable",
Variable: "pathValue",
},
},
},
uri: "/test/foo/bar",
urlVariables: map[string]string{
"claim": "foo",
"metadata": "bar",
"claim": "foo",
"metadata": "bar",
"pathValue": "foobar",
},
expected: &Request{
Logger: sallust.Default(),
Expand All @@ -220,6 +282,9 @@ func testNewRequestBuildersSuccess(t *testing.T) {
Metadata: map[string]interface{}{
"fromVariable": "bar",
},
PathValues: map[string]any{
"fromVariable": "foobar",
},
},
},
}
Expand Down Expand Up @@ -316,6 +381,7 @@ func testNewRequestBuildersInvalidPartnerID(t *testing.T) {
func TestNewRequestBuilders(t *testing.T) {
t.Run("InvalidClaim", testNewRequestBuildersInvalidClaim)
t.Run("InvalidMetadata", testNewRequestBuildersInvalidMetadata)
t.Run("InvalidPathValues", testNewRequestBuildersInvalidPathValues)
t.Run("MissingVariable", testNewRequestBuildersMissingVariable)
t.Run("InvalidPartnerID", testNewRequestBuildersInvalidPartnerID)
t.Run("Success", testNewRequestBuildersSuccess)
Expand All @@ -341,9 +407,10 @@ func testBuildRequestSuccess(t *testing.T) {
}),
},
expected: &Request{
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim": []int{1, 2, 3}},
Metadata: make(map[string]interface{}),
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim": []int{1, 2, 3}},
Metadata: make(map[string]interface{}),
PathValues: make(map[string]interface{}),
},
},
{
Expand All @@ -354,9 +421,10 @@ func testBuildRequestSuccess(t *testing.T) {
}),
},
expected: &Request{
Logger: sallust.Default(),
Claims: make(map[string]interface{}),
Metadata: map[string]interface{}{"metadata": -75.8},
Logger: sallust.Default(),
Claims: make(map[string]interface{}),
Metadata: map[string]interface{}{"metadata": -75.8},
PathValues: make(map[string]interface{}),
},
},
{
Expand All @@ -376,9 +444,10 @@ func testBuildRequestSuccess(t *testing.T) {
}),
},
expected: &Request{
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim1": 238947123, "claim2": []byte{1, 2, 3}},
Metadata: map[string]interface{}{"metadata1": "value1", "metadata2": 15.7},
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim1": 238947123, "claim2": []byte{1, 2, 3}},
Metadata: map[string]interface{}{"metadata1": "value1", "metadata2": 15.7},
PathValues: make(map[string]interface{}),
},
},
}
Expand Down Expand Up @@ -569,9 +638,10 @@ func testDecodeServerRequestSuccess(t *testing.T) {
require.IsType((*Request)(nil), v)
assert.Equal(
Request{
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim": "value"},
Metadata: make(map[string]interface{}),
Logger: sallust.Default(),
Claims: map[string]interface{}{"claim": "value"},
Metadata: make(map[string]interface{}),
PathValues: make(map[string]interface{}),
},
*v.(*Request),
)
Expand Down
Loading