pulumi-django-azure 1.0.8__tar.gz → 1.0.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pulumi-django-azure might be problematic. Click here for more details.
- {pulumi-django-azure-1.0.8/src/pulumi_django_azure.egg-info → pulumi_django_azure-1.0.10}/PKG-INFO +63 -1
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/README.md +62 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/pyproject.toml +2 -2
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure/django_deployment.py +90 -2
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10/src/pulumi_django_azure.egg-info}/PKG-INFO +63 -1
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/LICENSE +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/setup.cfg +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure/__init__.py +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure.egg-info/SOURCES.txt +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure.egg-info/dependency_links.txt +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure.egg-info/requires.txt +0 -0
- {pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure.egg-info/top_level.txt +0 -0
{pulumi-django-azure-1.0.8/src/pulumi_django_azure.egg-info → pulumi_django_azure-1.0.10}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pulumi-django-azure
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.10
|
|
4
4
|
Summary: Simply deployment of Django on Azure with Pulumi
|
|
5
5
|
Author-email: Maarten Ureel <maarten@youreal.eu>
|
|
6
6
|
License: MIT License
|
|
@@ -47,8 +47,21 @@ To have a proper and secure environment, we need these components:
|
|
|
47
47
|
* PostgreSQL server
|
|
48
48
|
* Azure Communication Services to send e-mails
|
|
49
49
|
* Webapp with multiple custom host names and managed SSL for the website itself
|
|
50
|
+
* Azure Key Vault per application
|
|
50
51
|
* Webapp running pgAdmin
|
|
51
52
|
|
|
53
|
+
## Project requirements
|
|
54
|
+
Your Django project should contain a folder `cicd` with these files:
|
|
55
|
+
* pre_build.sh: commands to be executed before building the application, for example NPM install, CSS build commands,...
|
|
56
|
+
* post_build.sh: commands to be executed after building the application, e.g. cleaning up.
|
|
57
|
+
Note that this runs in the identity of the build container, so you should not run database or storage manipulations here.
|
|
58
|
+
* startup.sh: commands to run the actual application. I recommend to put at least:
|
|
59
|
+
```bash
|
|
60
|
+
python manage.py migrate
|
|
61
|
+
python manage.py collectstatic --noinput
|
|
62
|
+
gunicorn --timeout 600 --workers $((($NUM_CORES*2)+1)) --chdir $APP_PATH yourapplication.wsgi --access-logfile '-' --error-logfile '-'
|
|
63
|
+
```
|
|
64
|
+
Be sure to change `yourapplication` in the above.
|
|
52
65
|
## Installation
|
|
53
66
|
This package is published on PyPi, so you can just add pulumi-django-azure to your requirements file.
|
|
54
67
|
|
|
@@ -176,6 +189,55 @@ pgAdmin will be created with a default login:
|
|
|
176
189
|
|
|
177
190
|
Best practice is to log in right away, create a user for yourself and delete this default user.
|
|
178
191
|
|
|
192
|
+
## Azure OAuth2 / Django Social Auth
|
|
193
|
+
If you want to set up login with Azure, which would make sense since you are in the ecosystem, you need to create an App Registration in Entra ID, create a secret and then register these settings in your stack:
|
|
194
|
+
```
|
|
195
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.key' secret_ID
|
|
196
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.secret' secret_value
|
|
197
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.tenant_id' directory_tenant_id
|
|
198
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.client_id' application_id
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Then in your Django deployment, pass to the `add_django_website` command:
|
|
202
|
+
```
|
|
203
|
+
secrets={
|
|
204
|
+
"mywebsite_social_auth_azure": "AZURE_OAUTH",
|
|
205
|
+
},
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The value will be automatically stored in the vault where the application has access to.
|
|
209
|
+
The environment variable will be suffixed with `_SECRET_NAME`.
|
|
210
|
+
|
|
211
|
+
Then, in your application, retrieve this data from the vault, e.g.:
|
|
212
|
+
```python
|
|
213
|
+
from azure.keyvault.secrets import SecretClient
|
|
214
|
+
from azure.identity import DefaultAzureCredential
|
|
215
|
+
|
|
216
|
+
# Azure credentials
|
|
217
|
+
azure_credential = DefaultAzureCredential()
|
|
218
|
+
|
|
219
|
+
# Azure Key Vault
|
|
220
|
+
AZURE_KEY_VAULT = env("AZURE_KEY_VAULT")
|
|
221
|
+
AZURE_KEY_VAULT_URI = f"https://{AZURE_KEY_VAULT}.vault.azure.net"
|
|
222
|
+
azure_key_vault_client = SecretClient(vault_url=AZURE_KEY_VAULT_URI, credential=azure_credential)
|
|
223
|
+
|
|
224
|
+
# Social Auth settings
|
|
225
|
+
oauth_secret = azure_key_vault_client.get_secret(env("AZURE_OAUTH_SECRET_NAME"))
|
|
226
|
+
oauth_secret = json.loads(oauth_secret.value)
|
|
227
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = oauth_secret["client_id"]
|
|
228
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = oauth_secret["secret"]
|
|
229
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = oauth_secret["tenant_id"]
|
|
230
|
+
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ["username", "first_name", "last_name", "email"]
|
|
231
|
+
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
|
|
232
|
+
|
|
233
|
+
AUTHENTICATION_BACKENDS = (
|
|
234
|
+
"social_core.backends.azuread_tenant.AzureADTenantOAuth2",
|
|
235
|
+
"django.contrib.auth.backends.ModelBackend",
|
|
236
|
+
)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
And of course add the login button somewhere, following Django Social Auth instructions.
|
|
240
|
+
|
|
179
241
|
## Automate deployments
|
|
180
242
|
When using a service like GitLab, you can configure a Webhook to fire upon a push to your branch.
|
|
181
243
|
|
|
@@ -8,8 +8,21 @@ To have a proper and secure environment, we need these components:
|
|
|
8
8
|
* PostgreSQL server
|
|
9
9
|
* Azure Communication Services to send e-mails
|
|
10
10
|
* Webapp with multiple custom host names and managed SSL for the website itself
|
|
11
|
+
* Azure Key Vault per application
|
|
11
12
|
* Webapp running pgAdmin
|
|
12
13
|
|
|
14
|
+
## Project requirements
|
|
15
|
+
Your Django project should contain a folder `cicd` with these files:
|
|
16
|
+
* pre_build.sh: commands to be executed before building the application, for example NPM install, CSS build commands,...
|
|
17
|
+
* post_build.sh: commands to be executed after building the application, e.g. cleaning up.
|
|
18
|
+
Note that this runs in the identity of the build container, so you should not run database or storage manipulations here.
|
|
19
|
+
* startup.sh: commands to run the actual application. I recommend to put at least:
|
|
20
|
+
```bash
|
|
21
|
+
python manage.py migrate
|
|
22
|
+
python manage.py collectstatic --noinput
|
|
23
|
+
gunicorn --timeout 600 --workers $((($NUM_CORES*2)+1)) --chdir $APP_PATH yourapplication.wsgi --access-logfile '-' --error-logfile '-'
|
|
24
|
+
```
|
|
25
|
+
Be sure to change `yourapplication` in the above.
|
|
13
26
|
## Installation
|
|
14
27
|
This package is published on PyPi, so you can just add pulumi-django-azure to your requirements file.
|
|
15
28
|
|
|
@@ -137,6 +150,55 @@ pgAdmin will be created with a default login:
|
|
|
137
150
|
|
|
138
151
|
Best practice is to log in right away, create a user for yourself and delete this default user.
|
|
139
152
|
|
|
153
|
+
## Azure OAuth2 / Django Social Auth
|
|
154
|
+
If you want to set up login with Azure, which would make sense since you are in the ecosystem, you need to create an App Registration in Entra ID, create a secret and then register these settings in your stack:
|
|
155
|
+
```
|
|
156
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.key' secret_ID
|
|
157
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.secret' secret_value
|
|
158
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.tenant_id' directory_tenant_id
|
|
159
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.client_id' application_id
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Then in your Django deployment, pass to the `add_django_website` command:
|
|
163
|
+
```
|
|
164
|
+
secrets={
|
|
165
|
+
"mywebsite_social_auth_azure": "AZURE_OAUTH",
|
|
166
|
+
},
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The value will be automatically stored in the vault where the application has access to.
|
|
170
|
+
The environment variable will be suffixed with `_SECRET_NAME`.
|
|
171
|
+
|
|
172
|
+
Then, in your application, retrieve this data from the vault, e.g.:
|
|
173
|
+
```python
|
|
174
|
+
from azure.keyvault.secrets import SecretClient
|
|
175
|
+
from azure.identity import DefaultAzureCredential
|
|
176
|
+
|
|
177
|
+
# Azure credentials
|
|
178
|
+
azure_credential = DefaultAzureCredential()
|
|
179
|
+
|
|
180
|
+
# Azure Key Vault
|
|
181
|
+
AZURE_KEY_VAULT = env("AZURE_KEY_VAULT")
|
|
182
|
+
AZURE_KEY_VAULT_URI = f"https://{AZURE_KEY_VAULT}.vault.azure.net"
|
|
183
|
+
azure_key_vault_client = SecretClient(vault_url=AZURE_KEY_VAULT_URI, credential=azure_credential)
|
|
184
|
+
|
|
185
|
+
# Social Auth settings
|
|
186
|
+
oauth_secret = azure_key_vault_client.get_secret(env("AZURE_OAUTH_SECRET_NAME"))
|
|
187
|
+
oauth_secret = json.loads(oauth_secret.value)
|
|
188
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = oauth_secret["client_id"]
|
|
189
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = oauth_secret["secret"]
|
|
190
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = oauth_secret["tenant_id"]
|
|
191
|
+
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ["username", "first_name", "last_name", "email"]
|
|
192
|
+
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
|
|
193
|
+
|
|
194
|
+
AUTHENTICATION_BACKENDS = (
|
|
195
|
+
"social_core.backends.azuread_tenant.AzureADTenantOAuth2",
|
|
196
|
+
"django.contrib.auth.backends.ModelBackend",
|
|
197
|
+
)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
And of course add the login button somewhere, following Django Social Auth instructions.
|
|
201
|
+
|
|
140
202
|
## Automate deployments
|
|
141
203
|
When using a service like GitLab, you can configure a Webhook to fire upon a push to your branch.
|
|
142
204
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pulumi-django-azure"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.10"
|
|
8
8
|
description = "Simply deployment of Django on Azure with Pulumi"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Maarten Ureel", email = "maarten@youreal.eu" }]
|
|
@@ -27,7 +27,7 @@ Homepage = "https://gitlab.com/MaartenUreel/pulumi-django-azure"
|
|
|
27
27
|
|
|
28
28
|
[tool.poetry]
|
|
29
29
|
name = "pulumi-django-azure"
|
|
30
|
-
version = "1.0.
|
|
30
|
+
version = "1.0.10"
|
|
31
31
|
description = "Simply deployment of Django on Azure with Pulumi"
|
|
32
32
|
authors = ["Maarten Ureel <maarten@youreal.eu>"]
|
|
33
33
|
|
|
@@ -35,13 +35,13 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
35
35
|
:param app_service_sku: The SKU for the app service plan.
|
|
36
36
|
:param storage_account_name: The name of the storage account. Should be unique across Azure.
|
|
37
37
|
:param cdn_host: A custom CDN host name (optional)
|
|
38
|
-
:param comms_data_location: The data location for the Communication Services (optional if you don't need it)
|
|
39
38
|
:param opts: The resource options
|
|
40
39
|
"""
|
|
41
40
|
|
|
42
41
|
super().__init__("pkg:index:DjangoDeployment", name, None, opts)
|
|
43
42
|
|
|
44
43
|
# child_opts = pulumi.ResourceOptions(parent=self)
|
|
44
|
+
self._config = pulumi.Config()
|
|
45
45
|
|
|
46
46
|
self._name = name
|
|
47
47
|
self._tenant_id = tenant_id
|
|
@@ -391,6 +391,59 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
391
391
|
|
|
392
392
|
return comm_service
|
|
393
393
|
|
|
394
|
+
def _add_webapp_vault(self, administrators: list[str], suffix: str) -> azure.keyvault.Vault:
|
|
395
|
+
# Create a keyvault
|
|
396
|
+
vault = azure.keyvault.Vault(
|
|
397
|
+
f"vault-{suffix}",
|
|
398
|
+
resource_group_name=self._rg,
|
|
399
|
+
vault_name=f"vault-{suffix}",
|
|
400
|
+
properties=azure.keyvault.VaultPropertiesArgs(
|
|
401
|
+
tenant_id=self._tenant_id,
|
|
402
|
+
sku=azure.keyvault.SkuArgs(
|
|
403
|
+
name=azure.keyvault.SkuName.STANDARD,
|
|
404
|
+
family=azure.keyvault.SkuFamily.A,
|
|
405
|
+
),
|
|
406
|
+
enable_rbac_authorization=True,
|
|
407
|
+
),
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Find the Key Vault Administrator role
|
|
411
|
+
administrator_role = vault.id.apply(
|
|
412
|
+
lambda scope: azure.authorization.get_role_definition(
|
|
413
|
+
role_definition_id="00482a5a-887f-4fb3-b363-3b7fe8e74483",
|
|
414
|
+
scope=scope,
|
|
415
|
+
)
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
# Add vault administrators
|
|
419
|
+
for a in administrators:
|
|
420
|
+
azure.authorization.RoleAssignment(
|
|
421
|
+
f"ra-{suffix}-vault-admin-{a}",
|
|
422
|
+
principal_id=a,
|
|
423
|
+
principal_type=azure.authorization.PrincipalType.USER,
|
|
424
|
+
role_definition_id=administrator_role.id,
|
|
425
|
+
scope=vault.id,
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
return vault
|
|
429
|
+
|
|
430
|
+
def _add_webapp_secret(self, vault: azure.keyvault.Vault, secret_name: str, config_secret_name: str, suffix: str):
|
|
431
|
+
secret = self._config.require_secret(config_secret_name)
|
|
432
|
+
|
|
433
|
+
# Normalize the secret name
|
|
434
|
+
secret_name = secret_name.replace("_", "-").lower()
|
|
435
|
+
|
|
436
|
+
# Create a secret in the vault
|
|
437
|
+
return azure.keyvault.Secret(
|
|
438
|
+
f"secret-{suffix}-{secret_name}",
|
|
439
|
+
resource_group_name=self._rg,
|
|
440
|
+
vault_name=vault.name,
|
|
441
|
+
secret_name=secret_name,
|
|
442
|
+
properties=azure.keyvault.SecretPropertiesArgs(
|
|
443
|
+
value=secret,
|
|
444
|
+
),
|
|
445
|
+
)
|
|
446
|
+
|
|
394
447
|
def _get_storage_account_access_keys(
|
|
395
448
|
self, storage_account: azure.storage.StorageAccount
|
|
396
449
|
) -> Sequence[azure.storage.outputs.StorageAccountKeyResponse]:
|
|
@@ -437,8 +490,10 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
437
490
|
website_hosts: list[str],
|
|
438
491
|
django_settings_module: str,
|
|
439
492
|
environment_variables: dict[str, str] = {},
|
|
493
|
+
secrets: dict[str, str] = {},
|
|
440
494
|
comms_data_location: Optional[str] = None,
|
|
441
495
|
comms_domains: Optional[list[str]] = [],
|
|
496
|
+
vault_administrators: Optional[list[str]] = [],
|
|
442
497
|
) -> azure.web.WebApp:
|
|
443
498
|
"""
|
|
444
499
|
Create a Django website with it's own database and storage containers.
|
|
@@ -450,8 +505,12 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
450
505
|
:param website_hosts: The list of custom host names for the website.
|
|
451
506
|
:param django_settings_module: The Django settings module to load.
|
|
452
507
|
:param environment_variables: A dictionary of environment variables to set.
|
|
508
|
+
:param secrets: A dictionary of secrets to store in the Key Vault and assign as environment variables.
|
|
509
|
+
The key is the name of the Pulumi secret, the value is the name of the environment variable
|
|
510
|
+
and the name of the secret in the Key Vault.
|
|
453
511
|
:param comms_data_location: The data location for the Communication Services (optional if you don't need it).
|
|
454
512
|
:param comms_domains: The list of custom domains for the E-mail Communication Services (optional).
|
|
513
|
+
:param vault_administrator: The principal ID of the vault administrator (optional).
|
|
455
514
|
"""
|
|
456
515
|
|
|
457
516
|
# Create a database
|
|
@@ -483,11 +542,19 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
483
542
|
# Communication Services (optional)
|
|
484
543
|
if comms_data_location:
|
|
485
544
|
comms = self._add_webapp_comms(comms_data_location, comms_domains, f"{name}-{self._name}")
|
|
486
|
-
# Add the
|
|
545
|
+
# Add the service endpoint as environment variable
|
|
487
546
|
environment_variables["AZURE_COMMUNICATION_SERVICE_ENDPOINT"] = comms.host_name.apply(lambda host: f"https://{host}")
|
|
488
547
|
else:
|
|
489
548
|
comms = None
|
|
490
549
|
|
|
550
|
+
# Key Vault
|
|
551
|
+
vault = self._add_webapp_vault(vault_administrators, f"{name}-{self._name}")
|
|
552
|
+
|
|
553
|
+
# Add secrets
|
|
554
|
+
for config_name, env_name in secrets.items():
|
|
555
|
+
s = self._add_webapp_secret(vault, env_name, config_name, f"{name}-{self._name}")
|
|
556
|
+
environment_variables[f"{env_name}_SECRET_NAME"] = s.name
|
|
557
|
+
|
|
491
558
|
# Create a Django Secret Key (random)
|
|
492
559
|
secret_key = pulumi_random.RandomString(f"django-secret-{name}-{self._name}", length=50)
|
|
493
560
|
|
|
@@ -510,6 +577,7 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
510
577
|
),
|
|
511
578
|
https_only=True,
|
|
512
579
|
site_config=azure.web.SiteConfigArgs(
|
|
580
|
+
app_command_line="cicd/startup.sh",
|
|
513
581
|
always_on=True,
|
|
514
582
|
health_check_path=self.HEALTH_CHECK_PATH,
|
|
515
583
|
ftps_state=azure.web.FtpsState.DISABLED,
|
|
@@ -528,6 +596,8 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
528
596
|
azure.web.NameValuePairArgs(name="DJANGO_SETTINGS_MODULE", value=django_settings_module),
|
|
529
597
|
azure.web.NameValuePairArgs(name="DJANGO_SECRET_KEY", value=secret_key.result),
|
|
530
598
|
azure.web.NameValuePairArgs(name="DJANGO_ALLOWED_HOSTS", value=",".join(website_hosts)),
|
|
599
|
+
# Vault settings
|
|
600
|
+
azure.web.NameValuePairArgs(name="AZURE_KEY_VAULT", value=vault.name),
|
|
531
601
|
# Storage settings
|
|
532
602
|
azure.web.NameValuePairArgs(name="AZURE_STORAGE_ACCOUNT_NAME", value=self._storage_account.name),
|
|
533
603
|
azure.web.NameValuePairArgs(name="AZURE_STORAGE_CONTAINER_STATICFILES", value=static_container.name),
|
|
@@ -572,6 +642,24 @@ class DjangoDeployment(pulumi.ComponentResource):
|
|
|
572
642
|
f"{name}_deploy_ssh_key_url", app.name.apply(lambda name: f"https://{name}.scm.azurewebsites.net/api/sshkey?ensurePublicKey=1")
|
|
573
643
|
)
|
|
574
644
|
|
|
645
|
+
# Find the role for Key Vault Secrets User
|
|
646
|
+
vault_access_role = vault.id.apply(
|
|
647
|
+
lambda scope: azure.authorization.get_role_definition(
|
|
648
|
+
role_definition_id="4633458b-17de-408a-b874-0445c86b69e6",
|
|
649
|
+
scope=scope,
|
|
650
|
+
)
|
|
651
|
+
)
|
|
652
|
+
|
|
653
|
+
# Grant the app access to the vault
|
|
654
|
+
azure.authorization.RoleAssignment(
|
|
655
|
+
f"ra-{name}-vault-user",
|
|
656
|
+
principal_id=principal_id,
|
|
657
|
+
principal_type=azure.authorization.PrincipalType.SERVICE_PRINCIPAL,
|
|
658
|
+
# Key Vault Secrets User
|
|
659
|
+
role_definition_id=vault_access_role.id,
|
|
660
|
+
scope=vault.id,
|
|
661
|
+
)
|
|
662
|
+
|
|
575
663
|
# Find the role for Storage Blob Data Contributor
|
|
576
664
|
storage_role = self._storage_account.id.apply(
|
|
577
665
|
lambda scope: azure.authorization.get_role_definition(
|
{pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10/src/pulumi_django_azure.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pulumi-django-azure
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.10
|
|
4
4
|
Summary: Simply deployment of Django on Azure with Pulumi
|
|
5
5
|
Author-email: Maarten Ureel <maarten@youreal.eu>
|
|
6
6
|
License: MIT License
|
|
@@ -47,8 +47,21 @@ To have a proper and secure environment, we need these components:
|
|
|
47
47
|
* PostgreSQL server
|
|
48
48
|
* Azure Communication Services to send e-mails
|
|
49
49
|
* Webapp with multiple custom host names and managed SSL for the website itself
|
|
50
|
+
* Azure Key Vault per application
|
|
50
51
|
* Webapp running pgAdmin
|
|
51
52
|
|
|
53
|
+
## Project requirements
|
|
54
|
+
Your Django project should contain a folder `cicd` with these files:
|
|
55
|
+
* pre_build.sh: commands to be executed before building the application, for example NPM install, CSS build commands,...
|
|
56
|
+
* post_build.sh: commands to be executed after building the application, e.g. cleaning up.
|
|
57
|
+
Note that this runs in the identity of the build container, so you should not run database or storage manipulations here.
|
|
58
|
+
* startup.sh: commands to run the actual application. I recommend to put at least:
|
|
59
|
+
```bash
|
|
60
|
+
python manage.py migrate
|
|
61
|
+
python manage.py collectstatic --noinput
|
|
62
|
+
gunicorn --timeout 600 --workers $((($NUM_CORES*2)+1)) --chdir $APP_PATH yourapplication.wsgi --access-logfile '-' --error-logfile '-'
|
|
63
|
+
```
|
|
64
|
+
Be sure to change `yourapplication` in the above.
|
|
52
65
|
## Installation
|
|
53
66
|
This package is published on PyPi, so you can just add pulumi-django-azure to your requirements file.
|
|
54
67
|
|
|
@@ -176,6 +189,55 @@ pgAdmin will be created with a default login:
|
|
|
176
189
|
|
|
177
190
|
Best practice is to log in right away, create a user for yourself and delete this default user.
|
|
178
191
|
|
|
192
|
+
## Azure OAuth2 / Django Social Auth
|
|
193
|
+
If you want to set up login with Azure, which would make sense since you are in the ecosystem, you need to create an App Registration in Entra ID, create a secret and then register these settings in your stack:
|
|
194
|
+
```
|
|
195
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.key' secret_ID
|
|
196
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.secret' secret_value
|
|
197
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.tenant_id' directory_tenant_id
|
|
198
|
+
pulumi config set --secret --path 'mywebsite_social_auth_azure.client_id' application_id
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Then in your Django deployment, pass to the `add_django_website` command:
|
|
202
|
+
```
|
|
203
|
+
secrets={
|
|
204
|
+
"mywebsite_social_auth_azure": "AZURE_OAUTH",
|
|
205
|
+
},
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The value will be automatically stored in the vault where the application has access to.
|
|
209
|
+
The environment variable will be suffixed with `_SECRET_NAME`.
|
|
210
|
+
|
|
211
|
+
Then, in your application, retrieve this data from the vault, e.g.:
|
|
212
|
+
```python
|
|
213
|
+
from azure.keyvault.secrets import SecretClient
|
|
214
|
+
from azure.identity import DefaultAzureCredential
|
|
215
|
+
|
|
216
|
+
# Azure credentials
|
|
217
|
+
azure_credential = DefaultAzureCredential()
|
|
218
|
+
|
|
219
|
+
# Azure Key Vault
|
|
220
|
+
AZURE_KEY_VAULT = env("AZURE_KEY_VAULT")
|
|
221
|
+
AZURE_KEY_VAULT_URI = f"https://{AZURE_KEY_VAULT}.vault.azure.net"
|
|
222
|
+
azure_key_vault_client = SecretClient(vault_url=AZURE_KEY_VAULT_URI, credential=azure_credential)
|
|
223
|
+
|
|
224
|
+
# Social Auth settings
|
|
225
|
+
oauth_secret = azure_key_vault_client.get_secret(env("AZURE_OAUTH_SECRET_NAME"))
|
|
226
|
+
oauth_secret = json.loads(oauth_secret.value)
|
|
227
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_KEY = oauth_secret["client_id"]
|
|
228
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_SECRET = oauth_secret["secret"]
|
|
229
|
+
SOCIAL_AUTH_AZUREAD_TENANT_OAUTH2_TENANT_ID = oauth_secret["tenant_id"]
|
|
230
|
+
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ["username", "first_name", "last_name", "email"]
|
|
231
|
+
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
|
|
232
|
+
|
|
233
|
+
AUTHENTICATION_BACKENDS = (
|
|
234
|
+
"social_core.backends.azuread_tenant.AzureADTenantOAuth2",
|
|
235
|
+
"django.contrib.auth.backends.ModelBackend",
|
|
236
|
+
)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
And of course add the login button somewhere, following Django Social Auth instructions.
|
|
240
|
+
|
|
179
241
|
## Automate deployments
|
|
180
242
|
When using a service like GitLab, you can configure a Webhook to fire upon a push to your branch.
|
|
181
243
|
|
|
File without changes
|
|
File without changes
|
{pulumi-django-azure-1.0.8 → pulumi_django_azure-1.0.10}/src/pulumi_django_azure/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|