diff --git a/docs/modules/resty.aws.utils.html b/docs/modules/resty.aws.utils.html
index 78d2af5..41d9f5d 100644
--- a/docs/modules/resty.aws.utils.html
+++ b/docs/modules/resty.aws.utils.html
@@ -84,6 +84,10 @@
Utils.getIDMSMetadata (subpath, version) |
Fetches IDMS Metadata (EC2 and EKS). |
+
+ | Utils.getInstanceSignature () |
+ Fetches the instance identity document and signature from IDMS. |
+
@@ -190,6 +194,22 @@ Returns:
+
+
+
+
+ Utils.getInstanceSignature ()
+
+
+ Fetches the instance identity document and signature from IDMS.
+ Will make a call to the AWS identity endpoint and hence might timeout if ran on anything
+ else than an EC2-instance.
+ Returns:
+
+ body & content-type (if json, the body will be decoded to a Lua table), or nil+err
+
+
+
diff --git a/spec/01-generic/04-utils_spec.lua b/spec/01-generic/04-utils_spec.lua
new file mode 100644
index 0000000..cdc87b9
--- /dev/null
+++ b/spec/01-generic/04-utils_spec.lua
@@ -0,0 +1,58 @@
+local utils = require "resty.aws.utils"
+
+describe("Utils:getInstanceSignature", function()
+ local mock_token = "mock-imds-token-12345"
+ local mock_signature = "-----BEGIN PKCS7-----\nMIAGCSqGSIb3DQEHAqCAMIACAQExCzAJ\n-----END PKCS7-----\n"
+ local expected_signature = "-----BEGIN PKCS7-----MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJ-----END PKCS7-----"
+
+ local http = {
+ new = function()
+ return {
+ connect = function() return true end,
+ set_timeouts = function() return true end,
+ close = function() end,
+ request_uri = function(self, uri, opts)
+ if string.find(uri, "/latest/api/token") then
+ ngx.log(ngx.ERR, "Returning mock IMDSv2 token")
+ return {
+ status = 200,
+ headers = {
+ ["Content-Type"] = "application/xml",
+ },
+ body = mock_token
+ }
+ elseif string.find(uri, "/rsa2048") then
+ return {
+ status = 200,
+ headers = {
+ ["Content-Type"] = "application/xml",
+ },
+ body = mock_signature
+ }
+ end
+ end,
+ }
+ end
+ }
+
+ setup(function()
+ package.loaded["resty.luasocket.http"] = http
+ end)
+
+ teardown(function()
+ package.loaded["resty.luasocket.http"] = nil
+ end)
+
+ before_each(function()
+ package.loaded["resty.luasocket.http"] = http
+ package.loaded["resty.aws.utils"] = nil
+ utils = require "resty.aws.utils"
+ end)
+
+ it("fetches instance signature successfully with IMDSv2", function()
+ local signature, err = utils.getInstanceSignature()
+
+ assert.is_nil(err)
+ assert.equals(expected_signature, signature)
+ end)
+end)
diff --git a/src/resty/aws/utils.lua b/src/resty/aws/utils.lua
index 8e078e9..ba5df23 100644
--- a/src/resty/aws/utils.lua
+++ b/src/resty/aws/utils.lua
@@ -294,6 +294,26 @@ do -- getCurrentRegion
return detected_region, detected_error
end
+
+
+ --- Retrieves the RSA2048 signature from EC2 instance metadata.
+ -- @return signature string, or nil+err
+ function Utils.getInstanceSignature()
+ local headers = { ["X-aws-ec2-metadata-token-ttl-seconds"] = "21600" }
+ local token, err = make_request(IDMS_URI .. "/latest/api/token", "PUT", headers)
+ if not token then
+ return nil, "failed getting IDMSToken: " .. tostring(err)
+ end
+
+ headers = { ["X-aws-ec2-metadata-token"] = token }
+ local signature, err = make_request(IDMS_URI .. "/latest/dynamic/instance-identity/rsa2048", "GET", headers)
+ if not signature then
+ return nil, "failed getting instance signature: " .. tostring(err)
+ end
+
+ signature = signature:gsub("\n", "")
+ return signature
+ end
end
return Utils