2018-07-16 12:39:59 -07:00
|
|
|
import re
|
2023-11-30 07:55:51 -08:00
|
|
|
import string
|
|
|
|
|
2022-09-28 09:35:12 +00:00
|
|
|
from moto.moto_api._internal import mock_random as random
|
2018-07-16 12:39:59 -07:00
|
|
|
|
|
|
|
|
|
|
|
def random_password(
|
2023-04-22 15:39:48 +00:00
|
|
|
password_length: int,
|
|
|
|
exclude_characters: str,
|
|
|
|
exclude_numbers: bool,
|
|
|
|
exclude_punctuation: bool,
|
|
|
|
exclude_uppercase: bool,
|
|
|
|
exclude_lowercase: bool,
|
|
|
|
include_space: bool,
|
|
|
|
require_each_included_type: bool,
|
|
|
|
) -> str:
|
2018-07-16 12:39:59 -07:00
|
|
|
|
|
|
|
password = ""
|
|
|
|
required_characters = ""
|
|
|
|
|
|
|
|
if not exclude_lowercase and not exclude_uppercase:
|
|
|
|
password += string.ascii_letters
|
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.ascii_lowercase, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.ascii_uppercase, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
elif not exclude_lowercase:
|
|
|
|
password += string.ascii_lowercase
|
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.ascii_lowercase, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
elif not exclude_uppercase:
|
|
|
|
password += string.ascii_uppercase
|
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.ascii_uppercase, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
if not exclude_numbers:
|
|
|
|
password += string.digits
|
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.digits, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
if not exclude_punctuation:
|
|
|
|
password += string.punctuation
|
|
|
|
required_characters += random.choice(
|
|
|
|
_exclude_characters(string.punctuation, exclude_characters)
|
2019-10-31 08:44:26 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
if include_space:
|
|
|
|
password += " "
|
|
|
|
required_characters += " "
|
2020-08-03 19:42:42 +07:00
|
|
|
if exclude_characters:
|
|
|
|
password = _exclude_characters(password, exclude_characters)
|
2018-07-16 12:39:59 -07:00
|
|
|
|
2021-07-26 07:40:39 +01:00
|
|
|
password = "".join(str(random.choice(password)) for x in range(password_length))
|
2018-07-16 12:39:59 -07:00
|
|
|
|
|
|
|
if require_each_included_type:
|
|
|
|
password = _add_password_require_each_included_type(
|
|
|
|
password, required_characters
|
|
|
|
)
|
|
|
|
|
|
|
|
return password
|
|
|
|
|
|
|
|
|
2023-04-22 15:39:48 +00:00
|
|
|
def secret_arn(account_id: str, region: str, secret_id: str) -> str:
|
2022-06-09 05:54:51 +10:00
|
|
|
id_string = "".join(random.choice(string.ascii_letters) for _ in range(6))
|
2022-08-13 09:49:43 +00:00
|
|
|
return (
|
|
|
|
f"arn:aws:secretsmanager:{region}:{account_id}:secret:{secret_id}-{id_string}"
|
2018-10-24 14:06:23 -07:00
|
|
|
)
|
2018-07-16 12:39:59 -07:00
|
|
|
|
|
|
|
|
2023-03-25 11:00:17 -01:00
|
|
|
def get_secret_name_from_partial_arn(partial_arn: str) -> str:
|
|
|
|
# We can retrieve a secret either using a full ARN, or using a partial ARN
|
|
|
|
# name: testsecret
|
|
|
|
# full ARN: arn:aws:secretsmanager:us-west-2:123456789012:secret:testsecret-xxxxxx
|
|
|
|
# partial ARN: arn:aws:secretsmanager:us-west-2:123456789012:secret:testsecret
|
|
|
|
#
|
|
|
|
# This method only deals with partial ARN's, and will return the name: testsecret
|
|
|
|
#
|
|
|
|
# If you were to pass in full url, this method will return 'testsecret-xxxxxx' - which has no meaning on it's own
|
|
|
|
if partial_arn.startswith("arn:aws:secretsmanager:"):
|
2019-11-23 10:12:31 +03:00
|
|
|
# split the arn by colon
|
|
|
|
# then get the last value which is the name appended with a random string
|
2023-03-25 11:00:17 -01:00
|
|
|
return partial_arn.split(":")[-1]
|
|
|
|
return partial_arn
|
2019-11-23 10:12:31 +03:00
|
|
|
|
|
|
|
|
2023-04-22 15:39:48 +00:00
|
|
|
def _exclude_characters(password: str, exclude_characters: str) -> str:
|
2018-07-16 12:39:59 -07:00
|
|
|
for c in exclude_characters:
|
|
|
|
if c in string.punctuation:
|
|
|
|
# Escape punctuation regex usage
|
2022-11-21 18:21:34 -01:00
|
|
|
c = rf"\{c}"
|
2018-07-16 12:39:59 -07:00
|
|
|
password = re.sub(c, "", str(password))
|
|
|
|
return password
|
|
|
|
|
|
|
|
|
2023-04-22 15:39:48 +00:00
|
|
|
def _add_password_require_each_included_type(
|
|
|
|
password: str, required_characters: str
|
|
|
|
) -> str:
|
2018-07-16 12:39:59 -07:00
|
|
|
password_with_required_char = password[: -len(required_characters)]
|
|
|
|
password_with_required_char += required_characters
|
|
|
|
|
|
|
|
return password_with_required_char
|