Skip to content

Commit 28ae9a9

Browse files
committed
sigV4a
1 parent d2ca94f commit 28ae9a9

File tree

3 files changed

+143
-8
lines changed

3 files changed

+143
-8
lines changed

aws_lambda_powertools/utilities/auth/aws_auth.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing import Optional
55

66
import botocore.session
7+
from botocore import crt
78
from botocore.auth import SigV4Auth
89
from botocore.awsrequest import AWSRequest
910
from botocore.credentials import Credentials, ReadOnlyCredentials
@@ -21,6 +22,7 @@ class AWSServicePrefix(Enum):
2122
RESTAPI = "execute-api"
2223
HTTPAPI = "apigateway"
2324
APPSYNC = "appsync"
25+
S3 = "s3"
2426

2527

2628
class AuthProvider(Enum):
@@ -36,6 +38,7 @@ class AuthProvider(Enum):
3638
class AWSSigV4Auth:
3739
"""
3840
Authenticating Requests (AWS Signature Version 4)
41+
Requests that were signed with SigV4 will have SignatureVersion set to AWS4-HMAC-SHA256
3942
4043
Args:
4144
url (str): URL
@@ -107,3 +110,80 @@ def __init__(
107110

108111
def __call__(self):
109112
return self.signed_request
113+
114+
115+
class AWSSigV4aAuth:
116+
"""
117+
Authenticating Requests (AWS Signature Version 4a)
118+
Requests that were signed with SigV4A will have a SignatureVersion set to AWS4-ECDSA-P256-SHA256
119+
120+
Args:
121+
url (str): URL
122+
region (str): AWS region
123+
body (str, optional): Request body
124+
params (dict, optional): Request parameters
125+
headers (dict, optional): Request headers
126+
method (str, optional): Request method
127+
service (str, optional): AWS service
128+
access_key (str, optional): AWS access key
129+
secret_key (str, optional): AWS secret key
130+
token (str, optional): AWS session token
131+
132+
Returns:
133+
SigV4aAuth: SigV4aAuth instance
134+
135+
Examples
136+
--------
137+
**Using default credentials**
138+
>>> from aws_lambda_powertools.utilities.iam import AWSSigV4aAuth
139+
>>> auth = AWSSigV4aAuth(region="us-east-2", service=AWSServicePrefix.LATTICE, url="https://test-fake-service.vpc-lattice-svcs.us-east-2.on.aws")
140+
"""
141+
142+
def __init__(
143+
self,
144+
url: str,
145+
region: str,
146+
body: Optional[str] = None,
147+
params: Optional[dict] = None,
148+
headers: Optional[dict] = None,
149+
method: Optional[str] = "GET",
150+
service: Enum = AWSServicePrefix.LATTICE,
151+
access_key: Optional[str] = None,
152+
secret_key: Optional[str] = None,
153+
token: Optional[str] = None,
154+
):
155+
self.service = service.value
156+
self.region = region
157+
self.method = method
158+
self.url = url
159+
self.data = body
160+
self.params = params
161+
self.headers = headers
162+
163+
self.credentials: Credentials | ReadOnlyCredentials
164+
165+
if access_key and secret_key and token:
166+
self.access_key = access_key
167+
self.secret_key = secret_key
168+
self.token = token
169+
self.credentials = Credentials(access_key=self.access_key, secret_key=self.secret_key, token=self.token)
170+
else:
171+
credentials = botocore.session.Session().get_credentials()
172+
self.credentials = credentials.get_frozen_credentials()
173+
174+
if self.headers is None:
175+
self.headers = {"Content-Type": "application/json"}
176+
177+
signer = crt.auth.CrtSigV4AsymAuth(self.credentials, self.service, self.region)
178+
179+
request = AWSRequest(method=self.method, url=self.url, data=self.data, params=self.params, headers=self.headers)
180+
181+
if self.service == AWSServicePrefix.LATTICE.value:
182+
# payload signing is not supported for vpc-lattice-svcs
183+
request.context["payload_signing_enabled"] = False
184+
185+
signer.add_auth(request)
186+
self.signed_request = request.prepare()
187+
188+
def __call__(self):
189+
return self.signed_request

poetry.lock

Lines changed: 58 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ typing-extensions = "^4.11.0"
4848
datadog-lambda = { version = ">=4.77,<6.0", optional = true }
4949
aws-encryption-sdk = { version = "^3.1.1", optional = true }
5050
jsonpath-ng = { version = "^1.6.0", optional = true }
51+
awscrt = "^0.20.9"
5152

5253
[tool.poetry.dev-dependencies]
5354
coverage = { extras = ["toml"], version = "^7.5" }
@@ -122,6 +123,10 @@ types-redis = "^4.6.0.7"
122123
testcontainers = { extras = ["redis"], version = "^3.7.1" }
123124
multiprocess = "^0.70.16"
124125

126+
127+
[tool.poetry.group.dev-dependencies.dependencies]
128+
botocore = "^1.34.94"
129+
125130
[tool.coverage.run]
126131
source = ["aws_lambda_powertools"]
127132
omit = [

0 commit comments

Comments
 (0)