From b04d24441fcf700d3e3d6507ae90e3b5d34c7017 Mon Sep 17 00:00:00 2001 From: Ahmet Soormally Date: Fri, 8 Jun 2018 09:17:54 +0100 Subject: [PATCH 1/6] bump go 1.8 to 1.9 version support --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ce622dd26cb..deebb9355fa 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,12 @@ Tyk is a lightweight, open source API Gateway and Management Platform enables you to control who accesses your API, when they access it and how they access it. Tyk will also record detailed analytics on how your users are interacting with your API and when things go wrong. -Go version 1.8 or later is required to build `master`, the current +Go version 1.9 is required to build `master`, the current development version. Tyk is officially supported on `linux/amd64`, `linux/i386` and `linux/arm64`. +Tests are run against both Go versions 1.9 & 1.10, however at present, only Go 1.9 is officially supported. + ## What is an API Gateway? An API Gateway sits in front of your application(s) and manages the heavy lifting of authorisation, access control and throughput limiting to your services. Ideally, From f1062303deccaf1b425092c17d37f51acd2fdaf8 Mon Sep 17 00:00:00 2001 From: dencoded <33698537+dencoded@users.noreply.github.com> Date: Fri, 8 Jun 2018 00:27:37 -0400 Subject: [PATCH 2/6] added optimizations, added mw tests and benchmarks --- mw_context_vars.go | 39 +++---- mw_context_vars_test.go | 222 +++++++++++++++++++++++++++++++--------- 2 files changed, 189 insertions(+), 72 deletions(-) diff --git a/mw_context_vars.go b/mw_context_vars.go index dfd111ec024..8e5aec4f575 100644 --- a/mw_context_vars.go +++ b/mw_context_vars.go @@ -23,37 +23,24 @@ func (m *MiddlewareContextVars) EnabledForSpec() bool { // ProcessRequest will run any checks on the request on the way through the system, return an error to have the chain fail func (m *MiddlewareContextVars) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) { + r.ParseForm() + + contextDataObject := map[string]interface{}{ + "request_data": r.Form, // Form params (map[string][]string) + "headers": map[string][]string(r.Header), + "headers_Host": r.Host, + "path_parts": strings.Split(r.URL.Path, "/"), // Path parts + "path": r.URL.Path, // path data + "remote_addr": request.RealIP(r), // IP + "request_id": uuid.NewV4().String(), //Correlation ID + } - copiedRequest := copyRequest(r) - contextDataObject := make(map[string]interface{}) - - copiedRequest.ParseForm() - - // Form params (map[string][]string) - contextDataObject["request_data"] = copiedRequest.Form - - contextDataObject["headers"] = map[string][]string(copiedRequest.Header) - - for hname, vals := range copiedRequest.Header { + for hname, vals := range r.Header { n := "headers_" + strings.Replace(hname, "-", "_", -1) contextDataObject[n] = vals[0] } - contextDataObject["headers_Host"] = copiedRequest.Host - - // Path parts - segmentedPathArray := strings.Split(copiedRequest.URL.Path, "/") - contextDataObject["path_parts"] = segmentedPathArray - - // path data - contextDataObject["path"] = copiedRequest.URL.Path - - // IP - contextDataObject["remote_addr"] = request.RealIP(copiedRequest) - - //Correlation ID - contextDataObject["request_id"] = uuid.NewV4().String() - for _, c := range copiedRequest.Cookies() { + for _, c := range r.Cookies() { name := "cookies_" + strings.Replace(c.Name, "-", "_", -1) contextDataObject[name] = c.Value } diff --git a/mw_context_vars_test.go b/mw_context_vars_test.go index 21d51b5c114..dd6871dfecc 100644 --- a/mw_context_vars_test.go +++ b/mw_context_vars_test.go @@ -1,16 +1,19 @@ package main import ( - "errors" + "io" "net/http" "net/http/httptest" + "net/url" + "reflect" + "strings" "testing" "github.com/TykTechnologies/tyk/apidef" "github.com/TykTechnologies/tyk/test" ) -func testPreparetContextVarsMiddleware() { +func testPrepareContextVarsMiddleware() { buildAndLoadAPI(func(spec *APISpec) { spec.Proxy.ListenPath = "/" spec.EnableContextVars = true @@ -32,7 +35,7 @@ func TestContextVarsMiddleware(t *testing.T) { ts := newTykTestServer() defer ts.Close() - testPreparetContextVarsMiddleware() + testPrepareContextVarsMiddleware() ts.Run(t, []test.TestCase{ {Path: "/test/path", Code: 200, BodyMatch: `"X-Remote-Addr":"127.0.0.1"`}, @@ -48,7 +51,7 @@ func BenchmarkContextVarsMiddleware(b *testing.B) { ts := newTykTestServer() defer ts.Close() - testPreparetContextVarsMiddleware() + testPrepareContextVarsMiddleware() for i := 0; i < b.N; i++ { ts.Run(b, []test.TestCase{ @@ -60,53 +63,180 @@ func BenchmarkContextVarsMiddleware(b *testing.B) { } } -func TestMiddlewareContextVars_ProcessRequest_cookies(t *testing.T) { - - req, _ := http.NewRequest(http.MethodGet, "/", nil) - res := httptest.NewRecorder() - - req.Header.Set("Cookie", "abc=123; def=456") - - err, code := (&MiddlewareContextVars{}).ProcessRequest(res, req, nil) - if err != nil { - t.Fatal(err) - } - - if code != http.StatusOK { - t.Fatal(errors.New("non 200 status code")) - } - - ctx := ctxGetData(req) - - if ctx["cookies_abc"].(string) != "123" { - t.Error("abc should be 123") - } +type testContextVarsData struct { + Method string + URL string + Data string + ExpectedCtxDataObject map[string]interface{} + Header http.Header +} - if ctx["cookies_def"].(string) != "456" { - t.Error("def should be 456") +func testPrepareTestContextVarsMiddleware() map[string]testContextVarsData { + return map[string]testContextVarsData{ + "GET with query string": { + Method: http.MethodGet, + URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", + Header: http.Header{ + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + }, + ExpectedCtxDataObject: map[string]interface{}{ + "remote_addr": "192.0.2.1", + "request_data": url.Values{ + "x": {"123"}, + "y": {"test"}, + }, + "headers": map[string][]string{ + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + }, + "headers_x_header_a": "A", + "headers_x_header_b": "B", + "headers_x_header_c": "C", + "headers_Host": "abc.com", + "path_parts": []string{"", "aaa", "bbb", "111", "222"}, + "path": "/aaa/bbb/111/222", + }, + }, + "POST with query string and encoded form data": { + Method: http.MethodPost, + URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", + Data: "i=1&j=2&str=abc", + Header: http.Header{ + "Content-Type": {"application/x-www-form-urlencoded"}, + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + }, + ExpectedCtxDataObject: map[string]interface{}{ + "remote_addr": "192.0.2.1", + "request_data": url.Values{ + "x": {"123"}, + "y": {"test"}, + "i": {"1"}, + "j": {"2"}, + "str": {"abc"}, + }, + "headers": map[string][]string{ + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + "Content-Type": {"application/x-www-form-urlencoded"}, + }, + "headers_x_header_a": "A", + "headers_x_header_b": "B", + "headers_x_header_c": "C", + "headers_Content_Type": "application/x-www-form-urlencoded", + "headers_Host": "abc.com", + "path_parts": []string{"", "aaa", "bbb", "111", "222"}, + "path": "/aaa/bbb/111/222", + }, + }, + "POST with query string and encoded form data and cookies": { + Method: http.MethodPost, + URL: "http://abc.com/aaa/bbb/111/222?x=123&y=test", + Data: "i=1&j=2&str=abc", + Header: http.Header{ + "Content-Type": {"application/x-www-form-urlencoded"}, + "Cookie": {"c-1=cookie1;c-2=cookie2"}, + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + }, + ExpectedCtxDataObject: map[string]interface{}{ + "remote_addr": "192.0.2.1", + "request_data": url.Values{ + "x": {"123"}, + "y": {"test"}, + "i": {"1"}, + "j": {"2"}, + "str": {"abc"}, + }, + "headers": map[string][]string{ + "x-header-a": {"A"}, + "x-header-b": {"B"}, + "x-header-c": {"C"}, + "Content-Type": {"application/x-www-form-urlencoded"}, + "Cookie": {"c-1=cookie1;c-2=cookie2"}, + }, + "headers_x_header_a": "A", + "headers_x_header_b": "B", + "headers_x_header_c": "C", + "headers_Content_Type": "application/x-www-form-urlencoded", + "headers_Cookie": "c-1=cookie1;c-2=cookie2", + "headers_Host": "abc.com", + "cookies_c_1": "cookie1", + "cookies_c_2": "cookie2", + "path_parts": []string{"", "aaa", "bbb", "111", "222"}, + "path": "/aaa/bbb/111/222", + }, + }, } +} - if ctx["cookies_ghi"] != nil { - t.Error("ghi should be nil") +func TestContextVarsMiddlewareProcessRequest(t *testing.T) { + mw := &MiddlewareContextVars{} + + tests := testPrepareTestContextVarsMiddleware() + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + var bodyReader io.Reader + if test.Data != "" { + bodyReader = strings.NewReader(test.Data) + } + req := httptest.NewRequest(test.Method, test.URL, bodyReader) + req.Header = test.Header + err, code := mw.ProcessRequest(nil, req, nil) + if err != nil { + t.Error(err) + } + if code != http.StatusOK { + t.Errorf("Wrong response code: %d Eexpected 200.", code) + } + + ctxDataObject := ctxGetData(req) + + // check request_id + if _, ok := ctxDataObject["request_id"].(string); !ok { + t.Error("Missing 'request_id' field") + } + + // delete request_if to do DeepEqual + delete(ctxDataObject, "request_id") + + if !reflect.DeepEqual(ctxDataObject, test.ExpectedCtxDataObject) { + t.Errorf("Expected: %v\n Got: %v\n", test.ExpectedCtxDataObject, ctxDataObject) + } + }) } } -func BenchmarkMiddlewareContextVars_ProcessRequest_cookies(b *testing.B) { - b.ReportAllocs() - - req, _ := http.NewRequest(http.MethodGet, "/", nil) - res := httptest.NewRecorder() - - req.Header.Set("Cookie", "abc=123; def=456") - - for i := 0; i < b.N; i++ { - err, code := (&MiddlewareContextVars{}).ProcessRequest(res, req, nil) - if err != nil { - b.Fatal(err) - } - if code != http.StatusOK { - b.Fatal(errors.New("non 200 status code")) - } +func BenchmarkContextVarsMiddlewareProcessRequest(b *testing.B) { + mw := &MiddlewareContextVars{} + tests := testPrepareTestContextVarsMiddleware() + var err error + var code int + for name, test := range tests { + b.Run(name, func(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + var bodyReader io.Reader + if test.Data != "" { + bodyReader = strings.NewReader(test.Data) + } + req := httptest.NewRequest(test.Method, test.URL, bodyReader) + req.Header = test.Header + err, code = mw.ProcessRequest(nil, req, nil) + if err != nil { + b.Error(err) + } + if code != http.StatusOK { + b.Errorf("Wrong response code: %d Eexpected 200.", code) + } + } + }) } - } From 0c6df69dcf77a374cb3631d60f48527ce23d9974 Mon Sep 17 00:00:00 2001 From: Matias Insaurralde Date: Thu, 31 May 2018 15:20:05 -0400 Subject: [PATCH 3/6] coprocess: use metadata as map[string]string, enhance conversion --- coprocess.go | 16 +-- .../python/coprocess_session_state_pb2.py | 67 ++++++++-- .../ruby/coprocess_session_state_pb.rb | 2 +- coprocess/coprocess_session_state.pb.go | 125 +++++++++--------- coprocess/proto/coprocess_session_state.proto | 2 +- coprocess/python/tyk/middleware.py | 4 +- coprocess_helpers.go | 29 +++- 7 files changed, 155 insertions(+), 90 deletions(-) diff --git a/coprocess.go b/coprocess.go index 549b5b44852..ba49a7d355c 100644 --- a/coprocess.go +++ b/coprocess.go @@ -136,13 +136,6 @@ func (c *CoProcessor) ObjectFromRequest(r *http.Request) *coprocess.Object { if c.HookType != coprocess.HookType_Pre && c.HookType != coprocess.HookType_CustomKeyCheck { if session := ctxGetSession(r); session != nil { object.Session = ProtoSessionState(session) - // If the session contains metadata, add items to the object's metadata map: - if len(session.MetaData) > 0 { - object.Metadata = make(map[string]string) - for k, v := range session.MetaData { - object.Metadata[k] = v.(string) - } - } } } @@ -278,7 +271,10 @@ func (m *CoProcessMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Requ coProcessor.ObjectPostProcess(returnObject, r) - token := returnObject.Metadata["token"] + var token string + if returnObject.Session != nil { + token = returnObject.Session.Metadata["token"] + } // The CP middleware indicates this is a bad auth: if returnObject.Request.ReturnOverrides.ResponseCode > 400 { @@ -320,10 +316,6 @@ func (m *CoProcessMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Requ returnedSession := TykSessionState(returnObject.Session) - // If the returned object contains metadata, add them to the session: - for k, v := range returnObject.Metadata { - returnedSession.MetaData[k] = string(v) - } if extractor == nil { sessionLifetime := returnedSession.Lifetime(m.Spec.SessionLifetime) // This API is not using the ID extractor, but we've got a session: diff --git a/coprocess/bindings/python/coprocess_session_state_pb2.py b/coprocess/bindings/python/coprocess_session_state_pb2.py index b313d51753c..c342655627b 100644 --- a/coprocess/bindings/python/coprocess_session_state_pb2.py +++ b/coprocess/bindings/python/coprocess_session_state_pb2.py @@ -19,7 +19,7 @@ name='coprocess_session_state.proto', package='coprocess', syntax='proto3', - serialized_pb=_b('\n\x1d\x63oprocess_session_state.proto\x12\tcoprocess\"*\n\nAccessSpec\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0f\n\x07methods\x18\x02 \x03(\t\"s\n\x10\x41\x63\x63\x65ssDefinition\x12\x10\n\x08\x61pi_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61pi_id\x18\x02 \x01(\t\x12\x10\n\x08versions\x18\x03 \x03(\t\x12+\n\x0c\x61llowed_urls\x18\x04 \x03(\x0b\x32\x15.coprocess.AccessSpec\"/\n\rBasicAuthData\x12\x10\n\x08password\x18\x01 \x01(\t\x12\x0c\n\x04hash\x18\x02 \x01(\t\"\x19\n\x07JWTData\x12\x0e\n\x06secret\x18\x01 \x01(\t\"!\n\x07Monitor\x12\x16\n\x0etrigger_limits\x18\x01 \x03(\x01\"\xa5\x07\n\x0cSessionState\x12\x12\n\nlast_check\x18\x01 \x01(\x03\x12\x11\n\tallowance\x18\x02 \x01(\x01\x12\x0c\n\x04rate\x18\x03 \x01(\x01\x12\x0b\n\x03per\x18\x04 \x01(\x01\x12\x0f\n\x07\x65xpires\x18\x05 \x01(\x03\x12\x11\n\tquota_max\x18\x06 \x01(\x03\x12\x14\n\x0cquota_renews\x18\x07 \x01(\x03\x12\x17\n\x0fquota_remaining\x18\x08 \x01(\x03\x12\x1a\n\x12quota_renewal_rate\x18\t \x01(\x03\x12@\n\raccess_rights\x18\n \x03(\x0b\x32).coprocess.SessionState.AccessRightsEntry\x12\x0e\n\x06org_id\x18\x0b \x01(\t\x12\x17\n\x0foauth_client_id\x18\x0c \x01(\t\x12:\n\noauth_keys\x18\r \x03(\x0b\x32&.coprocess.SessionState.OauthKeysEntry\x12\x31\n\x0f\x62\x61sic_auth_data\x18\x0e \x01(\x0b\x32\x18.coprocess.BasicAuthData\x12$\n\x08jwt_data\x18\x0f \x01(\x0b\x32\x12.coprocess.JWTData\x12\x14\n\x0chmac_enabled\x18\x10 \x01(\x08\x12\x13\n\x0bhmac_secret\x18\x11 \x01(\t\x12\x13\n\x0bis_inactive\x18\x12 \x01(\x08\x12\x17\n\x0f\x61pply_policy_id\x18\x13 \x01(\t\x12\x14\n\x0c\x64\x61ta_expires\x18\x14 \x01(\x03\x12#\n\x07monitor\x18\x15 \x01(\x0b\x32\x12.coprocess.Monitor\x12!\n\x19\x65nable_detailed_recording\x18\x16 \x01(\x08\x12\x10\n\x08metadata\x18\x17 \x01(\t\x12\x0c\n\x04tags\x18\x18 \x03(\t\x12\r\n\x05\x61lias\x18\x19 \x01(\t\x12\x14\n\x0clast_updated\x18\x1a \x01(\t\x12\x1d\n\x15id_extractor_deadline\x18\x1b \x01(\x03\x12\x18\n\x10session_lifetime\x18\x1c \x01(\x03\x12\x16\n\x0e\x61pply_policies\x18\x1d \x03(\t\x12\x13\n\x0b\x63\x65rtificate\x18\x1e \x01(\t\x1aP\n\x11\x41\x63\x63\x65ssRightsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x1b.coprocess.AccessDefinition:\x02\x38\x01\x1a\x30\n\x0eOauthKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x62\x06proto3') + serialized_pb=_b('\n\x1d\x63oprocess_session_state.proto\x12\tcoprocess\"*\n\nAccessSpec\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x0f\n\x07methods\x18\x02 \x03(\t\"s\n\x10\x41\x63\x63\x65ssDefinition\x12\x10\n\x08\x61pi_name\x18\x01 \x01(\t\x12\x0e\n\x06\x61pi_id\x18\x02 \x01(\t\x12\x10\n\x08versions\x18\x03 \x03(\t\x12+\n\x0c\x61llowed_urls\x18\x04 \x03(\x0b\x32\x15.coprocess.AccessSpec\"/\n\rBasicAuthData\x12\x10\n\x08password\x18\x01 \x01(\t\x12\x0c\n\x04hash\x18\x02 \x01(\t\"\x19\n\x07JWTData\x12\x0e\n\x06secret\x18\x01 \x01(\t\"!\n\x07Monitor\x12\x16\n\x0etrigger_limits\x18\x01 \x03(\x01\"\xfd\x07\n\x0cSessionState\x12\x12\n\nlast_check\x18\x01 \x01(\x03\x12\x11\n\tallowance\x18\x02 \x01(\x01\x12\x0c\n\x04rate\x18\x03 \x01(\x01\x12\x0b\n\x03per\x18\x04 \x01(\x01\x12\x0f\n\x07\x65xpires\x18\x05 \x01(\x03\x12\x11\n\tquota_max\x18\x06 \x01(\x03\x12\x14\n\x0cquota_renews\x18\x07 \x01(\x03\x12\x17\n\x0fquota_remaining\x18\x08 \x01(\x03\x12\x1a\n\x12quota_renewal_rate\x18\t \x01(\x03\x12@\n\raccess_rights\x18\n \x03(\x0b\x32).coprocess.SessionState.AccessRightsEntry\x12\x0e\n\x06org_id\x18\x0b \x01(\t\x12\x17\n\x0foauth_client_id\x18\x0c \x01(\t\x12:\n\noauth_keys\x18\r \x03(\x0b\x32&.coprocess.SessionState.OauthKeysEntry\x12\x31\n\x0f\x62\x61sic_auth_data\x18\x0e \x01(\x0b\x32\x18.coprocess.BasicAuthData\x12$\n\x08jwt_data\x18\x0f \x01(\x0b\x32\x12.coprocess.JWTData\x12\x14\n\x0chmac_enabled\x18\x10 \x01(\x08\x12\x13\n\x0bhmac_secret\x18\x11 \x01(\t\x12\x13\n\x0bis_inactive\x18\x12 \x01(\x08\x12\x17\n\x0f\x61pply_policy_id\x18\x13 \x01(\t\x12\x14\n\x0c\x64\x61ta_expires\x18\x14 \x01(\x03\x12#\n\x07monitor\x18\x15 \x01(\x0b\x32\x12.coprocess.Monitor\x12!\n\x19\x65nable_detailed_recording\x18\x16 \x01(\x08\x12\x37\n\x08metadata\x18\x17 \x03(\x0b\x32%.coprocess.SessionState.MetadataEntry\x12\x0c\n\x04tags\x18\x18 \x03(\t\x12\r\n\x05\x61lias\x18\x19 \x01(\t\x12\x14\n\x0clast_updated\x18\x1a \x01(\t\x12\x1d\n\x15id_extractor_deadline\x18\x1b \x01(\x03\x12\x18\n\x10session_lifetime\x18\x1c \x01(\x03\x12\x16\n\x0e\x61pply_policies\x18\x1d \x03(\t\x12\x13\n\x0b\x63\x65rtificate\x18\x1e \x01(\t\x1aP\n\x11\x41\x63\x63\x65ssRightsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12*\n\x05value\x18\x02 \x01(\x0b\x32\x1b.coprocess.AccessDefinition:\x02\x38\x01\x1a\x30\n\x0eOauthKeysEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x62\x06proto3') ) @@ -248,8 +248,8 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1120, - serialized_end=1200, + serialized_start=1159, + serialized_end=1239, ) _SESSIONSTATE_OAUTHKEYSENTRY = _descriptor.Descriptor( @@ -285,8 +285,45 @@ extension_ranges=[], oneofs=[ ], - serialized_start=1202, - serialized_end=1250, + serialized_start=1241, + serialized_end=1289, +) + +_SESSIONSTATE_METADATAENTRY = _descriptor.Descriptor( + name='MetadataEntry', + full_name='coprocess.SessionState.MetadataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='coprocess.SessionState.MetadataEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='coprocess.SessionState.MetadataEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=_descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1291, + serialized_end=1338, ) _SESSIONSTATE = _descriptor.Descriptor( @@ -452,8 +489,8 @@ options=None, file=DESCRIPTOR), _descriptor.FieldDescriptor( name='metadata', full_name='coprocess.SessionState.metadata', index=22, - number=23, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), + number=23, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, options=None, file=DESCRIPTOR), @@ -509,7 +546,7 @@ ], extensions=[ ], - nested_types=[_SESSIONSTATE_ACCESSRIGHTSENTRY, _SESSIONSTATE_OAUTHKEYSENTRY, ], + nested_types=[_SESSIONSTATE_ACCESSRIGHTSENTRY, _SESSIONSTATE_OAUTHKEYSENTRY, _SESSIONSTATE_METADATAENTRY, ], enum_types=[ ], options=None, @@ -519,18 +556,20 @@ oneofs=[ ], serialized_start=317, - serialized_end=1250, + serialized_end=1338, ) _ACCESSDEFINITION.fields_by_name['allowed_urls'].message_type = _ACCESSSPEC _SESSIONSTATE_ACCESSRIGHTSENTRY.fields_by_name['value'].message_type = _ACCESSDEFINITION _SESSIONSTATE_ACCESSRIGHTSENTRY.containing_type = _SESSIONSTATE _SESSIONSTATE_OAUTHKEYSENTRY.containing_type = _SESSIONSTATE +_SESSIONSTATE_METADATAENTRY.containing_type = _SESSIONSTATE _SESSIONSTATE.fields_by_name['access_rights'].message_type = _SESSIONSTATE_ACCESSRIGHTSENTRY _SESSIONSTATE.fields_by_name['oauth_keys'].message_type = _SESSIONSTATE_OAUTHKEYSENTRY _SESSIONSTATE.fields_by_name['basic_auth_data'].message_type = _BASICAUTHDATA _SESSIONSTATE.fields_by_name['jwt_data'].message_type = _JWTDATA _SESSIONSTATE.fields_by_name['monitor'].message_type = _MONITOR +_SESSIONSTATE.fields_by_name['metadata'].message_type = _SESSIONSTATE_METADATAENTRY DESCRIPTOR.message_types_by_name['AccessSpec'] = _ACCESSSPEC DESCRIPTOR.message_types_by_name['AccessDefinition'] = _ACCESSDEFINITION DESCRIPTOR.message_types_by_name['BasicAuthData'] = _BASICAUTHDATA @@ -589,6 +628,13 @@ # @@protoc_insertion_point(class_scope:coprocess.SessionState.OauthKeysEntry) )) , + + MetadataEntry = _reflection.GeneratedProtocolMessageType('MetadataEntry', (_message.Message,), dict( + DESCRIPTOR = _SESSIONSTATE_METADATAENTRY, + __module__ = 'coprocess_session_state_pb2' + # @@protoc_insertion_point(class_scope:coprocess.SessionState.MetadataEntry) + )) + , DESCRIPTOR = _SESSIONSTATE, __module__ = 'coprocess_session_state_pb2' # @@protoc_insertion_point(class_scope:coprocess.SessionState) @@ -596,10 +642,13 @@ _sym_db.RegisterMessage(SessionState) _sym_db.RegisterMessage(SessionState.AccessRightsEntry) _sym_db.RegisterMessage(SessionState.OauthKeysEntry) +_sym_db.RegisterMessage(SessionState.MetadataEntry) _SESSIONSTATE_ACCESSRIGHTSENTRY.has_options = True _SESSIONSTATE_ACCESSRIGHTSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) _SESSIONSTATE_OAUTHKEYSENTRY.has_options = True _SESSIONSTATE_OAUTHKEYSENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) +_SESSIONSTATE_METADATAENTRY.has_options = True +_SESSIONSTATE_METADATAENTRY._options = _descriptor._ParseOptions(descriptor_pb2.MessageOptions(), _b('8\001')) # @@protoc_insertion_point(module_scope) diff --git a/coprocess/bindings/ruby/coprocess_session_state_pb.rb b/coprocess/bindings/ruby/coprocess_session_state_pb.rb index d9a611c4c29..7f638c3e097 100644 --- a/coprocess/bindings/ruby/coprocess_session_state_pb.rb +++ b/coprocess/bindings/ruby/coprocess_session_state_pb.rb @@ -47,7 +47,7 @@ optional :data_expires, :int64, 20 optional :monitor, :message, 21, "coprocess.Monitor" optional :enable_detailed_recording, :bool, 22 - optional :metadata, :string, 23 + map :metadata, :string, :string, 23 repeated :tags, :string, 24 optional :alias, :string, 25 optional :last_updated, :string, 26 diff --git a/coprocess/coprocess_session_state.pb.go b/coprocess/coprocess_session_state.pb.go index c69efce4210..6149fa78cad 100644 --- a/coprocess/coprocess_session_state.pb.go +++ b/coprocess/coprocess_session_state.pb.go @@ -155,7 +155,7 @@ type SessionState struct { DataExpires int64 `protobuf:"varint,20,opt,name=data_expires,json=dataExpires" json:"data_expires,omitempty"` Monitor *Monitor `protobuf:"bytes,21,opt,name=monitor" json:"monitor,omitempty"` EnableDetailedRecording bool `protobuf:"varint,22,opt,name=enable_detailed_recording,json=enableDetailedRecording" json:"enable_detailed_recording,omitempty"` - Metadata string `protobuf:"bytes,23,opt,name=metadata" json:"metadata,omitempty"` + Metadata map[string]string `protobuf:"bytes,23,rep,name=metadata" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` Tags []string `protobuf:"bytes,24,rep,name=tags" json:"tags,omitempty"` Alias string `protobuf:"bytes,25,opt,name=alias" json:"alias,omitempty"` LastUpdated string `protobuf:"bytes,26,opt,name=last_updated,json=lastUpdated" json:"last_updated,omitempty"` @@ -324,11 +324,11 @@ func (m *SessionState) GetEnableDetailedRecording() bool { return false } -func (m *SessionState) GetMetadata() string { +func (m *SessionState) GetMetadata() map[string]string { if m != nil { return m.Metadata } - return "" + return nil } func (m *SessionState) GetTags() []string { @@ -392,63 +392,64 @@ func init() { func init() { proto.RegisterFile("coprocess_session_state.proto", fileDescriptor4) } var fileDescriptor4 = []byte{ - // 914 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x55, 0x6f, 0x4f, 0x1b, 0xc7, - 0x13, 0x96, 0x31, 0x60, 0x7b, 0x6c, 0x03, 0xd9, 0x40, 0xb2, 0x40, 0xf8, 0xfd, 0x8c, 0xa5, 0xa6, - 0x8e, 0x94, 0xa2, 0x96, 0xbe, 0x41, 0x51, 0xa5, 0x36, 0x0d, 0xbc, 0xa0, 0x4d, 0xd2, 0xea, 0x68, - 0xd4, 0x37, 0x95, 0x56, 0xc3, 0xdd, 0x60, 0x6f, 0xb8, 0x7f, 0xdd, 0x5d, 0x63, 0xfc, 0x55, 0xfa, - 0x29, 0xfa, 0x11, 0xab, 0x9d, 0xdb, 0x83, 0x43, 0xb4, 0xef, 0x76, 0x9e, 0xe7, 0xd9, 0xb9, 0x67, - 0x77, 0x67, 0xe6, 0xe0, 0x20, 0x2e, 0x4a, 0x53, 0xc4, 0x64, 0xad, 0xb2, 0x64, 0xad, 0x2e, 0x72, - 0x65, 0x1d, 0x3a, 0x3a, 0x2a, 0x4d, 0xe1, 0x0a, 0xd1, 0xbb, 0xa3, 0xc7, 0x27, 0x00, 0x6f, 0x63, - 0xbf, 0xba, 0x28, 0x29, 0x16, 0x5b, 0xd0, 0x9e, 0x9b, 0x54, 0xb6, 0x46, 0xad, 0x49, 0x2f, 0xf2, - 0x4b, 0x21, 0xa1, 0x93, 0x91, 0x9b, 0x15, 0x89, 0x95, 0x2b, 0xa3, 0xf6, 0xa4, 0x17, 0xd5, 0xe1, - 0xf8, 0xaf, 0x16, 0x6c, 0x55, 0x5b, 0x4f, 0xe9, 0x4a, 0xe7, 0xda, 0xe9, 0x22, 0x17, 0xbb, 0xd0, - 0xc5, 0x52, 0xab, 0x1c, 0x33, 0x0a, 0x59, 0x3a, 0x58, 0xea, 0x8f, 0x98, 0x91, 0xd8, 0x81, 0x75, - 0x4f, 0xe9, 0x44, 0xae, 0x30, 0xb1, 0x86, 0xa5, 0x3e, 0x4f, 0xc4, 0x1e, 0x74, 0x6f, 0xc8, 0x78, - 0x8b, 0x56, 0xb6, 0xf9, 0x0b, 0x77, 0xb1, 0x38, 0x81, 0x01, 0xa6, 0x69, 0xb1, 0xa0, 0x44, 0xcd, - 0x4d, 0x6a, 0xe5, 0xea, 0xa8, 0x3d, 0xe9, 0x1f, 0xef, 0x1c, 0xdd, 0xd9, 0x3f, 0xba, 0xf7, 0x1e, - 0xf5, 0x83, 0xf4, 0x93, 0x49, 0xed, 0xf8, 0x7b, 0x18, 0xfe, 0x88, 0x56, 0xc7, 0x6f, 0xe7, 0x6e, - 0x76, 0x8a, 0x0e, 0xfd, 0x67, 0x4a, 0xb4, 0x76, 0x51, 0x98, 0x24, 0x18, 0xbb, 0x8b, 0x85, 0x80, - 0xd5, 0x19, 0xda, 0x59, 0xf0, 0xc5, 0xeb, 0xf1, 0x21, 0x74, 0x7e, 0xfa, 0xfd, 0x37, 0xde, 0xfa, - 0x0c, 0xd6, 0x2d, 0xc5, 0x86, 0x5c, 0xd8, 0x18, 0xa2, 0xf1, 0xd7, 0xd0, 0xf9, 0x50, 0xe4, 0xda, - 0x15, 0x46, 0x7c, 0x01, 0x1b, 0xce, 0xe8, 0xe9, 0x94, 0x8c, 0x4a, 0x75, 0xa6, 0x9d, 0x95, 0xad, - 0x51, 0x7b, 0xd2, 0x8a, 0x86, 0x01, 0x7d, 0xcf, 0xe0, 0xf8, 0x6f, 0x80, 0xc1, 0x45, 0xf5, 0x1e, - 0x17, 0xfe, 0x39, 0xc4, 0x01, 0x40, 0x8a, 0xd6, 0xa9, 0x78, 0x46, 0xf1, 0x35, 0xa7, 0x6f, 0x47, - 0x3d, 0x8f, 0xbc, 0xf3, 0x80, 0x78, 0x01, 0x3d, 0x3e, 0x14, 0xe6, 0x31, 0xb1, 0xbb, 0x56, 0x74, - 0x0f, 0x78, 0xdb, 0x06, 0x1d, 0xc9, 0x36, 0x13, 0xbc, 0xf6, 0x0f, 0x58, 0x92, 0x91, 0xab, 0x0c, - 0xf9, 0xa5, 0x7f, 0x40, 0xba, 0x2d, 0xb5, 0x21, 0x2b, 0xd7, 0x38, 0x7f, 0x1d, 0x8a, 0x7d, 0xe8, - 0xfd, 0x39, 0x2f, 0x1c, 0xaa, 0x0c, 0x6f, 0xe5, 0x3a, 0x73, 0x5d, 0x06, 0x3e, 0xe0, 0xad, 0x38, - 0x84, 0x41, 0x45, 0x1a, 0xca, 0x69, 0x61, 0x65, 0x87, 0xf9, 0x3e, 0x63, 0x11, 0x43, 0xe2, 0x4b, - 0xd8, 0xac, 0x25, 0x19, 0xea, 0x5c, 0xe7, 0x53, 0xd9, 0x65, 0xd5, 0x46, 0x50, 0x05, 0x54, 0xbc, - 0x06, 0xd1, 0xc8, 0x85, 0xa9, 0x62, 0xdb, 0x3d, 0xd6, 0x6e, 0xdd, 0x67, 0xc4, 0x34, 0xf2, 0x47, - 0xf8, 0x08, 0x43, 0xe4, 0x57, 0x55, 0x46, 0x4f, 0x67, 0xce, 0x4a, 0xe0, 0x57, 0x7f, 0xd5, 0x78, - 0xf5, 0xe6, 0x1d, 0x86, 0x12, 0x88, 0x58, 0x7b, 0x96, 0x3b, 0xb3, 0x8c, 0x06, 0xd8, 0x80, 0x7c, - 0xdd, 0x15, 0x66, 0xea, 0xeb, 0xae, 0x5f, 0xd5, 0x5d, 0x61, 0xa6, 0xe7, 0x89, 0x78, 0x09, 0x9b, - 0x05, 0xce, 0xdd, 0x4c, 0xc5, 0xa9, 0xa6, 0xdc, 0x79, 0x7e, 0xc0, 0xfc, 0x90, 0xe1, 0x77, 0x8c, - 0x9e, 0x27, 0xe2, 0x0c, 0xa0, 0xd2, 0x5d, 0xd3, 0xd2, 0xca, 0x21, 0x7b, 0x79, 0xf9, 0x5f, 0x5e, - 0x7e, 0xf1, 0xca, 0x9f, 0x69, 0x19, 0x8c, 0xf4, 0x8a, 0x3a, 0x16, 0x3f, 0xc0, 0xe6, 0xa5, 0x2f, - 0x48, 0xc5, 0xb9, 0x12, 0x74, 0x28, 0x37, 0x46, 0xad, 0x49, 0xff, 0x58, 0x36, 0x72, 0x3d, 0x28, - 0xd9, 0x68, 0x78, 0xf9, 0xa0, 0x82, 0xbf, 0x82, 0xee, 0xe7, 0x85, 0xab, 0xb6, 0x6e, 0xf2, 0x56, - 0xd1, 0xd8, 0x1a, 0x8a, 0x35, 0xea, 0x7c, 0x5e, 0x38, 0x96, 0x1f, 0xc2, 0x60, 0x96, 0x61, 0xac, - 0x28, 0xc7, 0xcb, 0x94, 0x12, 0xb9, 0x35, 0x6a, 0x4d, 0xba, 0x51, 0xdf, 0x63, 0x67, 0x15, 0x24, - 0xfe, 0x0f, 0x1c, 0xaa, 0x50, 0xdd, 0x4f, 0xf8, 0xf8, 0xe0, 0xa1, 0x0b, 0x46, 0xbc, 0x40, 0x5b, - 0xa5, 0x73, 0x8c, 0x9d, 0xbe, 0x21, 0x29, 0x38, 0x05, 0x68, 0x7b, 0x1e, 0x10, 0x7f, 0x89, 0x58, - 0x96, 0xe9, 0x52, 0x95, 0x45, 0xaa, 0xe3, 0xa5, 0xbf, 0xc4, 0xa7, 0xd5, 0x25, 0x32, 0xfc, 0x2b, - 0xa3, 0xe7, 0x89, 0x37, 0xe3, 0x7d, 0xab, 0xba, 0x12, 0xb7, 0xab, 0x6a, 0xf2, 0xd8, 0x59, 0xa8, - 0xc6, 0xd7, 0xd0, 0xc9, 0xaa, 0x6e, 0x92, 0x3b, 0x8f, 0x4e, 0x17, 0xfa, 0x2c, 0xaa, 0x25, 0xe2, - 0x0d, 0xec, 0x56, 0x07, 0x53, 0x09, 0x39, 0xd4, 0x29, 0x25, 0xca, 0x50, 0x5c, 0x98, 0xc4, 0x57, - 0xe1, 0x33, 0xf6, 0xf9, 0xbc, 0x12, 0x9c, 0x06, 0x3e, 0xaa, 0x69, 0x3f, 0x0a, 0x32, 0x72, 0xc8, - 0x17, 0xf9, 0xbc, 0x1a, 0x05, 0x75, 0xec, 0x7b, 0xca, 0xe1, 0xd4, 0x4a, 0xc9, 0x93, 0x88, 0xd7, - 0x62, 0x1b, 0xd6, 0x30, 0xd5, 0x68, 0xe5, 0x6e, 0x98, 0x5b, 0x3e, 0xf0, 0x47, 0xe2, 0xd6, 0x9d, - 0x97, 0x09, 0x3a, 0x4a, 0xe4, 0x1e, 0x93, 0x7d, 0x8f, 0x7d, 0xaa, 0x20, 0x71, 0x0c, 0x3b, 0x3a, - 0x51, 0x74, 0xeb, 0x0c, 0xc6, 0xae, 0x30, 0x2a, 0x21, 0x4c, 0x52, 0x9d, 0x93, 0xdc, 0xe7, 0xe3, - 0x3f, 0xd5, 0xc9, 0x59, 0xcd, 0x9d, 0x06, 0x4a, 0xbc, 0x82, 0xad, 0x7a, 0x62, 0xa7, 0xfa, 0x8a, - 0x9c, 0xce, 0x48, 0xbe, 0x60, 0xf9, 0x66, 0xc0, 0xdf, 0x07, 0xd8, 0x0f, 0x9d, 0xc6, 0xe5, 0x6b, - 0xb2, 0xf2, 0x80, 0x5d, 0x37, 0xee, 0x5e, 0x93, 0x15, 0x23, 0xe8, 0xc7, 0x64, 0x9c, 0xbe, 0xd2, - 0xb1, 0x6f, 0xbb, 0xff, 0x55, 0x3e, 0x1b, 0xd0, 0xde, 0x1f, 0xf0, 0xe4, 0x51, 0x13, 0xf9, 0x49, - 0x72, 0x4d, 0xcb, 0xfa, 0x57, 0x70, 0x4d, 0x4b, 0xf1, 0x0d, 0xac, 0xdd, 0x60, 0x3a, 0xaf, 0x26, - 0x51, 0xff, 0x78, 0xff, 0xd1, 0x18, 0xbe, 0xff, 0x0f, 0x44, 0x95, 0xf2, 0xcd, 0xca, 0x49, 0x6b, - 0xef, 0x3b, 0xd8, 0x78, 0xd8, 0x16, 0xff, 0x92, 0x7a, 0xbb, 0x99, 0xba, 0xd7, 0xd8, 0x7d, 0xb9, - 0xce, 0x7f, 0xac, 0x6f, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0x93, 0xd4, 0x16, 0x3a, 0xd2, 0x06, - 0x00, 0x00, + // 933 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0x4f, 0x6f, 0x1b, 0xb7, + 0x13, 0x85, 0x2c, 0xdb, 0x92, 0x66, 0x25, 0x5b, 0x61, 0xec, 0x84, 0xb6, 0xe3, 0xdf, 0x4f, 0x16, + 0x90, 0x54, 0x01, 0x52, 0xa3, 0x75, 0x2f, 0x46, 0x5a, 0xa0, 0x75, 0x63, 0x1d, 0xd4, 0xc6, 0x69, + 0xb1, 0x6e, 0xd0, 0x4b, 0x01, 0x82, 0xde, 0x1d, 0x4b, 0x8c, 0xf7, 0x5f, 0x49, 0xca, 0xb2, 0xbe, + 0x47, 0x4f, 0xfd, 0xb4, 0x05, 0x67, 0xb9, 0xf2, 0x1a, 0x6e, 0x0e, 0xbd, 0x71, 0xde, 0x7b, 0x33, + 0xfb, 0xc8, 0x19, 0x72, 0xe1, 0x30, 0xca, 0x0b, 0x9d, 0x47, 0x68, 0x8c, 0x30, 0x68, 0x8c, 0xca, + 0x33, 0x61, 0xac, 0xb4, 0x78, 0x5c, 0xe8, 0xdc, 0xe6, 0xac, 0xb3, 0xa2, 0x87, 0xa7, 0x00, 0x67, + 0x91, 0x5b, 0x5d, 0x16, 0x18, 0xb1, 0x3e, 0x34, 0xe7, 0x3a, 0xe1, 0x8d, 0x41, 0x63, 0xd4, 0x09, + 0xdd, 0x92, 0x71, 0x68, 0xa5, 0x68, 0x67, 0x79, 0x6c, 0xf8, 0xda, 0xa0, 0x39, 0xea, 0x84, 0x55, + 0x38, 0xfc, 0xbb, 0x01, 0xfd, 0x32, 0xf5, 0x1c, 0xaf, 0x55, 0xa6, 0xac, 0xca, 0x33, 0xb6, 0x07, + 0x6d, 0x59, 0x28, 0x91, 0xc9, 0x14, 0x7d, 0x95, 0x96, 0x2c, 0xd4, 0x07, 0x99, 0x22, 0xdb, 0x85, + 0x4d, 0x47, 0xa9, 0x98, 0xaf, 0x11, 0xb1, 0x21, 0x0b, 0x35, 0x89, 0xd9, 0x3e, 0xb4, 0x6f, 0x51, + 0x3b, 0x8b, 0x86, 0x37, 0xe9, 0x0b, 0xab, 0x98, 0x9d, 0x42, 0x57, 0x26, 0x49, 0xbe, 0xc0, 0x58, + 0xcc, 0x75, 0x62, 0xf8, 0xfa, 0xa0, 0x39, 0x0a, 0x4e, 0x76, 0x8f, 0x57, 0xf6, 0x8f, 0xef, 0xbd, + 0x87, 0x81, 0x97, 0x7e, 0xd4, 0x89, 0x19, 0x7e, 0x0f, 0xbd, 0x1f, 0xa5, 0x51, 0xd1, 0xd9, 0xdc, + 0xce, 0xce, 0xa5, 0x95, 0xee, 0x33, 0x85, 0x34, 0x66, 0x91, 0xeb, 0xd8, 0x1b, 0x5b, 0xc5, 0x8c, + 0xc1, 0xfa, 0x4c, 0x9a, 0x99, 0xf7, 0x45, 0xeb, 0xe1, 0x11, 0xb4, 0x7e, 0xfa, 0xfd, 0x37, 0x4a, + 0x7d, 0x06, 0x9b, 0x06, 0x23, 0x8d, 0xd6, 0x27, 0xfa, 0x68, 0xf8, 0x15, 0xb4, 0x2e, 0xf2, 0x4c, + 0xd9, 0x5c, 0xb3, 0x97, 0xb0, 0x65, 0xb5, 0x9a, 0x4e, 0x51, 0x8b, 0x44, 0xa5, 0xca, 0x1a, 0xde, + 0x18, 0x34, 0x47, 0x8d, 0xb0, 0xe7, 0xd1, 0xf7, 0x04, 0x0e, 0xff, 0x0a, 0xa0, 0x7b, 0x59, 0xf6, + 0xe3, 0xd2, 0xb5, 0x83, 0x1d, 0x02, 0x24, 0xd2, 0x58, 0x11, 0xcd, 0x30, 0xba, 0xa1, 0xf2, 0xcd, + 0xb0, 0xe3, 0x90, 0x77, 0x0e, 0x60, 0x2f, 0xa0, 0x43, 0x9b, 0x92, 0x59, 0x84, 0xe4, 0xae, 0x11, + 0xde, 0x03, 0xce, 0xb6, 0x96, 0x16, 0x79, 0x93, 0x08, 0x5a, 0xbb, 0x06, 0x16, 0xa8, 0xf9, 0x3a, + 0x41, 0x6e, 0xe9, 0x1a, 0x88, 0x77, 0x85, 0xd2, 0x68, 0xf8, 0x06, 0xd5, 0xaf, 0x42, 0x76, 0x00, + 0x9d, 0x3f, 0xe7, 0xb9, 0x95, 0x22, 0x95, 0x77, 0x7c, 0x93, 0xb8, 0x36, 0x01, 0x17, 0xf2, 0x8e, + 0x1d, 0x41, 0xb7, 0x24, 0x35, 0x66, 0xb8, 0x30, 0xbc, 0x45, 0x7c, 0x40, 0x58, 0x48, 0x10, 0xfb, + 0x02, 0xb6, 0x2b, 0x49, 0x2a, 0x55, 0xa6, 0xb2, 0x29, 0x6f, 0x93, 0x6a, 0xcb, 0xab, 0x3c, 0xca, + 0xde, 0x00, 0xab, 0xd5, 0x92, 0x89, 0x20, 0xdb, 0x1d, 0xd2, 0xf6, 0xef, 0x2b, 0xca, 0x24, 0x74, + 0x5b, 0xf8, 0x00, 0x3d, 0x49, 0x5d, 0x15, 0x5a, 0x4d, 0x67, 0xd6, 0x70, 0xa0, 0xae, 0xbf, 0xae, + 0x75, 0xbd, 0x7e, 0x86, 0x7e, 0x04, 0x42, 0xd2, 0x8e, 0x33, 0xab, 0x97, 0x61, 0x57, 0xd6, 0x20, + 0x37, 0x77, 0xb9, 0x9e, 0xba, 0xb9, 0x0b, 0xca, 0xb9, 0xcb, 0xf5, 0x74, 0x12, 0xb3, 0x57, 0xb0, + 0x9d, 0xcb, 0xb9, 0x9d, 0x89, 0x28, 0x51, 0x98, 0x59, 0xc7, 0x77, 0x89, 0xef, 0x11, 0xfc, 0x8e, + 0xd0, 0x49, 0xcc, 0xc6, 0x00, 0xa5, 0xee, 0x06, 0x97, 0x86, 0xf7, 0xc8, 0xcb, 0xab, 0xcf, 0x79, + 0xf9, 0xc5, 0x29, 0x7f, 0xc6, 0xa5, 0x37, 0xd2, 0xc9, 0xab, 0x98, 0xfd, 0x00, 0xdb, 0x57, 0x6e, + 0x20, 0x05, 0xd5, 0x8a, 0xa5, 0x95, 0x7c, 0x6b, 0xd0, 0x18, 0x05, 0x27, 0xbc, 0x56, 0xeb, 0xc1, + 0xc8, 0x86, 0xbd, 0xab, 0x07, 0x13, 0xfc, 0x25, 0xb4, 0x3f, 0x2d, 0x6c, 0x99, 0xba, 0x4d, 0xa9, + 0xac, 0x96, 0xea, 0x87, 0x35, 0x6c, 0x7d, 0x5a, 0x58, 0x92, 0x1f, 0x41, 0x77, 0x96, 0xca, 0x48, + 0x60, 0x26, 0xaf, 0x12, 0x8c, 0x79, 0x7f, 0xd0, 0x18, 0xb5, 0xc3, 0xc0, 0x61, 0xe3, 0x12, 0x62, + 0xff, 0x07, 0x0a, 0x85, 0x9f, 0xee, 0x27, 0xb4, 0x7d, 0x70, 0xd0, 0x25, 0x21, 0x4e, 0xa0, 0x8c, + 0x50, 0x99, 0x8c, 0xac, 0xba, 0x45, 0xce, 0xa8, 0x04, 0x28, 0x33, 0xf1, 0x88, 0x3b, 0x44, 0x59, + 0x14, 0xc9, 0x52, 0x14, 0x79, 0xa2, 0xa2, 0xa5, 0x3b, 0xc4, 0xa7, 0xe5, 0x21, 0x12, 0xfc, 0x2b, + 0xa1, 0x93, 0xd8, 0x99, 0x71, 0xbe, 0x45, 0x35, 0x89, 0x3b, 0xe5, 0x34, 0x39, 0x6c, 0xec, 0xa7, + 0xf1, 0x0d, 0xb4, 0xd2, 0xf2, 0x36, 0xf1, 0xdd, 0x47, 0xbb, 0xf3, 0xf7, 0x2c, 0xac, 0x24, 0xec, + 0x2d, 0xec, 0x95, 0x1b, 0x13, 0x31, 0x5a, 0xa9, 0x12, 0x8c, 0x85, 0xc6, 0x28, 0xd7, 0xb1, 0x9b, + 0xc2, 0x67, 0xe4, 0xf3, 0x79, 0x29, 0x38, 0xf7, 0x7c, 0x58, 0xd1, 0xec, 0x0c, 0xda, 0x29, 0x5a, + 0x49, 0x07, 0xf9, 0x9c, 0xfa, 0xf9, 0xf2, 0x73, 0xfd, 0xbc, 0xf0, 0xba, 0xb2, 0x9d, 0xab, 0x34, + 0x77, 0xf5, 0xac, 0x9c, 0x1a, 0xce, 0xe9, 0xc1, 0xa2, 0x35, 0xdb, 0x81, 0x0d, 0x99, 0x28, 0x69, + 0xf8, 0x9e, 0x7f, 0xde, 0x5c, 0xe0, 0x76, 0x4e, 0x37, 0x7c, 0x5e, 0xc4, 0xd2, 0x62, 0xcc, 0xf7, + 0x89, 0x0c, 0x1c, 0xf6, 0xb1, 0x84, 0xd8, 0x09, 0xec, 0xaa, 0x58, 0xe0, 0x9d, 0xd5, 0x32, 0xb2, + 0xb9, 0x16, 0x31, 0xca, 0x38, 0x51, 0x19, 0xf2, 0x03, 0x3a, 0xa5, 0xa7, 0x2a, 0x1e, 0x57, 0xdc, + 0xb9, 0xa7, 0xd8, 0x6b, 0xe8, 0x57, 0x0f, 0x7b, 0xa2, 0xae, 0xd1, 0xaa, 0x14, 0xf9, 0x0b, 0x92, + 0x6f, 0x7b, 0xfc, 0xbd, 0x87, 0xdd, 0xdb, 0x54, 0xeb, 0x91, 0x42, 0xc3, 0x0f, 0xc9, 0x75, 0xad, + 0x45, 0x0a, 0x0d, 0x1b, 0x40, 0x10, 0xa1, 0xb6, 0xea, 0x5a, 0x45, 0xee, 0x76, 0xfe, 0xaf, 0xf4, + 0x59, 0x83, 0xf6, 0xff, 0x80, 0x27, 0x8f, 0xee, 0x9a, 0x7b, 0x70, 0x6e, 0x70, 0x59, 0xfd, 0x31, + 0x6e, 0x70, 0xc9, 0xbe, 0x86, 0x8d, 0x5b, 0x99, 0xcc, 0xcb, 0x07, 0x2b, 0x38, 0x39, 0x78, 0xf4, + 0x5a, 0xdf, 0xff, 0x2e, 0xc2, 0x52, 0xf9, 0x76, 0xed, 0xb4, 0xb1, 0xff, 0x1d, 0x6c, 0x3d, 0xbc, + 0x3d, 0xff, 0x52, 0x7a, 0xa7, 0x5e, 0xba, 0x53, 0xcf, 0xfe, 0x16, 0x7a, 0x0f, 0x7a, 0xf5, 0x5f, + 0x92, 0xaf, 0x36, 0xe9, 0xaf, 0xf8, 0xcd, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xdc, 0xad, 0x0c, + 0x63, 0x36, 0x07, 0x00, 0x00, } diff --git a/coprocess/proto/coprocess_session_state.proto b/coprocess/proto/coprocess_session_state.proto index 36f080127e9..c045bfd10c6 100644 --- a/coprocess/proto/coprocess_session_state.proto +++ b/coprocess/proto/coprocess_session_state.proto @@ -60,7 +60,7 @@ message SessionState { bool enable_detailed_recording = 22; - string metadata = 23; + map metadata = 23; repeated string tags = 24; string alias = 25; diff --git a/coprocess/python/tyk/middleware.py b/coprocess/python/tyk/middleware.py index 44b84ec39be..5ad0cf5ec16 100644 --- a/coprocess/python/tyk/middleware.py +++ b/coprocess/python/tyk/middleware.py @@ -78,7 +78,9 @@ def process(self, handler, object): handler(object, object.spec) return elif handler.arg_count == 4: - object.request, object.session, object.metadata = handler(object.request, object.session, object.metadata, object.spec) + md = object.session.metadata + object.request, object.session, md = handler(object.request, object.session, md, object.spec) + object.session.metadata.MergeFrom(md) elif handler.arg_count == 3: object.request, object.session = handler(object.request, object.session, object.spec) return object diff --git a/coprocess_helpers.go b/coprocess_helpers.go index 64b8d9a3cd3..4361ec10a0b 100644 --- a/coprocess_helpers.go +++ b/coprocess_helpers.go @@ -5,6 +5,8 @@ package main import ( "encoding/json" + "github.com/Sirupsen/logrus" + "github.com/TykTechnologies/tyk/coprocess" "github.com/TykTechnologies/tyk/user" ) @@ -54,10 +56,9 @@ func TykSessionState(session *coprocess.SessionState) *user.SessionState { } metadata := make(map[string]interface{}) - if session.Metadata != "" { - err := json.Unmarshal([]byte(session.Metadata), &metadata) - if err != nil { - log.Error("Error interpreting metadata: ", err) + if session.Metadata != nil { + for k, v := range session.Metadata { + metadata[k] = v } } @@ -129,6 +130,25 @@ func ProtoSessionState(session *user.SessionState) *coprocess.SessionState { TriggerLimits: session.Monitor.TriggerLimits, } + metadata := make(map[string]string) + if len(session.MetaData) > 0 { + for k, v := range session.MetaData { + switch v.(type) { + case string: + metadata[k] = v.(string) + default: + jsonValue, err := json.Marshal(v) + if err != nil { + log.WithFields(logrus.Fields{ + "prefix": "coprocess", + }).WithError(err).Error("Couldn't encode session metadata") + continue + } + metadata[k] = string(jsonValue) + } + } + } + return &coprocess.SessionState{ LastCheck: session.LastCheck, Allowance: session.Allowance, @@ -152,6 +172,7 @@ func ProtoSessionState(session *user.SessionState) *coprocess.SessionState { ApplyPolicies: session.ApplyPolicies, DataExpires: session.DataExpires, Monitor: monitor, + Metadata: metadata, EnableDetailedRecording: session.EnableDetailedRecording, Tags: session.Tags, Alias: session.Alias, From cdb8664061f0de6c1d9f8b6777eac8be05adc0b9 Mon Sep 17 00:00:00 2001 From: Matias Insaurralde Date: Tue, 5 Jun 2018 22:38:21 -0400 Subject: [PATCH 4/6] coprocess: fix compatibility with plugins that still use coprocess.Object.Metadata --- coprocess.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/coprocess.go b/coprocess.go index ba49a7d355c..3d7761e7f5f 100644 --- a/coprocess.go +++ b/coprocess.go @@ -273,6 +273,16 @@ func (m *CoProcessMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Requ var token string if returnObject.Session != nil { + // For compatibility purposes, inject coprocess.Object.Metadata fields: + if returnObject.Metadata != nil { + if returnObject.Session.Metadata == nil { + returnObject.Session.Metadata = make(map[string]string) + } + for k, v := range returnObject.Metadata { + returnObject.Session.Metadata[k] = v + } + } + token = returnObject.Session.Metadata["token"] } From 28a81000332c5e9b17471b511d499b48261f5a9d Mon Sep 17 00:00:00 2001 From: Matias Insaurralde Date: Tue, 12 Jun 2018 20:26:30 -0400 Subject: [PATCH 5/6] coprocess: add additional compatibility code --- coprocess.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/coprocess.go b/coprocess.go index 3d7761e7f5f..513c1675a33 100644 --- a/coprocess.go +++ b/coprocess.go @@ -136,6 +136,8 @@ func (c *CoProcessor) ObjectFromRequest(r *http.Request) *coprocess.Object { if c.HookType != coprocess.HookType_Pre && c.HookType != coprocess.HookType_CustomKeyCheck { if session := ctxGetSession(r); session != nil { object.Session = ProtoSessionState(session) + // For compatibility purposes: + object.Metadata = object.Session.Metadata } } From cf3c47b2edf0b56a1e25cb9e6e98c5f1be554d24 Mon Sep 17 00:00:00 2001 From: Matias Insaurralde Date: Tue, 12 Jun 2018 20:32:57 -0400 Subject: [PATCH 6/6] coprocess: enhance tests with session metadata checks --- coprocess_grpc_test.go | 128 ++++++++++++++++++++++++++++++++++----- coprocess_python_test.go | 73 ++++++++++++++++++++++ 2 files changed, 187 insertions(+), 14 deletions(-) diff --git a/coprocess_grpc_test.go b/coprocess_grpc_test.go index 135d4abb493..717568f803b 100644 --- a/coprocess_grpc_test.go +++ b/coprocess_grpc_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "net" "net/http" + "strings" "testing" "context" @@ -18,6 +19,7 @@ import ( "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/coprocess" "github.com/TykTechnologies/tyk/test" + "github.com/TykTechnologies/tyk/user" ) const ( @@ -36,6 +38,56 @@ func (d *dispatcher) Dispatch(ctx context.Context, object *coprocess.Object) (*c object.Request.SetHeaders = map[string]string{ testHeaderName: testHeaderValue, } + case "testPostHook1": + testKeyValue, ok := object.Session.Metadata["testkey"] + if !ok { + object.Request.ReturnOverrides.ResponseError = "'testkey' not found in session metadata" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + jsonObject := make(map[string]string) + if err := json.Unmarshal([]byte(testKeyValue), &jsonObject); err != nil { + object.Request.ReturnOverrides.ResponseError = "couldn't decode 'testkey' nested value" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + nestedKeyValue, ok := jsonObject["nestedkey"] + if !ok { + object.Request.ReturnOverrides.ResponseError = "'nestedkey' not found in JSON object" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + if nestedKeyValue != "nestedvalue" { + object.Request.ReturnOverrides.ResponseError = "'nestedvalue' value doesn't match" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + testKey2Value, ok := object.Session.Metadata["testkey2"] + if !ok { + object.Request.ReturnOverrides.ResponseError = "'testkey' not found in session metadata" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + if testKey2Value != "testvalue" { + object.Request.ReturnOverrides.ResponseError = "'testkey2' value doesn't match" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + + // Check for compatibility (object.Metadata should contain the same keys as object.Session.Metadata) + for k, v := range object.Metadata { + sessionKeyValue, ok := object.Session.Metadata[k] + if !ok { + object.Request.ReturnOverrides.ResponseError = k + " not found in object.Session.Metadata" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + if strings.Compare(sessionKeyValue, v) != 0 { + object.Request.ReturnOverrides.ResponseError = k + " doesn't match value in object.Session.Metadata" + object.Request.ReturnOverrides.ResponseCode = 400 + break + } + } } return object, nil } @@ -50,13 +102,14 @@ func newTestGRPCServer() (s *grpc.Server) { return s } -func loadTestGRPCSpec() *APISpec { - spec := buildAndLoadAPI(func(spec *APISpec) { - spec.APIID = "999999" +func loadTestGRPCAPIs() { + buildAndLoadAPI(func(spec *APISpec) { + spec.APIID = "1" spec.OrgID = "default" spec.Auth = apidef.Auth{ AuthHeaderName: "authorization", } + spec.UseKeylessAccess = false spec.VersionData = struct { NotVersioned bool `bson:"not_versioned" json:"not_versioned"` DefaultVersion string `bson:"default_version" json:"default_version"` @@ -77,9 +130,34 @@ func loadTestGRPCSpec() *APISpec { }, Driver: apidef.GrpcDriver, } - })[0] - - return spec + }, func(spec *APISpec) { + spec.APIID = "2" + spec.OrgID = "default" + spec.Auth = apidef.Auth{ + AuthHeaderName: "authorization", + } + spec.UseKeylessAccess = false + spec.VersionData = struct { + NotVersioned bool `bson:"not_versioned" json:"not_versioned"` + DefaultVersion string `bson:"default_version" json:"default_version"` + Versions map[string]apidef.VersionInfo `bson:"versions" json:"versions"` + }{ + NotVersioned: true, + Versions: map[string]apidef.VersionInfo{ + "v1": { + Name: "v1", + }, + }, + } + spec.Proxy.ListenPath = "/grpc-test-api-2/" + spec.Proxy.StripListenPath = true + spec.CustomMiddleware = apidef.MiddlewareSection{ + Post: []apidef.MiddlewareDefinition{ + {Name: "testPostHook1"}, + }, + Driver: apidef.GrpcDriver, + } + }) } func startTykWithGRPC() (*tykTestServer, *grpc.Server) { @@ -95,8 +173,8 @@ func startTykWithGRPC() (*tykTestServer, *grpc.Server) { } ts := newTykTestServer(tykTestServerConfig{coprocessConfig: cfg}) - // Load a test API: - loadTestGRPCSpec() + // Load test APIs: + loadTestGRPCAPIs() return &ts, grpcServer } @@ -105,11 +183,20 @@ func TestGRPCDispatch(t *testing.T) { defer ts.Close() defer grpcServer.Stop() + keyID := createSession(func(s *user.SessionState) { + s.MetaData = map[string]interface{}{ + "testkey": map[string]interface{}{"nestedkey": "nestedvalue"}, + "testkey2": "testvalue", + } + }) + headers := map[string]string{"authorization": keyID} + t.Run("Pre Hook with SetHeaders", func(t *testing.T) { res, err := ts.Run(t, test.TestCase{ - Path: "/grpc-test-api/", - Method: http.MethodGet, - Code: http.StatusOK, + Path: "/grpc-test-api/", + Method: http.MethodGet, + Code: http.StatusOK, + Headers: headers, }) if err != nil { t.Fatalf("Request failed: %s", err.Error()) @@ -132,6 +219,15 @@ func TestGRPCDispatch(t *testing.T) { } }) + t.Run("Post Hook with metadata", func(t *testing.T) { + ts.Run(t, test.TestCase{ + Path: "/grpc-test-api-2/", + Method: http.MethodGet, + Code: http.StatusOK, + Headers: headers, + }) + }) + } func BenchmarkGRPCDispatch(b *testing.B) { @@ -139,14 +235,18 @@ func BenchmarkGRPCDispatch(b *testing.B) { defer ts.Close() defer grpcServer.Stop() + keyID := createSession(func(s *user.SessionState) {}) + headers := map[string]string{"authorization": keyID} + b.Run("Pre Hook with SetHeaders", func(b *testing.B) { path := "/grpc-test-api/" b.ReportAllocs() for i := 0; i < b.N; i++ { ts.Run(b, test.TestCase{ - Path: path, - Method: http.MethodGet, - Code: http.StatusOK, + Path: path, + Method: http.MethodGet, + Code: http.StatusOK, + Headers: headers, }) } }) diff --git a/coprocess_python_test.go b/coprocess_python_test.go index 86bbcd5674c..77eaaf3ca75 100644 --- a/coprocess_python_test.go +++ b/coprocess_python_test.go @@ -9,6 +9,7 @@ import ( "github.com/TykTechnologies/tyk/config" "github.com/TykTechnologies/tyk/test" + "github.com/TykTechnologies/tyk/user" ) var pythonBundleWithAuthCheck = map[string]string{ @@ -42,6 +43,51 @@ def MyAuthHook(request, session, metadata, spec): `, } +var pythonBundleWithPostHook = map[string]string{ + "manifest.json": ` + { + "file_list": [ + "middleware.py" + ], + "custom_middleware": { + "driver": "python", + "post": [{ + "name": "MyPostHook" + }] + } + } + `, + "middleware.py": ` +from tyk.decorators import * +from gateway import TykGateway as tyk +import json + +@Hook +def MyPostHook(request, session, spec): + print("called", session.metadata) + if "testkey" not in session.metadata.keys(): + request.object.return_overrides.response_code = 400 + request.object.return_overrides.response_error = "'testkey' not found in metadata" + return request, session + nested_data = json.loads(session.metadata["testkey"]) + if "nestedkey" not in nested_data: + request.object.return_overrides.response_code = 400 + request.object.return_overrides.response_error = "'nestedkey' not found in nested metadata" + return request, session + if "stringkey" not in session.metadata.keys(): + request.object.return_overrides.response_code = 400 + request.object.return_overrides.response_error = "'stringkey' not found in metadata" + return request, session + stringkey = session.metadata["stringkey"] + if stringkey != "testvalue": + request.object.return_overrides.response_code = 400 + request.object.return_overrides.response_error = "'stringkey' value doesn't match" + return request, session + return request, session + +`, +} + func TestPythonBundles(t *testing.T) { ts := newTykTestServer(tykTestServerConfig{ coprocessConfig: config.CoProcessConfig{ @@ -50,6 +96,7 @@ func TestPythonBundles(t *testing.T) { defer ts.Close() bundleID := registerBundle("python_with_auth_check", pythonBundleWithAuthCheck) + bundleID2 := registerBundle("python_with_post_hook", pythonBundleWithPostHook) t.Run("Single-file bundle with authentication hook", func(t *testing.T) { buildAndLoadAPI(func(spec *APISpec) { @@ -70,4 +117,30 @@ func TestPythonBundles(t *testing.T) { {Path: "/test-api/", Code: 403, Headers: invalidAuth}, }...) }) + + t.Run("Single-file bundle with post hook", func(t *testing.T) { + + keyID := createSession(func(s *user.SessionState) { + s.MetaData = map[string]interface{}{ + "testkey": map[string]interface{}{"nestedkey": "nestedvalue"}, + "stringkey": "testvalue", + } + }) + + buildAndLoadAPI(func(spec *APISpec) { + spec.Proxy.ListenPath = "/test-api-2/" + spec.UseKeylessAccess = false + spec.EnableCoProcessAuth = false + spec.CustomMiddlewareBundle = bundleID2 + spec.VersionData.NotVersioned = true + }) + + time.Sleep(1 * time.Second) + + auth := map[string]string{"Authorization": keyID} + + ts.Run(t, []test.TestCase{ + {Path: "/test-api-2/", Code: 200, Headers: auth}, + }...) + }) }