148 lines
4.9 KiB
Python
148 lines
4.9 KiB
Python
"""DirectoryServiceBackend checks that result in ValidationException.
|
|
|
|
Note that ValidationExceptions are accumulative.
|
|
"""
|
|
import re
|
|
|
|
from moto.ds.exceptions import DsValidationException
|
|
|
|
|
|
def validate_args(validators):
|
|
"""Raise exception if any of the validations fails.
|
|
|
|
validators is a list of tuples each containing the following:
|
|
(printable field name, field value)
|
|
|
|
The error messages are accumulated before the exception is raised.
|
|
"""
|
|
validation_map = {
|
|
"alias": validate_alias,
|
|
"description": validate_description,
|
|
"directoryId": validate_directory_id,
|
|
"connectSettings.customerDnsIps": validate_dns_ips,
|
|
"edition": validate_edition,
|
|
"name": validate_name,
|
|
"password": validate_password,
|
|
"shortName": validate_short_name,
|
|
"size": validate_size,
|
|
"ssoPassword": validate_sso_password,
|
|
"connectSettings.vpcSettings.subnetIds": validate_subnet_ids,
|
|
"connectSettings.customerUserName": validate_user_name,
|
|
"userName": validate_user_name,
|
|
"vpcSettings.subnetIds": validate_subnet_ids,
|
|
}
|
|
err_msgs = []
|
|
# This eventually could be a switch (python 3.10), elminating the need
|
|
# for the above map and individual functions.
|
|
for (fieldname, value) in validators:
|
|
msg = validation_map[fieldname](value)
|
|
if msg:
|
|
err_msgs.append((fieldname, value, msg))
|
|
if err_msgs:
|
|
raise DsValidationException(err_msgs)
|
|
|
|
|
|
def validate_alias(value):
|
|
"""Raise exception if alias fails to conform to length and constraints."""
|
|
if len(value) > 62:
|
|
return "have length less than or equal to 62"
|
|
|
|
alias_pattern = r"^(?!D-|d-)([\da-zA-Z]+)([-]*[\da-zA-Z])*$"
|
|
if not re.match(alias_pattern, value):
|
|
return fr"satisfy regular expression pattern: {alias_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_description(value):
|
|
"""Raise exception if description exceeds length."""
|
|
if value and len(value) > 128:
|
|
return "have length less than or equal to 128"
|
|
return ""
|
|
|
|
|
|
def validate_directory_id(value):
|
|
"""Raise exception if the directory id is invalid."""
|
|
id_pattern = r"^d-[0-9a-f]{10}$"
|
|
if not re.match(id_pattern, value):
|
|
return fr"satisfy regular expression pattern: {id_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_dns_ips(value):
|
|
"""Raise exception if DNS IPs fail to match constraints."""
|
|
dnsip_pattern = (
|
|
r"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}"
|
|
r"(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
|
|
)
|
|
for dnsip in value:
|
|
if not re.match(dnsip_pattern, dnsip):
|
|
return fr"satisfy regular expression pattern: {dnsip_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_edition(value):
|
|
"""Raise exception if edition not one of the allowed values."""
|
|
if value and value not in ["Enterprise", "Standard"]:
|
|
return "satisfy enum value set: [Enterprise, Standard]"
|
|
return ""
|
|
|
|
|
|
def validate_name(value):
|
|
"""Raise exception if name fails to match constraints."""
|
|
name_pattern = r"^([a-zA-Z0-9]+[\.-])+([a-zA-Z0-9])+$"
|
|
if not re.match(name_pattern, value):
|
|
return fr"satisfy regular expression pattern: {name_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_password(value):
|
|
"""Raise exception if password fails to match constraints."""
|
|
passwd_pattern = (
|
|
r"^(?=^.{8,64}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|"
|
|
r"(?=.*\d)(?=.*[^A-Za-z0-9\s])(?=.*[a-z])|"
|
|
r"(?=.*[^A-Za-z0-9\s])(?=.*[A-Z])(?=.*[a-z])|"
|
|
r"(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))^.*$"
|
|
)
|
|
if not re.match(passwd_pattern, value):
|
|
return fr"satisfy regular expression pattern: {passwd_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_short_name(value):
|
|
"""Raise exception if short name fails to match constraints."""
|
|
short_name_pattern = r'^[^\/:*?"<>|.]+[^\/:*?"<>|]*$'
|
|
if value and not re.match(short_name_pattern, value):
|
|
return fr"satisfy regular expression pattern: {short_name_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_size(value):
|
|
"""Raise exception if size fails to match constraints."""
|
|
if value.lower() not in ["small", "large"]:
|
|
return "satisfy enum value set: [Small, Large]"
|
|
return ""
|
|
|
|
|
|
def validate_sso_password(value):
|
|
"""Raise exception is SSO password exceeds length."""
|
|
if value and len(value) > 128:
|
|
return "have length less than or equal to 128"
|
|
return ""
|
|
|
|
|
|
def validate_subnet_ids(value):
|
|
"""Raise exception is subnet IDs fail to match constraints."""
|
|
subnet_id_pattern = r"^(subnet-[0-9a-f]{8}|subnet-[0-9a-f]{17})$"
|
|
for subnet in value:
|
|
if not re.match(subnet_id_pattern, subnet):
|
|
return fr"satisfy regular expression pattern: {subnet_id_pattern}"
|
|
return ""
|
|
|
|
|
|
def validate_user_name(value):
|
|
"""Raise exception is username fails to match constraints."""
|
|
username_pattern = r"^[a-zA-Z0-9._-]+$"
|
|
if value and not re.match(username_pattern, value):
|
|
return fr"satisfy regular expression pattern: {username_pattern}"
|
|
return ""
|