Skip to content

Commit

Permalink
Merge pull request #2258 from alan-turing-institute/merge_release
Browse files Browse the repository at this point in the history
Merge release v5.0.1 into develop
  • Loading branch information
JimMadge authored Oct 24, 2024
2 parents 9534194 + 22901cd commit 67d5ace
Show file tree
Hide file tree
Showing 24 changed files with 215 additions and 66 deletions.
6 changes: 4 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ updates:
# Python package update PRs
- package-ecosystem: pip # This will update 'pyproject.toml'
directory: "/"
schedule:
interval: weekly
ignore:
- dependency-name: "psycopg" # 3.1.19 is the latest version to support on older MacOS versions
groups:
production-dependencies:
dependency-type: "production"
development-dependencies:
dependency-type: "development"
schedule:
interval: weekly
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ expanded.yaml

# ruff cache
.ruff_cache

**/venv
8 changes: 4 additions & 4 deletions .hatch/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# This file is autogenerated by hatch-pip-compile with Python 3.12
#
# [constraints] .hatch/requirements.txt (SHA256: 02ec09f022011bea4adeff6755ed03b7c3c1c847be7bcff73b746968aa5579a0)
# [constraints] .hatch/requirements.txt (SHA256: e9ada52b8f6ba0b8f072b9c1a47b577eeb19f863ee4e75afc8a24ad948bf35eb)
#
# - appdirs==1.4.4
# - azure-core==1.31.0
Expand All @@ -23,7 +23,7 @@
# - chevron==0.14.0
# - cryptography==43.0.3
# - fqdn==1.5.1
# - psycopg[binary]==3.2.3
# - psycopg[binary]==3.1.19
# - pulumi-azure-native==2.68.0
# - pulumi-azuread==6.0.1
# - pulumi-random==4.16.7
Expand Down Expand Up @@ -287,11 +287,11 @@ protobuf==4.25.5
# via
# -c .hatch/requirements.txt
# pulumi
psycopg==3.2.3
psycopg==3.1.19
# via
# -c .hatch/requirements.txt
# hatch.envs.test
psycopg-binary==3.2.3
psycopg-binary==3.1.19
# via
# -c .hatch/requirements.txt
# psycopg
Expand Down
6 changes: 3 additions & 3 deletions .hatch/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
# - chevron==0.14.0
# - cryptography==43.0.3
# - fqdn==1.5.1
# - psycopg[binary]==3.2.3
# - psycopg[binary]==3.1.19
# - pulumi-azure-native==2.68.0
# - pulumi-azuread==6.0.1
# - pulumi-random==4.16.7
Expand Down Expand Up @@ -188,9 +188,9 @@ portalocker==2.10.1
# via msal-extensions
protobuf==4.25.5
# via pulumi
psycopg==3.2.3
psycopg==3.1.19
# via hatch.envs.default
psycopg-binary==3.2.3
psycopg-binary==3.1.19
# via psycopg
pulumi==3.137.0
# via
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ All organisations using an earlier version in production should update to the la

| Version | Supported |
| --------------------------------------------------------------------------------------- | ------------------ |
| [5.0.0](https://github.com/alan-turing-institute/data-safe-haven/releases/tag/v5.0.0) | :white_check_mark: |
| < 5.0.0 | :x: |
| [5.0.1](https://github.com/alan-turing-institute/data-safe-haven/releases/tag/v5.0.1) | :white_check_mark: |
| < 5.0.1 | :x: |

## Reporting a Vulnerability

Expand Down
4 changes: 2 additions & 2 deletions data_safe_haven/commands/shm.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def deploy(
),
] = None,
) -> None:
"""Deploy a Safe Haven Management environment."""
"""Deploy a Safe Haven Management environment using the current context."""
logger = get_logger()

# Load selected context
Expand Down Expand Up @@ -126,7 +126,7 @@ def deploy(

@shm_command_group.command()
def teardown() -> None:
"""Tear down a deployed a Safe Haven Management environment."""
"""Tear down a deployed Safe Haven Management environment."""
logger = get_logger()
try:
context = ContextManager.from_file().assert_context()
Expand Down
10 changes: 8 additions & 2 deletions data_safe_haven/commands/sre.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def deploy(
)
logger.info(
f"SRE will be deployed to subscription '[green]{sre_subscription_name}[/]'"
f" ('[bold]{sre_config.azure.subscription_id}[/]')"
f" ({sre_config.azure.subscription_id})"
)
# Set Entra options
application = graph_api.get_application_by_name(context.entra_application_name)
Expand Down Expand Up @@ -136,7 +136,13 @@ def deploy(
replace=True,
)
logger.info(f"SRE will be registered in SHM '[green]{shm_config.shm.fqdn}[/]'")
logger.info(f"SHM subscription '[green]{shm_config.azure.subscription_id}[/]'")
shm_subscription_name = azure_sdk.get_subscription_name(
shm_config.azure.subscription_id
)
logger.info(
f"SHM is deployed to subscription '[green]{shm_subscription_name}[/]'"
f" ({shm_config.azure.subscription_id})"
)

# Deploy Azure infrastructure with Pulumi
try:
Expand Down
2 changes: 1 addition & 1 deletion data_safe_haven/config/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Context(ContextBase, BaseModel, validate_assignment=True):

@property
def entra_application_name(self) -> str:
return f"Data Safe Haven ({self.description}) Pulumi Service Principal"
return f"Data Safe Haven ({self.name}) Pulumi Service Principal"

@property
def entra_application_secret(self) -> str:
Expand Down
28 changes: 20 additions & 8 deletions data_safe_haven/external/api/graph_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ def verify_custom_domain(
# Check whether all expected nameservers are active
with suppress(resolver.NXDOMAIN):
self.logger.debug(
f"Checking [green]{domain_name}[/] domain registration status ..."
f"Checking [green]{domain_name}[/] DNS delegation."
)
active_nameservers = [
str(ns) for ns in iter(resolver.resolve(domain_name, "NS"))
Expand All @@ -1045,23 +1045,35 @@ def verify_custom_domain(
for nameserver in expected_nameservers
):
self.logger.info(
f"Verified that [green]{domain_name}[/] is registered as a custom Entra ID domain."
f"[green]{domain_name}[/] DNS has been delegated correctly."
)
break
self.logger.warning(
f"Domain [green]{domain_name}[/] is not currently registered as a custom Entra ID domain."
f"[green]{domain_name}[/] DNS is not delegated correctly."
)
# Prompt user to set domain delegation manually
docs_link = "https://learn.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns#delegate-the-domain"
self.logger.info(
f"To proceed you will need to delegate [green]{domain_name}[/] to Azure ({docs_link})"
f"To proceed you will need to delegate [green]{domain_name}[/] to specific Azure nameservers"
)
ns_list = ", ".join([f"[green]{n}[/]" for n in expected_nameservers])
domain_parent = ".".join(domain_name.split(".")[1:])
self.logger.info(
f"You will need to create NS records pointing to: {ns_list}"
f"Create {len(expected_nameservers)} [green]NS[/] records for [green]{domain_name}[/] (for example in the zone of {domain_parent})"
)
console.tabulate(
header=["domain", "record type", "value"],
rows=[
[domain_name, "NS", nameserver]
for nameserver in expected_nameservers
],
)
docs_link = (
"https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/"
)
self.logger.info(
f"You can learn more about NS records here: {docs_link}"
)
if not console.confirm(
f"Are you ready to check whether [green]{domain_name}[/] has been delegated to Azure?",
f"Are you ready to check whether [green]{domain_name}[/] has been delegated to the correct Azure nameservers?",
default_to_yes=True,
):
self.logger.error("User terminated check for domain delegation.")
Expand Down
2 changes: 2 additions & 0 deletions data_safe_haven/external/interface/pulumi_account.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Manage Pulumi accounts"""

import sys
from shutil import which
from typing import Any

Expand Down Expand Up @@ -39,5 +40,6 @@ def env(self) -> dict[str, Any]:
"AZURE_STORAGE_ACCOUNT": self.storage_account_name,
"AZURE_STORAGE_KEY": str(storage_account_keys[0].value),
"AZURE_KEYVAULT_AUTH_VIA_CLI": "true",
"PULUMI_PYTHON_CMD": sys.executable,
}
return self._env
15 changes: 7 additions & 8 deletions data_safe_haven/infrastructure/programs/imperative_shm.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,14 +154,13 @@ def deploy(self) -> None:
"signInAudience": "AzureADMyOrg",
},
)
# Ensure that the application secret exists
if not self.context.entra_application_secret:
self.context.entra_application_secret = (
graph_api.create_application_secret(
self.context.entra_application_name,
self.context.entra_application_secret_name,
)
)
# Always recreate the application secret.
# Otherwise the one in the key vault will be used which might be out of date
# An SRE deployment will read from the keyvault, and get the latest version
self.context.entra_application_secret = graph_api.create_application_secret(
self.context.entra_application_name,
self.context.entra_application_secret_name,
)
except DataSafeHavenMicrosoftGraphError as exc:
msg = "Failed to create deployment application in Entra ID."
raise DataSafeHavenAzureError(msg) from exc
Expand Down
24 changes: 20 additions & 4 deletions data_safe_haven/infrastructure/project_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,8 @@ def apply_config_options(self) -> None:
else:
self.ensure_config(name, value, secret=is_secret)
self._options = {}
except Exception as exc:
msg = "Applying Pulumi configuration options failed.."
except DataSafeHavenError as exc:
msg = "Applying Pulumi configuration options failed."
raise DataSafeHavenPulumiError(msg) from exc

def cancel(self) -> None:
Expand Down Expand Up @@ -286,10 +286,26 @@ def destroy(self) -> None:
raise DataSafeHavenPulumiError(msg) from exc

def ensure_config(self, name: str, value: str, *, secret: bool) -> None:
"""Ensure that config values have been set, setting them if they do not exist"""
"""
Ensure that config values have been set.
Values will be set if they do not exist.
If the value is already set and does not match the `value` argument,
`DataSafeHavenPulumiError` will be raised.
"""
try:
self.stack.get_config(name)
# Check whether a value is already set for this parameter
existing_value = self.stack.get_config(name).value
# ... if it is, ensure it is consistent with the incoming value
if existing_value != value:
msg = (
f"Unchangeable configuration option '{name}' not consistent, "
f"your configuration: '{value}', Pulumi workspace: '{existing_value}'."
)
raise DataSafeHavenPulumiError(msg)
except automation.CommandError:
# Set value if it does not already exist
self.set_config(name, value, secret=secret)

def evaluate(self, result: str) -> None:
Expand Down
2 changes: 1 addition & 1 deletion data_safe_haven/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "5.0.0"
__version__ = "5.0.1"
__version_info__ = tuple(__version__.split("."))
7 changes: 4 additions & 3 deletions docs/source/deployment/configure_entra_id.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,18 @@ Follow the instructions [here](https://learn.microsoft.com/en-us/entra/fundament
Use the following settings:

- **Basics** tab:
- **User principal name:** entra.admin._FIRST_NAME_._LAST_NAME_
- **User principal name:** entra.admin._first_name_._last_name_
- If you have a choice of domains use _YOUR_ORGANISATION_.onmicrosoft.com, which will create a clearer separation between administrators and users
- **Display name:** Entra Admin - _FIRST_NAME_ _LAST_NAME_
- **Display name:** Entra Admin - _first_name_ _last_name_
- **Other fields:** leave them with their default values
- **Properties** tab:
- **Usage location:** set to the country being used for this deployment
- **Assigments** tab:
- **Assignments** tab:
- Click the **{guilabel}`+ Add role`** button
- Search for **Global Administrator**, and check the box
- Click the **{guilabel}`Select`** button

Click the **{guilabel}`Review + Create`** button
:::

## Register allowed authentication methods
Expand Down
4 changes: 2 additions & 2 deletions docs/source/deployment/deploy_shm.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ However, you may choose to use multiple SHMs if, for example, you want to separa
## Requirements

- A [Microsoft Entra](https://learn.microsoft.com/en-us/entra/fundamentals/) tenant for managing your users
- An account with [Global Administrator](https://learn.microsoft.com/en-us/entra/global-secure-access/reference-role-based-permissions#global-administrator) privileges on this tenant
- An account with [Global Administrator](https://learn.microsoft.com/en-us/entra/global-secure-access/reference-role-based-permissions#global-administrator) privileges on the tenant that you set up in the {ref}`configure_entra_id` step.
- An Azure subscription where you will deploy your infrastructure
- An account with at least [Contributor](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles/general#contributor) permissions on this subscription

Expand All @@ -26,7 +26,7 @@ However, you may choose to use multiple SHMs if, for example, you want to separa
Before deploying the Safe Haven Management (SHM) infrastructure you need to decide on a few parameters:

**entra_tenant_id**
: Tenant ID for the Entra ID used to manage TRE users
: Tenant ID for the Entra tenant you will be using to manage the TRE users

:::{admonition} How to find your Microsoft Entra Tenant ID
:class: dropdown hint
Expand Down
1 change: 1 addition & 0 deletions docs/source/deployment/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Deploying an instance of the Data Safe Haven involves the following steps:

Install the following requirements before starting

- [Python 3.12](https://wiki.python.org/moin/BeginnersGuide/Download)
- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)
- [pipx](https://pipx.pypa.io/stable/installation/)
- [Pulumi](https://www.pulumi.com/docs/get-started/install/)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 67d5ace

Please sign in to comment.