From 1a653144bf884b0f74ff0fd577b3a3ab15933395 Mon Sep 17 00:00:00 2001 From: yaron2 Date: Wed, 25 Jan 2023 15:03:43 -0800 Subject: [PATCH] add security token header support Signed-off-by: yaron2 --- bindings/http/http.go | 17 ++++++++++---- bindings/http/http_test.go | 47 +++++++++++++++++++++++++++++++++---- bindings/http/metadata.yaml | 11 +++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/bindings/http/http.go b/bindings/http/http.go index 5fc22dfb4..00b55e8ce 100644 --- a/bindings/http/http.go +++ b/bindings/http/http.go @@ -45,6 +45,8 @@ const ( TraceparentHeaderKey = "traceparent" TracestateHeaderKey = "tracestate" TraceMetadataKey = "traceHeaders" + securityToken = "securityToken" + securityTokenHeader = "securityTokenHeader" ) // HTTPSource is a binding for an http url endpoint invocation @@ -58,10 +60,12 @@ type HTTPSource struct { } type httpMetadata struct { - URL string `mapstructure:"url"` - MTLSClientCert string `mapstructure:"mtlsClientCert"` - MTLSClientKey string `mapstructure:"mtlsClientKey"` - MTLSRootCA string `mapstructure:"mtlsRootCA"` + URL string `mapstructure:"url"` + MTLSClientCert string `mapstructure:"mtlsClientCert"` + MTLSClientKey string `mapstructure:"mtlsClientKey"` + MTLSRootCA string `mapstructure:"mtlsRootCA"` + SecurityToken string `mapstructure:"securityToken"` + SecurityTokenHeader string `mapstructure:"securityTokenHeader"` } // NewHTTP returns a new HTTPSource. @@ -233,6 +237,11 @@ func (h *HTTPSource) Invoke(ctx context.Context, req *bindings.InvokeRequest) (* request.Header.Set("Accept", "application/json; charset=utf-8") } + // Set security token values if set. + if h.metadata.SecurityToken != "" && h.metadata.SecurityTokenHeader != "" { + request.Header.Set(h.metadata.SecurityTokenHeader, h.metadata.SecurityToken) + } + // Any metadata keys that start with a capital letter // are treated as request headers for mdKey, mdValue := range req.Metadata { diff --git a/bindings/http/http_test.go b/bindings/http/http_test.go index dd64afa0c..017f47c4c 100644 --- a/bindings/http/http_test.go +++ b/bindings/http/http_test.go @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package http_test +package http import ( "context" @@ -31,13 +31,12 @@ import ( "github.com/stretchr/testify/require" "github.com/dapr/components-contrib/bindings" - bindingHttp "github.com/dapr/components-contrib/bindings/http" "github.com/dapr/components-contrib/metadata" "github.com/dapr/kit/logger" ) func TestOperations(t *testing.T) { - opers := (*bindingHttp.HTTPSource)(nil).Operations() + opers := (*HTTPSource)(nil).Operations() assert.Equal(t, []bindings.OperationKind{ bindings.CreateOperation, "get", @@ -132,7 +131,7 @@ func InitBinding(s *httptest.Server, extraProps map[string]string) (bindings.Out } } - hs := bindingHttp.NewHTTP(logger.NewLogger("test")) + hs := NewHTTP(logger.NewLogger("test")) err := hs.Init(m) return hs, err } @@ -166,6 +165,44 @@ func TestNon2XXErrorsSuppressed(t *testing.T) { verifyNon2XXErrorsSuppressed(t, hs, handler) } +func TestSecurityTokenHeaderForwarded(t *testing.T) { + handler := NewHTTPHandler() + s := httptest.NewServer(handler) + defer s.Close() + + t.Run("security token headers are forwarded", func(t *testing.T) { + hs, err := InitBinding(s, map[string]string{securityTokenHeader: "X-Token", securityToken: "12345"}) + require.NoError(t, err) + + req := TestCase{ + input: "GET", + operation: "get", + path: "/", + err: "", + statusCode: 200, + }.ToInvokeRequest() + _, err = hs.Invoke(context.Background(), &req) + assert.NoError(t, err) + assert.Equal(t, "12345", handler.Headers["X-Token"]) + }) + + t.Run("security token headers are forwarded", func(t *testing.T) { + hs, err := InitBinding(s, nil) + require.NoError(t, err) + + req := TestCase{ + input: "GET", + operation: "get", + path: "/", + err: "", + statusCode: 200, + }.ToInvokeRequest() + _, err = hs.Invoke(context.Background(), &req) + assert.NoError(t, err) + assert.Empty(t, handler.Headers["X-Token"]) + }) +} + func TestTraceHeadersForwarded(t *testing.T) { handler := NewHTTPHandler() s := httptest.NewServer(handler) @@ -231,7 +268,7 @@ func InitBindingForHTTPS(s *httptest.Server, extraProps map[string]string) (bind for k, v := range extraProps { m.Properties[k] = v } - hs := bindingHttp.NewHTTP(logger.NewLogger("test")) + hs := NewHTTP(logger.NewLogger("test")) err := hs.Init(m) return hs, err } diff --git a/bindings/http/metadata.yaml b/bindings/http/metadata.yaml index 007ed5ec3..988149347 100644 --- a/bindings/http/metadata.yaml +++ b/bindings/http/metadata.yaml @@ -54,3 +54,14 @@ metadata: description: "The client certificate key to present to server to enable client verification" binding: output: true + - name: securityToken + required: false + description: "The security token to include on an outgoing HTTP request as a header" + binding: + output: true + - name: securityTokenHeader + required: false + description: "The header name on an outgoing HTTP request for a security token" + binding: + output: true +