Sign and verify requests with HTTP Message Signatures
Introduction
In modern API-driven architectures, ensuring the integrity and authenticity of API requests is crucial to prevent unauthorized access and protect sensitive data. The HTTP Message Signatures plugin for Gate provides a robust solution for signing and verifying API requests using digital signatures. This use case guide will walk you through the process of implementing HTTP Message Signatures in your API requests using the Gate plugin.
The plugin implements HTTP Message Signatures, RFC 9421.
Benefits of HTTP Message Signatures over TLS
While TLS (Transport Layer Security) is crucial for securing data in transit by encrypting the connection, it has some limitations, HTTP Message Signatures complement TLS by addressing its limitations and providing additional security benefits:
End-to-End Data Integrity and Authentication
- Persistent Integrity: With HTTP Message Signatures, each message or request is signed individually, ensuring its integrity and authenticity are maintained from the sender to the final recipient, regardless of how many intermediaries handle it.
- Non-repudiation: The signature provides proof of the sender’s identity, and the sender cannot deny having sent the message, ensuring accountability.
Protection Against Intermediaries
- Intermediate Trust: HTTP Message Signatures ensure that even if data passes through untrusted intermediaries, the integrity and authenticity of the message remain intact. Intermediaries cannot alter the data without invalidating the signature.
- Secure Delegation: In scenarios where requests are forwarded or proxied, each entity can verify the original signature, ensuring that the message has not been tampered with.
Granular Security Controls
- Request-Level Granularity: By signing individual requests, different parts of a system can enforce security policies at a more granular level. This is particularly useful in microservices architectures and APIs where different endpoints might require different security measures.
- Selective Verification: Only specific parts of the message (such as headers or body content) can be signed and verified, providing flexibility in what needs to be protected.
Compatibility with Existing Infrastructure: HTTP Message Signatures can be used in conjunction with existing infrastructure, such as load balancers or reverse proxies, without the need for TLS termination at each component. The signatures are validated at the application level, providing end-to-end security.
Example Walkthrough
Configuration
Configure Signing and Verification Options: Contrary to other Gate plugins, the HTTP Message Signature plugin has a top-level configuration, as shown below:
request_signing:
sign_requests: true
verify_requests: true
block_unverified: true
verification_keys:
key1: |
-----BEGIN PUBLIC KEY-----
UFkwEwYHKoyIzj0CAQYIKoZIzj0DAQcDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPp
Y2MAogStF33OiQj30+d/mAWM9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
-----END PUBLIC KEY-----
key2: |
-----BEGIN PUBLIC KEY-----
AFkyEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPp
Y2MAogStF33OiQj30+d/mAWM9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
-----END PUBLIC KEY-----
signing_key:
key_id: "my_key_id"
key_value: |
-----BEGIN EC PRIVATE KEY-----
MHcCYTUDMIA34DuzRBiZttW9R524G2VPqt1GDTgyXE5SSFF+3NOPboAoGCCqGSM49
AwEHoUQDQgAEaL3e+E0BkzOkK+g61fttW2wQEmPpY2MAogStF33OiQj30+d/mAWM
9jxLbP9DWzGYPqagg8e0LVHtzzB2l0ptJg==
-----END EC PRIVATE KEY-----sign_requests
: Set totrue
if you want to sign all outgoing requests.verify_requests
: Set totrue
if you want to verify all incoming requests.block_unverified
: Set totrue
if you want to block requests that fail signature verification.verification_keys
: Provide a map of key IDs and their corresponding public keys for verification.key_id
: Specify the ID of the signing key.signing_key
: Provide the private key used for signing requests.
In production the private key should be retrieved from the secret manger using the secret_engine
configuration.
(Optionally) Apply the Request Signature Plugin: To enable HTTP Message Signatures for your API endpoints, you can apply the plugin to the desired URL pattern:
urls:
- pattern: "/api/*"
sign_req: true
verify_req: trueThis configuration verifies all the incoming signatures to
/api/*
and signs all outgoing requests.
Testing
Let's run Gate to forward requests to to /api/*
to localhost:8090
and enable HTTP Message Signatures:
curl --trace - -v http://gate/api
nc -l 8090
GET /api HTTP/1.1
Host: localhost:8090
User-Agent: curl/8.4.0
Accept: */*
Signature: sig=:+3s/8dSuE1arX/6QiGkafpE7eQOXO3xYfzLyPqTHakMw6dl/fiAWoQJ5zz5ysknQ9e8gzoNqj0eSq761/w4c+Q==:
Signature-Input: sig=();created=1716310006;keyid="my_key_id";alg="ecdsa-p256-sha256"
X-B3-Sampled: 1
X-B3-Spanid: 5c53064c9b5c8442
X-B3-Traceid: 564b117b5a50960efb0d655d8d2d49dc
Accept-Encoding: gzip
We can see that Gate added the Signature
and Signature-Input
to the request to the upstream server using the private key my_key_id
associated with the Gate instance.
Conclusion
The HTTP Message Signatures plugin for Gate provides a powerful solution for securing API requests and ensuring their integrity and authenticity. By signing and verifying requests using digital signatures, you can protect your APIs from unauthorized access and tampering. The plugin offers flexibility in configuration options and seamlessly integrates with your existing URL patterns. By leveraging HTTP Message Signatures, you can enhance the security of your API ecosystem and build trust with your API consumers.