2727REQUESTER_NAME = 'Venafi Cloud Service'
2828REQUESTER_EMAIL = 'no-reply@venafi.cloud'
2929REQUESTER_PHONE = '801-555-0123'
30- ALLOW_ALL = '.*'
30+ ipv4 = "v4"
31+ ipv6 = "v6"
32+ ipv4_private = "v4private"
33+ ipv6_private = "v6private"
34+ re_allow_all = '.*'
35+ re_allow_all_email = '.*@.*'
36+ re_ipv4 = "\\ b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\ .|$)){4}\\ b"
37+ re_ipv6 = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]" \
38+ "{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|" \
39+ "([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|" \
40+ "[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%" \
41+ "[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\ .){3,3}(25[0-5]|" \
42+ "(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\ .)" \
43+ "{3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))"
44+ re_ipv4_private = "^(172\\ .(1[6-9]\\ .|2[0-9]\\ .|3[0-1]\\ .)|192\\ .168\\ .|10\\ .).*"
45+ re_ipv6_private = "^(::1$)|([fF][cCdD]).*"
46+ supported_ip_protocols = {
47+ ipv4 : re_ipv4 ,
48+ ipv6 : re_ipv6 ,
49+ ipv4_private : re_ipv4_private ,
50+ ipv6_private : re_ipv6_private
51+ }
3152DEFAULT_MAX_VALID_DAYS = 365
3253DEFAULT_HASH_ALGORITHM = 'SHA256'
3354
@@ -119,9 +140,26 @@ def build_policy_spec(cit, ca_info, subject_cn_to_str=True):
119140 p .key_pair = kp if create_kp else None
120141
121142 sans = SubjectAltNames (False , False , False , False , False )
143+ create_sans = False
122144 if cit .SANRegexes :
123145 sans .dns_allowed = True
124- p .subject_alt_names = sans
146+ create_sans = True
147+
148+ if cit .email_regexes and len (cit .email_regexes ) > 0 :
149+ sans .email_allowed = True
150+ create_sans = True
151+
152+ if cit .ip_constraints_regexes and len (cit .ip_constraints_regexes ) > 0 :
153+ sans .ip_allowed = True
154+ create_sans = True
155+ sans .ip_constraints = resolve_ip_constraints (cit .ip_constraints_regexes )
156+
157+ if cit .uri_regexes and len (cit .uri_regexes ) > 0 :
158+ sans .uri_allowed = True
159+ create_sans = True
160+ sans .uri_protocols = resolve_uri_protocols (cit .uri_regexes )
161+
162+ p .subject_alt_names = sans if create_sans else None
125163
126164 ps .policy = p
127165
@@ -201,8 +239,17 @@ def validate_policy_spec(policy_spec):
201239 sans = get_sans (policy_spec .policy .subject_alt_names )
202240 if len (sans ) > 0 :
203241 for k , v in sans .items ():
204- if v is True and not (k == RPA .TPP_DNS_ALLOWED ):
242+ if v is True and (k == RPA .TPP_UPN_ALLOWED ):
205243 raise VenafiError (f"Subject Alt name [{ k } ] is not allowed by VaaS" )
244+ if v is True and (k == RPA .TPP_URI_ALLOWED ):
245+ if len (p .subject_alt_names .uri_protocols ) == 0 :
246+ raise VenafiError (f"'uriAllowed' attribute is True but 'uriProtocols' list is empty" )
247+ if v is True and (k == RPA .TPP_IP_ALLOWED ):
248+ ip_constraints = p .subject_alt_names .ip_constraints
249+ if ip_constraints and len (ip_constraints ) > 0 :
250+ invalid_value = get_invalid_ip_constraint (ip_constraints )
251+ if invalid_value :
252+ raise VenafiError (f"The IP constraint [{ invalid_value } ] is not supported by VaaS" )
206253
207254 # validate default subject values against policy values
208255 if policy_spec .defaults and policy_spec .defaults .subject and policy_spec .policy .subject :
@@ -325,13 +372,26 @@ def get_sans(names):
325372 return sans
326373
327374
375+ def get_invalid_ip_constraint (ip_list ):
376+ """
377+
378+ :param list[str] ip_list:
379+ :rtype: str
380+ """
381+ for ip_value in ip_list :
382+ if ip_value not in supported_ip_protocols .keys ():
383+ return ip_value
384+
385+ return None
386+
387+
328388def is_valid_policy_value (policy_values , default_value ):
329389 """
330390 :param list[str] policy_values:
331391 :param str default_value:
332392 :rtype: bool
333393 """
334- if len (policy_values ) == 1 and policy_values [0 ] == ALLOW_ALL :
394+ if len (policy_values ) == 1 and policy_values [0 ] == re_allow_all :
335395 return True
336396 return True if default_value in policy_values else False
337397
@@ -344,7 +404,7 @@ def member_of(sub_list, collection):
344404 :param list[str] collection:
345405 :rtype: bool
346406 """
347- if len (sub_list ) == 1 and sub_list [0 ] == ALLOW_ALL :
407+ if len (sub_list ) == 1 and sub_list [0 ] == re_allow_all :
348408 return True
349409 return all (x in collection for x in sub_list )
350410
@@ -408,39 +468,66 @@ def build_cit_request(ps, ca_details):
408468 if ps .policy and len (ps .policy .domains ) > 0 :
409469 regex_value = convert_to_regex (ps .policy .domains , ps .policy .wildcard_allowed )
410470 request ['subjectCNRegexes' ] = regex_value
411- if ps .policy .subject_alt_names and ps .policy .subject_alt_names .dns_allowed is not None :
412- if ps .policy .subject_alt_names .dns_allowed :
471+ sans = ps .policy .subject_alt_names
472+ if sans and sans .dns_allowed is not None :
473+ if sans .dns_allowed :
413474 request ['sanRegexes' ] = regex_value
414475 else :
415476 request ['sanRegexes' ] = regex_value
477+
478+ if sans and sans .email_allowed :
479+ email_regex_list = convert_to_email_regex (ps .policy .domains )
480+ request ['sanRfc822NameRegexes' ] = email_regex_list
481+
482+ if sans and sans .uri_allowed :
483+ uri_regex_list = convert_to_uri_regex (sans .uri_protocols , ps .policy .domains )
484+ request ['sanUniformResourceIdentifierRegexes' ] = uri_regex_list
485+
486+ # sanIpAddressRegexes
487+
416488 else :
417- request ['subjectCNRegexes' ] = [ALLOW_ALL ]
418- request ['sanRegexes' ] = [ALLOW_ALL ]
489+ request ['subjectCNRegexes' ] = [re_allow_all ]
490+ request ['sanRegexes' ] = [re_allow_all ]
491+ if ps .policy :
492+ sans = ps .policy .subject_alt_names
493+ if sans and sans .email_allowed :
494+ request ['sanRfc822NameRegexes' ] = [re_allow_all_email ]
495+ if sans and sans .uri_allowed :
496+ uri_regex_list = convert_to_uri_regex (sans .uri_protocols , [re_allow_all ])
497+ request ['sanUniformResourceIdentifierRegexes' ] = uri_regex_list
498+ if sans and sans .ip_allowed :
499+ request ['sanIpAddressRegexes' ] = []
500+
501+ if ps .policy and ps .policy .subject_alt_names and ps .policy .subject_alt_names .ip_allowed :
502+ if ps .policy .subject_alt_names .ip_constraints and len (ps .policy .subject_alt_names .ip_constraints ) > 0 :
503+ request ['sanIpAddressRegexes' ] = resolve_ip_regexes (ps .policy .subject_alt_names .ip_constraints )
504+ else :
505+ request ['sanIpAddressRegexes' ] = [re_ipv4 , re_ipv6 ]
419506
420507 if ps .policy and ps .policy .subject and len (ps .policy .subject .orgs ) > 0 :
421508 request ['subjectORegexes' ] = ps .policy .subject .orgs
422509 else :
423- request ['subjectORegexes' ] = [ALLOW_ALL ]
510+ request ['subjectORegexes' ] = [re_allow_all ]
424511
425512 if ps .policy and ps .policy .subject and len (ps .policy .subject .org_units ) > 0 :
426513 request ['subjectOURegexes' ] = ps .policy .subject .org_units
427514 else :
428- request ['subjectOURegexes' ] = [ALLOW_ALL ]
515+ request ['subjectOURegexes' ] = [re_allow_all ]
429516
430517 if ps .policy and ps .policy .subject and len (ps .policy .subject .localities ) > 0 :
431518 request ['subjectLRegexes' ] = ps .policy .subject .localities
432519 else :
433- request ['subjectLRegexes' ] = [ALLOW_ALL ]
520+ request ['subjectLRegexes' ] = [re_allow_all ]
434521
435522 if ps .policy and ps .policy .subject and len (ps .policy .subject .states ) > 0 :
436523 request ['subjectSTRegexes' ] = ps .policy .subject .states
437524 else :
438- request ['subjectSTRegexes' ] = [ALLOW_ALL ]
525+ request ['subjectSTRegexes' ] = [re_allow_all ]
439526
440527 if ps .policy and ps .policy .subject and len (ps .policy .subject .countries ) > 0 :
441528 request ['subjectCValues' ] = ps .policy .subject .countries
442529 else :
443- request ['subjectCValues' ] = [ALLOW_ALL ]
530+ request ['subjectCValues' ] = [re_allow_all ]
444531
445532 key_types = []
446533 if ps .policy and ps .policy .key_pair and len (ps .policy .key_pair .key_types ) > 0 :
@@ -529,13 +616,15 @@ def build_cit_request(ps, ca_details):
529616
530617domain_regex = '[a-z]{1}[a-z0-9.-]*\\ .'
531618domain_regex_wildcard = '[*a-z]{1}[a-z0-9.-]*\\ .'
619+ email_prefix_regex = '.*@{}'
620+ uri_protocols_regex = "({})://.*\\ ."
532621
533622
534623def convert_to_regex (domains , wildcard_allowed ):
535624 """
536625 :param list[str] domains:
537626 :param bool wildcard_allowed:
538- :rtype: dict
627+ :rtype: list[str]
539628 """
540629 regex_list = []
541630 for d in domains :
@@ -548,6 +637,88 @@ def convert_to_regex(domains, wildcard_allowed):
548637 return regex_list
549638
550639
640+ def convert_to_email_regex (emails_list ):
641+ """
642+
643+ :param list[str] emails_list:
644+ :rtype: list[str]
645+ """
646+ regex_list = []
647+ for email in emails_list :
648+ current = email .replace ('.' , '\\ .' )
649+ current = email_prefix_regex .format (current )
650+ regex_list .append (current )
651+
652+ return regex_list
653+
654+
655+ def convert_to_uri_regex (uri_protocols , domains_list ):
656+ """
657+
658+ :param list[str] uri_protocols:
659+ :param list[str] domains_list:
660+ :rtype: list[str]
661+ """
662+ protocol_expr = "|" .join (uri_protocols )
663+ protocol_expr = uri_protocols_regex .format (protocol_expr )
664+
665+ regex_list = []
666+ for d in domains_list :
667+ current = d .replace ('.' , '\\ .' )
668+ current = f"{ protocol_expr } { current } "
669+ regex_list .append (current )
670+
671+ return regex_list
672+
673+
674+ def resolve_ip_regexes (ip_protocols ):
675+ """
676+
677+ :param list[str] ip_protocols:
678+ :rtype: list[str]
679+ """
680+ ip_regexes = list ()
681+ for ip_str in ip_protocols :
682+ regex = supported_ip_protocols .get (ip_str )
683+ if regex :
684+ ip_regexes .append (regex )
685+
686+ return ip_regexes
687+
688+
689+ def resolve_ip_constraints (ip_constraints_list ):
690+ """
691+
692+ :param list[str] ip_constraints_list:
693+ :rtype: list[str]
694+ """
695+ ip_list = list ()
696+ for ip_regex in ip_constraints_list :
697+ for k , v in supported_ip_protocols .items ():
698+ if ip_regex == v :
699+ ip_list .append (k )
700+ break
701+ return ip_list
702+
703+
704+ def resolve_uri_protocols (uri_regexes_list ):
705+ """
706+
707+ :param list[str] uri_regexes_list:
708+ :rtype: list[str]
709+ """
710+ protocols_list = list ()
711+ for uri_regex in uri_regexes_list :
712+ index = uri_regex .index (')://' )
713+ sub_str = uri_regex [1 :index ]
714+ current_protocols = sub_str .split ("|" )
715+ for p in current_protocols :
716+ if p not in protocols_list :
717+ protocols_list .append (p )
718+
719+ return protocols_list
720+
721+
551722def convert_to_string (regexes , wildcard_allowed ):
552723 """
553724 :param list[str] regexes:
0 commit comments