Skip to content

Commit

Permalink
feat(secrets): helper function gets secret by name
Browse files Browse the repository at this point in the history
  • Loading branch information
thekaveman committed Jan 30, 2024
1 parent 29a0d41 commit 6ec2455
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 12 deletions.
30 changes: 18 additions & 12 deletions benefits/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,30 @@
KEY_VAULT_URL = "https://kv-cdt-pub-calitp-{env}-001.vault.azure.net/"


def get_secret_by_name(secret_name, client=None):
if client is None:
# construct the KeyVault URL from the runtime environment
# see https://docs.calitp.org/benefits/deployment/infrastructure/#environments
# and https://github.com/cal-itp/benefits/blob/dev/terraform/key_vault.tf
runtime_env = settings.RUNTIME_ENVIRONMENT()
vault_url = KEY_VAULT_URL.format(env=runtime_env[0])

credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)

secret = client.get_secret(secret_name)
return secret.value


if __name__ == "__main__":
args = sys.argv[1:]
if len(args) < 1:
print("Provide the name of the secret to read")
exit(1)

# construct the KeyVault URL from the runtime environment
# see https://docs.calitp.org/benefits/deployment/infrastructure/#environments
# and https://github.com/cal-itp/benefits/blob/dev/terraform/key_vault.tf
runtime_env = settings.RUNTIME_ENVIRONMENT()
vault_url = KEY_VAULT_URL.format(env=runtime_env[0])

secret_name = args[0]
secret_value = get_secret_by_name(secret_name)

credential = DefaultAzureCredential()
client = SecretClient(vault_url=vault_url, credential=credential)
secret = client.get_secret(secret_name)

print(f"Reading {secret_name} from {vault_url}")
print(f"Value: {secret.value}")
print(f"Reading {secret_name} from {settings.RUNTIME_ENVIRONMENT()}")

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (secret)
as clear text.
print(f"Value: {secret_value}")

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This expression logs
sensitive data (secret)
as clear text.
exit(0)
45 changes: 45 additions & 0 deletions tests/pytest/test_secrets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import pytest

from benefits.secrets import KEY_VAULT_URL, get_secret_by_name


@pytest.fixture(autouse=True)
def mock_DefaultAzureCredential(mocker):
# patching the class to ensure new instances always return the same mock
credential_cls = mocker.patch("benefits.secrets.DefaultAzureCredential")
credential_cls.return_value = mocker.Mock()
return credential_cls


def test_get_secret_by_name__mock_client__returns_value(mocker):
secret_name = "the secret name"
secret_value = "the secret value"
client = mocker.patch("benefits.secrets.SecretClient")
client.get_secret.return_value = mocker.Mock(value=secret_value)

actual_value = get_secret_by_name(secret_name, client)

client.get_secret.assert_called_once_with(secret_name)
assert actual_value == secret_value


def test_get_secret_by_name__None_client__returns_value(mocker, settings, mock_DefaultAzureCredential):
secret_name = "the secret name"
secret_value = "the secret value"

# override runtime to dev
settings.RUNTIME_ENVIRONMENT = lambda: "dev"
expected_keyvault_url = KEY_VAULT_URL.format(env="d")

# set up the mock client class and expected return values
# this test does not pass in a known client, instead checking that a client is constructed as expected
mock_credential = mock_DefaultAzureCredential.return_value
client_cls = mocker.patch("benefits.secrets.SecretClient")
client = client_cls.return_value
client.get_secret.return_value = mocker.Mock(value=secret_value)

actual_value = get_secret_by_name(secret_name)

client_cls.assert_called_once_with(vault_url=expected_keyvault_url, credential=mock_credential)
client.get_secret.assert_called_once_with(secret_name)
assert actual_value == secret_value

0 comments on commit 6ec2455

Please sign in to comment.