diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 62b06d3..9508732 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,9 +1,10 @@ name: Test -on: [push, pull_request] - -env: - LIBEXPAT_DOWNLOAD_URL: https://github.com/libexpat/libexpat/releases/download/R_2_5_0/expat-2.5.0.tar.gz +on: + push: + branches: [main] + pull_request: + branches: [main] jobs: @@ -16,6 +17,8 @@ jobs: openresty_version: - 1.17.8.2 - 1.19.9.1 + - 1.21.4.3 + - 1.25.3.2 runs-on: ubuntu-latest container: @@ -30,18 +33,6 @@ jobs: apk add --no-cache curl perl bash wget git perl-dev libarchive-tools nodejs jq ln -s /usr/bin/bsdtar /usr/bin/tar - - name: Build libexpat - if: matrix.openresty_version == '1.17.8.2' - run: | - mkdir -p /tmp/expat - curl -Ls $LIBEXPAT_DOWNLOAD_URL | tar -xz --strip-components=1 -f - -C /tmp/expat - cd /tmp/expat && ./configure && make && make install - - - name: Install libexpat from package manager - if: matrix.openresty_version == '1.19.9.1' - run: | - apk add --no-cache expat-dev - - name: Cache uses: actions/cache@v2 with: diff --git a/lua-resty-aws-dev-1.rockspec.template b/lua-resty-aws-dev-1.rockspec.template index 9f05ac9..ffb6f62 100644 --- a/lua-resty-aws-dev-1.rockspec.template +++ b/lua-resty-aws-dev-1.rockspec.template @@ -27,7 +27,6 @@ dependencies = { "lua-resty-http >= 0.16", "lua-resty-luasocket ~> 1", "lua-resty-openssl >= 0.8.17", - "luaexpat >= 1.5.1", } build = { diff --git a/spec/02-requests/02-build_request_spec.lua b/spec/02-requests/02-build_request_spec.lua index 9e3a1b5..937fc7f 100644 --- a/spec/02-requests/02-build_request_spec.lua +++ b/spec/02-requests/02-build_request_spec.lua @@ -1,5 +1,4 @@ local cjson = require "cjson" -local pl_stringx = require "pl.stringx" describe("operations protocol", function() @@ -37,10 +36,6 @@ describe("operations protocol", function() }, input = { type = "structure", - locationName = "mainXmlElement", -- only for rest-xml protocol - xmlNamespace = { -- only for rest-xml protocol - uri = "cool-name-space" - }, required = { "RoleArn", "RoleSessionName" @@ -206,6 +201,7 @@ describe("operations protocol", function() local request = build_request(operation, config, params) assert.same({ headers = { + ["Accept"] = 'application/json', ["X-Sooper-Secret"] = "towel", ["X-Amz-Target"] = "sts.AssumeRole", ["Host"] = "sts.amazonaws.com", @@ -239,6 +235,7 @@ describe("operations protocol", function() assert.same({ headers = { + ["Accept"] = 'application/json', ["X-Sooper-Secret"] = "towel", ["Content-Length"] = 172, ["Content-Type"] = "application/x-amz-json-1.0", @@ -279,6 +276,7 @@ describe("operations protocol", function() assert.same({ headers = { + ["Accept"] = 'application/json', ["X-Sooper-Secret"] = "towel", ["Content-Length"] = 172, ["Content-Type"] = "application/x-amz-json-1.0", @@ -314,6 +312,7 @@ describe("operations protocol", function() assert.same({ headers = { + ["Accept"] = 'application/json', ["Content-Length"] = 4, ["X-Amz-Target"] = "s3.PutObject", ["Host"] = "s3.amazonaws.com", @@ -328,85 +327,6 @@ describe("operations protocol", function() end) - it("rest-xml: querystring, uri, header and body params", function() - - config.protocol = "rest-xml" - - local request = build_request(operation, config, params) - if request and request.body then - -- cannot reliably compare non-canonicalized json, so decode to Lua table - local body_lines = pl_stringx.splitlines(request.body) - for i, line in ipairs(body_lines) do - body_lines[i] = pl_stringx.strip(line, ' ') - end - request.body = assert(require("pl.xml").parse(table.concat(body_lines, ""))) - local to_lua = function(t) - -- convert LOM to comparable Lua table - for i, v in ipairs(t) do - if type(v) == "table" and v.tag then - t[v.tag] = v - v.tag = nil - t[i] = nil - if type(v.attr) == "table" and not next(v.attr) then - -- delete empty attr table - v.attr = nil - end - end - end - end - to_lua(request.body) - to_lua(request.body.someSubStructure) - end - - assert.same({ - headers = { - ["X-Sooper-Secret"] = "towel", - ["Content-Length"] = 456, - ["Content-Type"] = "application/xml", - ["X-Amz-Target"] = "sts.AssumeRole", - ["Host"] = "sts.amazonaws.com", - }, - method = 'POST', - path = '/hello%20world/42', - host = 'sts.amazonaws.com', - port = 443, - body = { - RoleArn = { - [1] = 'hello' }, - RoleSessionName = { - [1] = 'world' }, - BinaryData = { - [1] = binary_data }, - attr = { - [1] = 'xmlns', - xmlns = 'cool-name-space' }, - someSubStructure = { - hello = { - [1] = 'the default hello thinghy' }, - world = { - [1] = 'the default world thinghy' } }, - subList = { - [1] = { - [1] = '1', - attr = {}, - tag = 'listELement' }, - [2] = { - [1] = '2', - attr = {}, - tag = 'listELement' }, - [3] = { - [1] = '3', - attr = {}, - tag = 'listELement' } }, - tag = 'mainXmlElement' }, - query = { - UserId = "Arthur Dent", - nice = '', - } - }, request) - end) - - pending("ec2: querystring, uri, header and body params", function() config.protocol = "ec2" diff --git a/spec/02-requests/03-execute_spec.lua b/spec/02-requests/03-execute_spec.lua index 48b0c2b..7c80a38 100644 --- a/spec/02-requests/03-execute_spec.lua +++ b/spec/02-requests/03-execute_spec.lua @@ -51,7 +51,8 @@ describe("request execution", function() it("tls defaults to true", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ @@ -76,7 +77,8 @@ describe("request execution", function() it("support configuring tls false", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ @@ -103,7 +105,8 @@ describe("request execution", function() it("support configuring ssl verify false", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json" } config.credentials = Credentials:new({ @@ -129,7 +132,8 @@ describe("request execution", function() it("support configure timeout", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ @@ -155,7 +159,8 @@ describe("request execution", function() it("support configure keepalive idle timeout", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ @@ -181,7 +186,8 @@ describe("request execution", function() it("support set proxy options", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ @@ -217,7 +223,8 @@ describe("request execution", function() it("decoded json body should have array metatable", function () local config = { - region = "us-east-1" + region = "us-east-1", + protocol = "json", } config.credentials = Credentials:new({ diff --git a/src/resty/aws/credentials/ChainableTemporaryCredentials.lua b/src/resty/aws/credentials/ChainableTemporaryCredentials.lua index 4121112..51805e4 100644 --- a/src/resty/aws/credentials/ChainableTemporaryCredentials.lua +++ b/src/resty/aws/credentials/ChainableTemporaryCredentials.lua @@ -1,7 +1,7 @@ --- ChainableTemporaryCredentials class. -- @classmod ChainableTemporaryCredentials -local lom = require("lxp.lom") +local cjson = require("cjson") -- Create class @@ -117,19 +117,17 @@ function ChainableTemporaryCredentials:refresh() return nil, "request for token returned invalid body: " .. err end - local resp_body_lom, err = lom.parse(response.body) - if not resp_body_lom then + local data, err = cjson.decode(response.body) + if not data then return nil, "failed to parse response body: " .. err end - - local cred_lom = lom.find_elem(lom.find_elem(resp_body_lom, "AssumeRoleResult"), "Credentials") - - local AccessKeyId = lom.find_elem(cred_lom, "AccessKeyId")[1] - local SecretAccessKey = lom.find_elem(cred_lom, "SecretAccessKey")[1] - local SessionToken = lom.find_elem(cred_lom, "SessionToken")[1] - local Expiration = lom.find_elem(cred_lom, "Expiration")[1] - - self:set(AccessKeyId, SecretAccessKey, SessionToken, Expiration) + local credentials = data.AssumeRoleResponse.AssumeRoleResult.Credentials + self:set( + credentials.AccessKeyId, + credentials.SecretAccessKey, + credentials.SessionToken, + credentials.Expiration + ) return true end diff --git a/src/resty/aws/credentials/TokenFileWebIdentityCredentials.lua b/src/resty/aws/credentials/TokenFileWebIdentityCredentials.lua index fc19c27..14e9dc2 100644 --- a/src/resty/aws/credentials/TokenFileWebIdentityCredentials.lua +++ b/src/resty/aws/credentials/TokenFileWebIdentityCredentials.lua @@ -2,7 +2,7 @@ -- @classmod TokenFileWebIdentityCredentials local readfile = require("pl.utils").readfile -local lom = require("lxp.lom") +local cjson = require("cjson") local aws_config = require("resty.aws.config") @@ -79,19 +79,17 @@ function TokenFileWebIdentityCredentials:refresh() return nil, "request for token returned invalid body: " .. err end - local resp_body_lom, err = lom.parse(response.body) - if not resp_body_lom then + local data, err = cjson.decode(response.body) + if not data then return nil, "failed to parse response body: " .. err end - - local cred_lom = lom.find_elem(lom.find_elem(resp_body_lom, "AssumeRoleWithWebIdentityResult"), "Credentials") - - local AccessKeyId = lom.find_elem(cred_lom, "AccessKeyId")[1] - local SecretAccessKey = lom.find_elem(cred_lom, "SecretAccessKey")[1] - local SessionToken = lom.find_elem(cred_lom, "SessionToken")[1] - local Expiration = lom.find_elem(cred_lom, "Expiration")[1] - - self:set(AccessKeyId, SecretAccessKey, SessionToken, Expiration) + local credentials = data.AssumeRoleWithWebIdentityResponse.AssumeRoleWithWebIdentityResult.Credentials + self:set( + credentials.AccessKeyId, + credentials.SecretAccessKey, + credentials.SessionToken, + credentials.Expiration + ) return true end diff --git a/src/resty/aws/request/build.lua b/src/resty/aws/request/build.lua index 7b5794e..c57e9c9 100644 --- a/src/resty/aws/request/build.lua +++ b/src/resty/aws/request/build.lua @@ -4,52 +4,11 @@ local protocols = { ec2 = true, json = true, query = true, - ["rest-xml"] = true, ["rest-json"] = true, } -local function poor_mans_xml_encoding(output, shape, shape_name, data, indent) - local indent = indent or 0 - local prefix = string.rep(" ", indent) - local element = shape.locationName or shape_name - - local xmlns = "" - if (shape.xmlNamespace or {}).uri then - xmlns = (' xmlns="%s"'):format(shape.xmlNamespace.uri) - end - if shape.type == "structure" or - shape.type == "list" or - shape.type == "map" then - -- nested structures - output[#output+1] = prefix .. '<' .. element .. xmlns .. ">" - - if shape.type == "structure" then - for name, member in pairs(shape.members) do - if data[name] ~= nil then - poor_mans_xml_encoding(output, member, name, data[name], indent + 1) - end - end - - elseif shape.type == "list" then - for i, member_data in ipairs(data or {}) do - poor_mans_xml_encoding(output, shape.member, "unknown", member_data, indent + 1) - end - - else -- shape.type == "map" - error("protocol 'rest-xml' hasn't implemented the 'map' type") - - end - - output[#output+1] = prefix .. '" - else - -- just a scalar value - output[#output+1] = prefix .. '<' .. element .. xmlns .. ">" .. - tostring(data) .. '" - end -end - local ESCAPE_PATTERN = "[^!#$&'()*+,/:;=?@[\\]A-Z\\d-_.~%]" local function percent_escape(m) @@ -139,7 +98,7 @@ local function build_request(operation, config, params) path = uri, method = http.method, query = {}, - headers = { ["Host"] = host_header, }, + headers = { ["Host"] = host_header, ["Accept"] = "application/json" }, host = host, port = port, } @@ -236,19 +195,6 @@ local function build_request(operation, config, params) if config.protocol == "ec2" then error("protocol 'ec2' not implemented yet") - elseif config.protocol == "rest-xml" then - local xml_data = { - '', - } - - -- encode rest of the body data here - poor_mans_xml_encoding(xml_data, operation.input, "input", body_tbl) - - -- TODO: untested, assuming "application/xml" as the default type here??? - request.headers["Content-Type"] = request.headers["Content-Type"] or "application/xml" - request.body = table.concat(xml_data, "\n") - - else -- assuming remaining protocols "rest-json", "json", "query" to be safe to json encode local version = config.jsonVersion or '1.0'