1111import argparse
1212import logging
1313from botocore .exceptions import ClientError , NoCredentialsError
14- from typing import Dict
14+ from typing import Dict , List
1515import sys
1616import time
1717import yaml
@@ -105,6 +105,8 @@ def add_defaults(configs: Dict[str, any]) -> AWSConfidentialComputeConfig:
105105 try :
106106 self .configs = add_defaults (json .loads (client .get_secret_value (SecretId = secret_identifier )["SecretString" ]))
107107 self .__validate_aws_specific_config ()
108+ except json .JSONDecodeError as e :
109+ raise OperatorKeyNotFoundError (self .__class__ .__name__ , f"Can not parse secret { secret_identifier } in { region } " )
108110 except NoCredentialsError as _ :
109111 raise InstanceProfileMissingError (self .__class__ .__name__ )
110112 except ClientError as _ :
@@ -119,38 +121,80 @@ def __get_max_capacity():
119121 except Exception as e :
120122 raise RuntimeError ("/etc/nitro_enclaves/allocator.yaml does not have CPU, memory allocated" )
121123
122- def __setup_vsockproxy (self , log_level : int ) -> None :
123- """
124- Sets up the vsock proxy service.
125- """
124+ def __setup_vsockproxy (self ) -> None :
125+ logging .info ("Sets up the vSock proxy service" )
126126 thread_count = (multiprocessing .cpu_count () + 1 ) // 2
127127 command = [
128128 "/usr/bin/vsockpx" , "-c" , "/etc/uid2operator/proxy.yaml" ,
129- "--workers" , str (thread_count ), "--log-level" , str (log_level ), "--daemon"
129+ "--workers" , str (thread_count ), "--daemon"
130+ ]
131+
132+ debug_command = [
133+ "/usr/bin/vsockpx" , "-c" , "/etc/uid2operator/proxy.yaml" ,
134+ "--workers" , str (thread_count ), "--log-level" , "0"
130135 ]
131- self .run_command (command )
136+
137+ self .run_service ([command , debug_command ], "vsock_proxy" )
132138
133139 def __run_config_server (self ) -> None :
134- """
135- Starts the Flask configuration server.
136- """
140+ logging .info ("Starts the Flask configuration server" )
137141 os .makedirs ("/etc/secret/secret-value" , exist_ok = True )
138142 config_path = "/etc/secret/secret-value/config"
143+
144+ # Save configs to a file
139145 with open (config_path , 'w' ) as config_file :
140146 json .dump (self .configs , config_file )
147+
141148 os .chdir ("/opt/uid2operator/config-server" )
142149 command = ["./bin/flask" , "run" , "--host" , AuxiliaryConfig .LOCALHOST , "--port" , AuxiliaryConfig .FLASK_PORT ]
143- self .run_command (command , separate_process = True )
150+
151+ self .run_service ([command , command ], "flask_config_server" , separate_process = True )
144152
145153 def __run_socks_proxy (self ) -> None :
154+ logging .info ("Starts the SOCKS proxy service" )
155+ command = ["sockd" , "-D" ]
156+
157+ # -d specifies debug level
158+ debug_command = ["sockd" , "-d" , "0" ]
159+
160+ self .run_service ([command , debug_command ], "socks_proxy" )
161+
162+ def run_service (self , command : List [List [str ]], log_filename : str , separate_process : bool = False ) -> None :
146163 """
147- Starts the SOCKS proxy service.
164+ Runs a service command with logging if debug_mode is enabled.
165+
166+ :param command: command[0] regular command, command[1] debug mode command
167+ :param log_filename: Base name of the log file (e.g., "flask_config_server", "socks_proxy", "vsock_proxy")
168+ :param separate_process: Whether to run in a separate process
148169 """
149- command = ["sockd" , "-D" ]
150- self .run_command (command )
170+ log_file = f"/var/log/{ log_filename } .log"
171+
172+ if self .configs .get ("debug_mode" ) is True :
173+
174+ # Remove old log file to start fresh
175+ if os .path .exists (log_file ):
176+ os .remove (log_file )
177+
178+ # Set up logging
179+ logging .basicConfig (
180+ filename = log_file ,
181+ filemode = "w" ,
182+ level = logging .DEBUG ,
183+ format = "%(asctime)s %(levelname)s: %(message)s"
184+ )
185+
186+ logging .info (f"Debug mode is on, logging into { log_file } " )
187+
188+ # Run debug mode command
189+ with open (log_file , "a" ) as log :
190+ self .run_command (command [1 ], separate_process = True , stdout = log , stderr = log )
191+ else :
192+ # Run regular command, possibly daemon
193+ self .run_command (command [0 ], separate_process = separate_process )
151194
152195 def __get_secret_name_from_userdata (self ) -> str :
153196 """Extracts the secret name from EC2 user data."""
197+ logging .info ("Extracts the secret name from EC2 user data" )
154198 token = self .__get_aws_token ()
155199 response = requests .get (AuxiliaryConfig .get_user_data_url (), headers = {"X-aws-ec2-metadata-token" : token })
156200 user_data = response .text
@@ -165,8 +209,7 @@ def __get_secret_name_from_userdata(self) -> str:
165209
166210 def _setup_auxiliaries (self ) -> None :
167211 """Sets up the vsock tunnel, socks proxy and flask server"""
168- log_level = 1 if self .configs ["debug_mode" ] else 3
169- self .__setup_vsockproxy (log_level )
212+ self .__setup_vsockproxy ()
170213 self .__run_config_server ()
171214 self .__run_socks_proxy ()
172215 logging .info ("Finished setting up all auxiliaries" )
@@ -206,7 +249,7 @@ def __run_nitro_enclave(self):
206249 "--enclave-name" , "uid2operator"
207250 ]
208251 if self .configs .get ('debug_mode' , False ):
209- logging .info ("Running in debug_mode" )
252+ logging .info ("Running nitro in debug_mode" )
210253 command += ["--debug-mode" , "--attach-console" ]
211254 self .run_command (command , separate_process = False )
212255
@@ -248,6 +291,7 @@ def __kill_auxiliaries(self) -> None:
248291 parser = argparse .ArgumentParser (description = "Manage EC2-based confidential compute workflows." )
249292 parser .add_argument ("-o" , "--operation" , choices = ["stop" , "start" ], default = "start" , help = "Operation to perform." )
250293 args = parser .parse_args ()
294+
251295 try :
252296 ec2 = EC2EntryPoint ()
253297 if args .operation == "stop" :
0 commit comments