@@ -13,6 +13,40 @@ class ConfidentialComputeConfig(TypedDict):
1313 environment : str
1414 skip_validations : NotRequired [bool ]
1515 debug_mode : NotRequired [bool ]
16+
17+ class ConfidentialComputeStartupException (Exception ):
18+ def __init__ (self , error_name , provider , extra_message = None ):
19+ urls = {
20+ "EC2" : "https://unifiedid.com/docs/guides/operator-guide-aws-marketplace#uid2-operator-error-codes" ,
21+ "Azure" : "https://unifiedid.com/docs/guides/operator-guide-azure-enclave#uid2-operator-error-codes" ,
22+ "GCP" : "https://unifiedid.com/docs/guides/operator-private-gcp-confidential-space#uid2-operator-error-codes" ,
23+ }
24+ url = urls .get (provider )
25+ super ().__init__ (f"{ error_name } \n " + (extra_message if extra_message else "" ) + f"\n Visit { url } for more details" )
26+
27+ class MissingInstanceProfile (ConfidentialComputeStartupException ):
28+ def __init__ (self , cls ):
29+ super ().__init__ (error_name = f"E01: { self .__class__ .__name__ } " , provider = cls )
30+
31+ class ConfigNotFound (ConfidentialComputeStartupException ):
32+ def __init__ (self , cls , message = None ):
33+ super ().__init__ (error_name = f"E02: { self .__class__ .__name__ } " , provider = cls , extra_message = message )
34+
35+ class MissingConfig (ConfidentialComputeStartupException ):
36+ def __init__ (self , cls , missing_keys ):
37+ super ().__init__ (error_name = f"E03: { self .__class__ .__name__ } " , provider = cls , extra_message = ', ' .join (missing_keys ))
38+
39+ class InvalidConfigValue (ConfidentialComputeStartupException ):
40+ def __init__ (self , cls , config_key = None ):
41+ super ().__init__ (error_name = f"E04: { self .__class__ .__name__ } " , provider = cls , extra_message = config_key )
42+
43+ class InvalidOperatorKey (ConfidentialComputeStartupException ):
44+ def __init__ (self , cls ):
45+ super ().__init__ (error_name = f"E05: { self .__class__ .__name__ } " , provider = cls )
46+
47+ class UID2ServicesUnreachable (ConfidentialComputeStartupException ):
48+ def __init__ (self , cls , ip = None ):
49+ super ().__init__ (error_name = f"E06: { self .__class__ .__name__ } " , provider = cls , extra_message = ip )
1650
1751class ConfidentialCompute (ABC ):
1852
@@ -25,36 +59,26 @@ def validate_configuration(self):
2559 def validate_operator_key ():
2660 """ Validates the operator key format and its environment alignment."""
2761 operator_key = self .configs .get ("api_token" )
28- if not operator_key :
29- raise ValueError ("API token is missing from the configuration." )
3062 pattern = r"^(UID2|EUID)-.\-(I|P|L)-\d+-.*$"
3163 if re .match (pattern , operator_key ):
3264 env = self .configs .get ("environment" , "" ).lower ()
3365 debug_mode = self .configs .get ("debug_mode" , False )
3466 expected_env = "I" if debug_mode or env == "integ" else "P"
35-
3667 if operator_key .split ("-" )[2 ] != expected_env :
37- raise ValueError (
38- f"Operator key does not match the expected environment ({ expected_env } )."
39- )
68+ raise InvalidOperatorKey (self .__class__ .__name__ )
4069 print ("Validated operator key matches environment" )
4170 else :
4271 print ("Skipping operator key validation" )
4372
4473 def validate_url (url_key , environment ):
4574 """URL should include environment except in prod"""
4675 if environment != "prod" and environment not in self .configs [url_key ]:
47- raise ValueError (
48- f"{ url_key } must match the environment. Ensure the URL includes '{ environment } '."
49- )
76+ raise InvalidConfigValue (self .__class__ .__name__ , url_key )
5077 parsed_url = urlparse (self .configs [url_key ])
5178 if parsed_url .scheme != 'https' and parsed_url .path :
52- raise ValueError (
53- f"{ url_key } is invalid. Ensure { self .configs [url_key ]} follows HTTPS, and doesn't have any path specified."
54- )
79+ raise InvalidConfigValue (self .__class__ .__name__ , url_key )
5580 print (f"Validated { self .configs [url_key ]} matches other config parameters" )
5681
57-
5882 def validate_connectivity () -> None :
5983 """ Validates that the core URL is accessible."""
6084 try :
@@ -63,32 +87,29 @@ def validate_connectivity() -> None:
6387 requests .get (core_url , timeout = 5 )
6488 print (f"Validated connectivity to { core_url } " )
6589 except (requests .ConnectionError , requests .Timeout ) as e :
66- raise RuntimeError (
67- f"Failed to reach required URLs. Consider enabling { core_ip } in the egress firewall."
68- )
90+ raise UID2ServicesUnreachable (self .__class__ .__name__ , core_ip )
6991 except Exception as e :
70- raise Exception ("Failed to reach the URLs." ) from e
92+ raise UID2ServicesUnreachable (self .__class__ .__name__ )
93+
7194 type_hints = get_type_hints (ConfidentialComputeConfig , include_extras = True )
7295 required_keys = [field for field , hint in type_hints .items () if "NotRequired" not in str (hint )]
7396 missing_keys = [key for key in required_keys if key not in self .configs ]
7497 if missing_keys :
75- raise MissingConfigError ( missing_keys )
76-
98+ raise MissingConfig ( self . __class__ . __name__ , missing_keys )
99+
77100 environment = self .configs ["environment" ]
78-
79101 if environment not in ["integ" , "prod" ]:
80- raise ValueError ( "Environment must be either prod/integ. It is currently set to" , environment )
102+ raise InvalidConfigValue ( self . __class__ . __name__ , " environment" )
81103
82104 if self .configs .get ("debug_mode" ) and environment == "prod" :
83- raise ValueError ( "Debug mode cannot be enabled in the production environment. " )
105+ raise InvalidConfigValue ( self . __class__ . __name__ , "debug_mode " )
84106
85107 validate_url ("core_base_url" , environment )
86108 validate_url ("optout_base_url" , environment )
87109 validate_operator_key ()
88110 validate_connectivity ()
89111 print ("Completed static validation of confidential compute config values" )
90112
91-
92113 @abstractmethod
93114 def _get_secret (self , secret_identifier : str ) -> ConfidentialComputeConfig :
94115 """
@@ -124,21 +145,4 @@ def run_command(command, seperate_process=False):
124145 subprocess .run (command ,check = True )
125146 except Exception as e :
126147 print (f"Failed to run command: { str (e )} " )
127- raise RuntimeError (f"Failed to start { ' ' .join (command )} " )
128-
129- class ConfidentialComputeStartupException (Exception ):
130- def __init__ (self , message ):
131- super ().__init__ (message )
132-
133- class MissingConfigError (ConfidentialComputeStartupException ):
134- """Custom exception to handle missing config keys."""
135- def __init__ (self , missing_keys ):
136- self .missing_keys = missing_keys
137- self .message = f"\n Missing configuration keys: { ', ' .join (missing_keys )} \n "
138- super ().__init__ (self .message )
139-
140- class SecretNotFoundException (ConfidentialComputeStartupException ):
141- """Custom exception if secret manager is not found"""
142- def __init__ (self , name ):
143- self .message = f"Secret manager not found - { name } . Please check if secret exist and the Instance Profile has permission to read it"
144- super ().__init__ (self .message )
148+ raise RuntimeError (f"Failed to start { ' ' .join (command )} " )
0 commit comments