Skip to content

Commit

Permalink
Merge branch 'develop' into template-checklist
Browse files Browse the repository at this point in the history
  • Loading branch information
craddm committed Dec 3, 2024
2 parents af232b7 + 56a53e2 commit 7ce9aaa
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 10 deletions.
30 changes: 22 additions & 8 deletions data_safe_haven/commands/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import typer

from data_safe_haven import console
from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import ContextManager, DSHPulumiConfig, SHMConfig, SREConfig
from data_safe_haven.exceptions import DataSafeHavenError
Expand Down Expand Up @@ -120,9 +121,9 @@ def register(
# Load SHMConfig
try:
shm_config = SHMConfig.from_remote(context)
except DataSafeHavenError:
except DataSafeHavenError as exc:
logger.error("Have you deployed the SHM?")
raise
raise typer.Exit(1) from exc

# Load Pulumi config
pulumi_config = DSHPulumiConfig.from_remote(context)
Expand All @@ -132,7 +133,7 @@ def register(
if sre_config.name not in pulumi_config.project_names:
msg = f"Could not load Pulumi settings for '{sre_config.name}'. Have you deployed the SRE?"
logger.error(msg)
raise DataSafeHavenError(msg)
raise typer.Exit(1)

# Load GraphAPI
graph_api = GraphApi.from_scopes(
Expand All @@ -146,16 +147,29 @@ def register(

# List users
users = UserHandler(context, graph_api)
available_usernames = users.get_usernames_entra_id()
available_users = users.entra_users.list()
user_dict = {
user.preferred_username.split("@")[0]: user.preferred_username.split("@")[1]
for user in available_users
}
usernames_to_register = []
for username in usernames:
if username in available_usernames:
usernames_to_register.append(username)
if user_domain := user_dict.get(username):
if shm_config.shm.fqdn not in user_domain:
console.print(
f"User [green]'{username}[/green]'s principal domain name is [blue]'{user_domain}'[/blue].\n"
f"SRE [yellow]'{sre}'[/yellow] belongs to SHM domain [blue]'{shm_config.shm.fqdn}'[/blue]."
)
logger.error(
"The user's principal domain name must match the domain of the SRE to be registered."
)
else:
usernames_to_register.append(username)
else:
logger.error(
f"Username '{username}' does not belong to this Data Safe Haven deployment."
" Please use 'dsh users add' to create it."
)
console.print("Please use 'dsh users add' to create this user.")
users.register(sre_config.name, usernames_to_register)
except DataSafeHavenError as exc:
logger.critical(f"Could not register Data Safe Haven users with SRE '{sre}'.")
Expand Down Expand Up @@ -259,8 +273,8 @@ def unregister(
else:
logger.error(
f"Username '{username}' does not belong to this Data Safe Haven deployment."
" Please use 'dsh users add' to create it."
)
console.print("Please use 'dsh users add' to create it.")
for group_name in (
f"{sre_config.name} Users",
f"{sre_config.name} Privileged Users",
Expand Down
4 changes: 2 additions & 2 deletions docs/source/overview/sensitivity_tiers.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Non-technical restrictions related to information governance procedures may also
- connections to the in-browser remote desktop can only be made from an agreed set of IP addresses
- outbound connections to the internet from inside the environment are not possible
- copy-and-paste between the environment and the user's device is not possible
- access to all packages on PyPI and CRAN is made available through a proxy or mirror server
- access to all packages on PyPI and CRAN is made available through a proxy server

Non-technical restrictions related to information governance procedures may also be applied according to your organisation's needs.

Expand All @@ -63,7 +63,7 @@ At the Turing connections to Tier 2 environments are only permitted from **Organ

**Tier 3** environments impose the following technical controls on top of what is required at {ref}`policy_tier_2`.

- a partial replica of agreed PyPI and CRAN packages is made available through a proxy or mirror server
- an agreed subset of PyPI and CRAN packages is made available through a proxy server

Non-technical restrictions related to information governance procedures may also be applied according to your organisation's needs.

Expand Down
13 changes: 13 additions & 0 deletions tests/commands/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from pytest import fixture
from typer.testing import CliRunner

from data_safe_haven.administration.users.entra_users import EntraUsers
from data_safe_haven.administration.users.research_user import ResearchUser
from data_safe_haven.config import (
Context,
ContextManager,
Expand Down Expand Up @@ -260,3 +262,14 @@ def tmp_contexts_none(tmp_path, context_yaml):
with open(config_file_path, "w") as f:
f.write(context_yaml)
return tmp_path


@fixture
def mock_entra_user_list(mocker):
test_user = ResearchUser(
given_name="Harry",
surname="Lime",
sam_account_name="harry.lime",
user_principal_name="[email protected]",
)
mocker.patch.object(EntraUsers, "list", return_value=[test_user])
20 changes: 20 additions & 0 deletions tests/commands/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ def test_invalid_shm(
assert result.exit_code == 1
assert "Have you deployed the SHM?" in result.stdout

def test_mismatched_domain(
self,
mock_graphapi_get_credential, # noqa: ARG002
mock_pulumi_config_no_key_from_remote, # noqa: ARG002
mock_shm_config_from_remote, # noqa: ARG002
mock_sre_config_from_remote, # noqa: ARG002
mock_entra_user_list, # noqa: ARG002
runner,
tmp_contexts, # noqa: ARG002
):
result = runner.invoke(
users_command_group, ["register", "-u", "harry.lime", "sandbox"]
)

assert result.exit_code == 0
assert (
"principal domain name must match the domain of the SRE to be registered"
in result.stdout
)

def test_invalid_sre(
self,
mock_pulumi_config_from_remote, # noqa: ARG002
Expand Down

0 comments on commit 7ce9aaa

Please sign in to comment.