diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 6b50254bf72..b25b9dd47a1 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -13,7 +13,7 @@ jobs: test: strategy: matrix: - go-version: [1.19.x] + go-version: [1.16.x] platform: [ubuntu-latest] arch: [amd64] node-version: [15.x] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34b413dccc0..12c9d060887 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Generated by: gromit policy -# Generated on: Fri Jun 16 08:40:35 UTC 2023 +# Generated on: Thu May 11 05:45:42 UTC 2023 # Distribution channels covered by this workflow @@ -43,8 +43,8 @@ jobs: debvers: 'ubuntu/xenial ubuntu/bionic debian/jessie' - golang_cross: 1.15 goreleaser: 'ci/goreleaser/goreleaser.yml' - rpmvers: 'el/8 el/9' - debvers: 'ubuntu/bionic ubuntu/focal ubuntu/jammy debian/buster debian/bullseye' + rpmvers: 'el/8' + debvers: 'ubuntu/focal debian/buster debian/bullseye' outputs: tag: ${{ steps.targets.outputs.tag }} @@ -122,7 +122,7 @@ jobs: - uses: goreleaser/goreleaser-action@v4 with: - version: latest + version: 1.18.2 args: release --clean -f ${{ matrix.goreleaser }} ${{ !startsWith(github.ref, 'refs/tags/') && ' --snapshot' || '' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/ci/images/hybrid/tyk/tyk.conf b/ci/images/hybrid/tyk/tyk.conf index ab880c714ad..2e6f9980eff 100644 --- a/ci/images/hybrid/tyk/tyk.conf +++ b/ci/images/hybrid/tyk/tyk.conf @@ -38,6 +38,7 @@ "enable_health_checks": false, "health_check_value_timeouts": 60 }, + "optimisations_use_async_session_write": true, "allow_master_keys": false, "policies": { "policy_source": "rpc", diff --git a/ci/images/hybrid/tyk/tyk.conf.example b/ci/images/hybrid/tyk/tyk.conf.example index 445975a90cd..7d5cf8fd89f 100644 --- a/ci/images/hybrid/tyk/tyk.conf.example +++ b/ci/images/hybrid/tyk/tyk.conf.example @@ -30,6 +30,7 @@ "enable_health_checks": false, "health_check_value_timeouts": 60 }, + "optimisations_use_async_session_write": true, "allow_master_keys": false, "policies": { "policy_source": "mongo", diff --git a/ci/images/plugin-compiler/Dockerfile b/ci/images/plugin-compiler/Dockerfile index a62fed80ac4..6ade3829556 100644 --- a/ci/images/plugin-compiler/Dockerfile +++ b/ci/images/plugin-compiler/Dockerfile @@ -1,34 +1,23 @@ -ARG BASE_IMAGE -FROM ${BASE_IMAGE} +ARG GOLANG_CROSS=1.15 +FROM tykio/golang-cross:${GOLANG_CROSS} LABEL description="Image for plugin development" ENV TYK_GW_PATH=/go/src/github.com/TykTechnologies/tyk ENV GO111MODULE=on + # This directory will contain the plugin source and will be # mounted from the host box by the user using docker volumes ENV PLUGIN_SOURCE_PATH=/plugin-source RUN mkdir -p $TYK_GW_PATH $PLUGIN_SOURCE_PATH -RUN apt-get remove -y --allow-remove-essential --auto-remove mercurial \ - && rm /usr/bin/passwd && rm /usr/sbin/adduser - -ADD go.mod go.sum $TYK_GW_PATH -WORKDIR $TYK_GW_PATH -RUN go mod download - -ADD . $TYK_GW_PATH - -ARG GITHUB_SHA -ARG GITHUB_TAG -ARG BASE_IMAGE -ENV BASE_IMAGE ${BASE_IMAGE} -ENV GITHUB_SHA ${GITHUB_SHA} -ENV GITHUB_TAG ${GITHUB_TAG} - COPY ci/images/plugin-compiler/data/build.sh /build.sh RUN chmod +x /build.sh +COPY . $TYK_GW_PATH +RUN cd $TYK_GW_PATH && go mod vendor + ENTRYPOINT ["/build.sh"] + diff --git a/ci/images/plugin-compiler/data/basic-plugin/go.mod b/ci/images/plugin-compiler/data/basic-plugin/go.mod deleted file mode 100644 index f0793995cc2..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module example.com/basic-plugin - -go 1.19 diff --git a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go b/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go deleted file mode 100644 index 4d1be1d6517..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin.go +++ /dev/null @@ -1,196 +0,0 @@ -package main - -import ( - "bufio" - "bytes" - "encoding/base64" - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/buger/jsonparser" - - "github.com/TykTechnologies/tyk-pump/analytics" - "github.com/TykTechnologies/tyk/ctx" - "github.com/TykTechnologies/tyk/header" - "github.com/TykTechnologies/tyk/user" -) - -// MyPluginPre checks if session is NOT present, adds custom header -// with initial URI path and will be used as "pre" custom MW -func MyPluginPre(rw http.ResponseWriter, r *http.Request) { - session := ctx.GetSession(r) - if session != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - rw.Header().Add(header.XInitialURI, r.URL.RequestURI()) -} - -// MyPluginAuthCheck does custom auth and will be used as -// "auth_check" custom MW -func MyPluginAuthCheck(rw http.ResponseWriter, r *http.Request) { - // perform auth (only one token "abc" is allowed) - token := r.Header.Get(header.Authorization) - if token != "abc" { - rw.Header().Add(header.XAuthResult, "failed") - rw.WriteHeader(http.StatusForbidden) - _, _ = rw.Write([]byte("auth failed")) - return - } - - // create session - session := &user.SessionState{ - OrgID: "default", - Alias: "abc-session", - KeyID: token, - } - - ctx.SetSession(r, session, true, true) - rw.Header().Add(header.XAuthResult, "OK") -} - -// MyPluginPostKeyAuth checks if session is present, adds custom header with session-alias -// and will be used as "post_key_auth" custom MW -func MyPluginPostKeyAuth(rw http.ResponseWriter, r *http.Request) { - session := ctx.GetSession(r) - if session == nil { - rw.Header().Add(header.XSessionAlias, "not found") - rw.WriteHeader(http.StatusInternalServerError) - return - } - - rw.Header().Add(header.XSessionAlias, session.Alias) -} - -// MyPluginPost prepares and sends reply, will be used as "post" custom MW -func MyPluginPost(rw http.ResponseWriter, r *http.Request) { - - replyData := map[string]interface{}{ - "message": "post message", - } - - jsonData, err := json.Marshal(replyData) - if err != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - apiDefinition := ctx.GetDefinition(r) - if apiDefinition == nil { - rw.Header().Add("X-Plugin-Data", "null") - } else { - pluginConfig, ok := apiDefinition.ConfigData["my-context-data"].(string) - if !ok || pluginConfig == "" { - rw.Header().Add("X-Plugin-Data", "null") - } else { - rw.Header().Add("X-Plugin-Data", pluginConfig) - } - - } - rw.Header().Set(header.ContentType, header.ApplicationJSON) - rw.WriteHeader(http.StatusOK) - rw.Write(jsonData) -} - -// MyPluginResponse intercepts response from upstream which we can then manipulate -func MyPluginResponse(rw http.ResponseWriter, res *http.Response, req *http.Request) { - - res.Header.Add("X-Response-Added", "resp-added") - - var buf bytes.Buffer - - buf.Write([]byte(`{"message":"response injected message"}`)) - - res.Body = ioutil.NopCloser(&buf) - - apiDefinition := ctx.GetDefinition(req) - if apiDefinition == nil { - res.Header.Add("X-Plugin-Data", "null") - return - } - pluginConfig, ok := apiDefinition.ConfigData["my-context-data"].(string) - if !ok || pluginConfig == "" { - res.Header.Add("X-Plugin-Data", "null") - return - } - res.Header.Add("X-Plugin-Data", pluginConfig) -} - -func MyPluginPerPathFoo(rw http.ResponseWriter, r *http.Request) { - - rw.Header().Add("X-foo", "foo") - -} - -func MyPluginPerPathBar(rw http.ResponseWriter, r *http.Request) { - rw.Header().Add("X-bar", "bar") - -} - -func MyPluginPerPathResp(rw http.ResponseWriter, r *http.Request) { - // prepare data to send - replyData := map[string]string{ - "current_time": "now", - } - - jsonData, err := json.Marshal(replyData) - if err != nil { - rw.WriteHeader(http.StatusInternalServerError) - return - } - - // send HTTP response from Golang plugin - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(http.StatusOK) - rw.Write(jsonData) -} - -func MyAnalyticsPluginDeleteHeader(record *analytics.AnalyticsRecord) { - str, err := base64.StdEncoding.DecodeString(record.RawResponse) - if err != nil { - return - } - - var b = &bytes.Buffer{} - b.Write(str) - - r := bufio.NewReader(b) - var resp *http.Response - resp, err = http.ReadResponse(r, nil) - if err != nil { - return - } - resp.Header.Del("Server") - var bNew bytes.Buffer - _ = resp.Write(&bNew) - record.RawResponse = base64.StdEncoding.EncodeToString(bNew.Bytes()) -} - -func MyAnalyticsPluginMaskJSONLoginBody(record *analytics.AnalyticsRecord) { - if record.ContentLength < 1 { - return - } - d, err := base64.StdEncoding.DecodeString(record.RawRequest) - if err != nil { - return - } - var mask = []byte("\"****\"") - const endOfHeaders = "\r\n\r\n" - paths := [][]string{ - {"email"}, - {"password"}, - {"data", "email"}, - {"data", "password"}, - } - if i := bytes.Index(d, []byte(endOfHeaders)); i > 0 || (i+4) < len(d) { - body := d[i+4:] - jsonparser.EachKey(body, func(idx int, _ []byte, _ jsonparser.ValueType, _ error) { - body, _ = jsonparser.Set(body, mask, paths[idx]...) - }, paths...) - if err == nil { - record.RawRequest = base64.StdEncoding.EncodeToString(append(d[:i+4], body...)) - } - } -} diff --git a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go b/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go deleted file mode 100644 index c3a8ff89c85..00000000000 --- a/ci/images/plugin-compiler/data/basic-plugin/test_goplugin_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "bytes" - "encoding/base64" - "fmt" - - "github.com/buger/jsonparser" - - "github.com/TykTechnologies/tyk-pump/analytics" -) - -func ExampleMyAnalyticsPluginDeleteHeader() { - record := analytics.AnalyticsRecord{ - ContentLength: 5, - RawResponse: base64.StdEncoding.EncodeToString([]byte("HTTP/1.1 200 OK\r\nServer: golang\r\nContent-Length: 5\r\n\r\nHello")), - } - MyAnalyticsPluginDeleteHeader(&record) - data, _ := base64.StdEncoding.DecodeString(record.RawResponse) - fmt.Printf("%q", string(data)) - // Output: "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello" -} - -func ExampleMyAnalyticsPluginMaskJSONLoginBody() { - record := analytics.AnalyticsRecord{ - ContentLength: 72, - RawRequest: base64.StdEncoding.EncodeToString([]byte("POST / HTTP/1.1\r\nHost: server.com\r\nContent-Length: 72\r\n\r\n{\"email\": \"m\", \"password\": \"p\", \"data\": {\"email\": \"m\", \"password\": \"p\"}}")), - } - MyAnalyticsPluginMaskJSONLoginBody(&record) - data, _ := base64.StdEncoding.DecodeString(record.RawRequest) - const endOfHeaders = "\r\n\r\n" - paths := [][]string{ - {"email"}, - {"password"}, - {"data", "email"}, - {"data", "password"}, - } - if i := bytes.Index(data, []byte(endOfHeaders)); i > 0 || (i+4) < len(data) { - jsonparser.EachKey(data[i+4:], func(_ int, v []byte, _ jsonparser.ValueType, _ error) { - fmt.Println(string(v)) - }, paths...) - } - // Output: **** - //**** - //**** - //**** -} diff --git a/ci/images/plugin-compiler/data/build.sh b/ci/images/plugin-compiler/data/build.sh index 0d8b919bbc0..e193e189743 100755 --- a/ci/images/plugin-compiler/data/build.sh +++ b/ci/images/plugin-compiler/data/build.sh @@ -1,34 +1,10 @@ #!/bin/bash -set -e - -GATEWAY_VERSION=$(echo $GITHUB_TAG | perl -n -e'/v(\d+).(\d+).(\d+)/'' && print "v$1\.$2\.$3"') - -# Plugin compiler arguments: -# -# - 1. plugin_name = vendor-plugin.so -# - 2. plugin_id = optional, sets build folder to `/opt/plugin_{plugin_name}{plugin_id}` -# - 3. GOOS = optional override of GOOS -# - 4. GOARCH = optional override of GOARCH -# -# The script will build a plugin named according to the following: -# -# - `{plugin_name%.*}_{GATEWAY_VERSION}_{GOOS}_{GOARCH}.so` -# -# If GOOS and GOARCH are not set, it will build `{plugin_name}`. -# -# Example command: ./build.sh -# Example output: tyk-extras_5.0.0_linux_amd64.so +set -xe plugin_name=$1 plugin_id=$2 -GOOS=${3:-$(go env GOOS)} -GOARCH=${4:-$(go env GOARCH)} -# Some defaults that can be overriden with env -WORKSPACE_ROOT=$(dirname $TYK_GW_PATH) - -PLUGIN_SOURCE_PATH=${PLUGIN_SOURCE_PATH:-"/plugin-source"} -PLUGIN_BUILD_PATH=${PLUGIN_BUILD_PATH:-"${WORKSPACE_ROOT}/plugin_${plugin_name%.*}$plugin_id"} +PLUGIN_BUILD_PATH="/go/src/plugin_${plugin_name%.*}$plugin_id" function usage() { cat <