Skip to content

Commit e7905ba

Browse files
committed
Add support for AWS named profiles in settings.py
This update introduces the ability to use AWS named profiles via the `AWS_IAM_PROFILE` setting. Additionally, documentation and tests have been updated to reflect the new functionality and ensure proper configuration and behavior. The version is incremented to 1.3.0 to reflect this enhancement.
1 parent 16df591 commit e7905ba

File tree

6 files changed

+76
-20
lines changed

6 files changed

+76
-20
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
# 1.2`0 - 12th May 2025
1+
# 1.3.0 - 26th May 2025
2+
- Added in support for AWS Profiles
3+
- Updated the documentation to include examples of how to configure settings.py
4+
5+
# 1.2.1 - 12th May 2025
26
- 1.2.0 was built using an older version so the package had the wrong name, it's been yanked, so use 1.2.1 instead
37

48
# 1.2.0 - 12th May 2025 - yanked

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,37 @@ pip install django-aws-api-gateway-websockets
5151
## settings.py
5252
Add ```django_aws_api_gateway_websockets``` into ```INSTALLED_APPS```
5353

54+
### Decide on AWS Credential Setup
55+
This package supports differing ways to connect to AWS, depending on the option you require depends on which settings
56+
you will need to define.
57+
58+
#### Using the IAM role of the instance
59+
If you are running this package on an EC2 Instance that has an IAM profile then you only need to specifc the region to
60+
connect to by setting the ```AWS_REGION_NAME``` in ```settings.py```.
61+
62+
E.G. ```AWS_REGION_NAME="eu-west-1"``` will mean this package will connect to the Ireland region using the IAM profile
63+
of the machine
64+
65+
#### Named Profiles (AWS_IAM_PROFILE)
66+
You can use a named profile by setting ```AWS_IAM_PROFILE``` to the name of the profile on your computer.
67+
68+
E.G ```AWS_IAM_PROFILE="example"```. As the profile contains the region you do not need to set anything else.
69+
70+
**NOTE:** If you are using ```Django-Storages``` you may already have set the value against ```AWS_S3_SESSION_PROFILE```
71+
72+
#### Using AWS IAM Access Key and Secret
73+
Alternatively you can specify the exact ACCESS_KEY, SECRET_ACCESS_KEY and REGION_NAME you wish to use by setting the
74+
three following ```settings.py``` values.
75+
76+
```
77+
AWS_ACCESS_KEY_ID="My-Key-Here"
78+
AWS_SECRET_ACCESS_KEY="My-Secret-Key-Here"
79+
AWS_REGION_NAME="region-to-use"
80+
```
81+
82+
The order above is the recommended order to use. As with all custom Django settings it's advisable to store the real
83+
values in either a secrets manager or environmental values. I tend to use https://pypi.org/project/python-decouple/
84+
5485
### IMPORTANT
5586
If your site is **not** already running cross-origin you will need to update some settings and flush the sessions to ensure the primary domain and subdomain will work.
5687

django_aws_api_gateway_websockets/models.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,25 @@
99
def get_boto3_client(service: str = "apigatewayv2", **kwargs):
1010
"""Returns the boto3 client to use.
1111
12-
:param str servivce: apigatewayv2 | apigatewaymanagementapi
12+
When running within AWS, if you are using an IAM Role with the service, E.G. on an EC2 instance, you need to
13+
set AWS_REGION_NAME within settings.py
1314
14-
If you are using an IAM Role then you just need to set AWS_REGION_NAME within settings.py otherwise you need to
15-
set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as well with the correct values
15+
Otherwise you can either use a named profile using settings.AWS_IAM_PROFILE or you can set the credentials
16+
using both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
17+
18+
:param str service: apigatewayv2 | apigatewaymanagementapi
1619
"""
17-
if (
20+
if hasattr(settings, "AWS_IAM_PROFILE") and settings.AWS_IAM_PROFILE:
21+
# Used a named profile where credentials are stored within .aws folder
22+
session = boto3.Session(profile_name=settings.AWS_IAM_PROFILE)
23+
client = session.client(service)
24+
elif (
1825
hasattr(settings, "AWS_ACCESS_KEY_ID")
1926
and settings.AWS_ACCESS_KEY_ID
2027
and hasattr(settings, "AWS_SECRET_ACCESS_KEY")
2128
and settings.AWS_SECRET_ACCESS_KEY
2229
):
30+
# Use specific access and secret keys
2331
if not hasattr(settings, "AWS_REGION_NAME") or not settings.AWS_REGION_NAME:
2432
raise RuntimeError("AWS_REGION_NAME must be set within settings.py")
2533

@@ -31,6 +39,7 @@ def get_boto3_client(service: str = "apigatewayv2", **kwargs):
3139
**kwargs,
3240
)
3341
else:
42+
# Use the IAM Role of the machine
3443
if not hasattr(settings, "AWS_REGION_NAME") or not settings.AWS_REGION_NAME:
3544
raise RuntimeError("AWS_REGION_NAME must be set within settings.py")
3645
client = boto3.client(service, region_name=settings.AWS_REGION_NAME, **kwargs)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ skip = [
99

1010
[project]
1111
name = "django-aws-api-gateway-websockets"
12-
version = "1.2.1"
12+
version = "1.3.0"
1313
authors = [
1414
{ name="Steven Mapes", email="steve@stevenmapes.com" },
1515
]

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = django-aws-api-gateway-websockets
3-
version = 1.2.1
3+
version = 1.3.0
44
description = Created to allow Django projects to be used as a HTTP backend for AWS API Gateway websockets
55
long_description = file: README.md
66
long_description_content_type = text/markdown

tests/test_models.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,42 @@
1414

1515

1616
class GetBoto3ClientTestCase(SimpleTestCase):
17+
1718
@override_settings(
18-
AWS_IAM_PROFILE="FakeIAMProfile",
19+
AWS_IAM_PROFILE=None,
1920
AWS_ACCESS_KEY_ID=None,
2021
AWS_SECRET_ACCESS_KEY=None,
21-
AWS_REGION_NAME=None,
22+
AWS_REGION_NAME="",
2223
)
2324
@patch("django_aws_api_gateway_websockets.models.boto3")
24-
def test_exception_raised_if_no_credentials_other_than_aws_iam_profile(
25-
self, mock_boto3
26-
):
27-
"""Named profiles are not supported yet by this package. In theory they may be the preferred method for
28-
local and non-AWS hosted deployments.
29-
30-
todo - I will add support in later
25+
def test_region_is_required_to_use_machine_iam(self, mock_boto3):
26+
"""Test what happens when there are not enough credentials
3127
3228
:param MagicMock mock_boto3:
3329
:return:
3430
"""
35-
with self.assertRaises(RuntimeError) as e:
31+
with self.assertRaises(RuntimeError) as re:
3632
get_boto3_client("s3")
33+
self.assertEqual("AWS_REGION_NAME must be set within settings.py", str(re))
3734

38-
self.assertEqual(
39-
str(e.exception), "AWS_REGION_NAME must be set within settings.py"
40-
)
35+
@override_settings(
36+
AWS_IAM_PROFILE="FakeIAMProfile",
37+
AWS_ACCESS_KEY_ID=None,
38+
AWS_SECRET_ACCESS_KEY=None,
39+
AWS_REGION_NAME=None,
40+
)
41+
@patch("django_aws_api_gateway_websockets.models.boto3")
42+
def test_boto3_connection_support_named_profiles(self, mock_boto3):
43+
"""Named profiles are supported via the settings.py variable AWS_IAM_PROFILE.
44+
45+
:param MagicMock mock_boto3:
46+
:return:
47+
"""
48+
service = "s3"
49+
res = get_boto3_client(service)
50+
mock_boto3.Session.assert_called_with(profile_name=settings.AWS_IAM_PROFILE)
51+
mock_boto3.Session.return_value.client.assert_called_with(service)
52+
self.assertEqual(res, mock_boto3.Session.return_value.client.return_value)
4153

4254
@override_settings(
4355
AWS_ACCESS_KEY_ID=None,

0 commit comments

Comments
 (0)