cloudx-proxy 0.3.14__py3-none-any.whl → 0.3.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
cloudx_proxy/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.3.14'
21
- __version_tuple__ = version_tuple = (0, 3, 14)
20
+ __version__ = version = '0.3.15'
21
+ __version_tuple__ = version_tuple = (0, 3, 15)
cloudx_proxy/cli.py CHANGED
@@ -17,8 +17,9 @@ def cli():
17
17
  @click.option('--profile', default='vscode', help='AWS profile to use (default: vscode)')
18
18
  @click.option('--region', help='AWS region (default: from profile, or eu-west-1 if not set)')
19
19
  @click.option('--ssh-key', default='vscode', help='SSH key name to use (default: vscode)')
20
+ @click.option('--ssh-config', help='SSH config file to use (default: ~/.ssh/vscode/config)')
20
21
  @click.option('--aws-env', help='AWS environment directory (default: ~/.aws, use name of directory in ~/.aws/aws-envs/)')
21
- def connect(instance_id: str, port: int, profile: str, region: str, ssh_key: str, aws_env: str):
22
+ def connect(instance_id: str, port: int, profile: str, region: str, ssh_key: str, ssh_config: str, aws_env: str):
22
23
  """Connect to an EC2 instance via SSM.
23
24
 
24
25
  INSTANCE_ID is the EC2 instance ID to connect to (e.g., i-0123456789abcdef0)
@@ -35,6 +36,7 @@ def connect(instance_id: str, port: int, profile: str, region: str, ssh_key: str
35
36
  profile=profile,
36
37
  region=region,
37
38
  ssh_key=ssh_key,
39
+ ssh_config=ssh_config,
38
40
  aws_env=aws_env
39
41
  )
40
42
 
@@ -48,8 +50,9 @@ def connect(instance_id: str, port: int, profile: str, region: str, ssh_key: str
48
50
  @cli.command()
49
51
  @click.option('--profile', default='vscode', help='AWS profile to use (default: vscode)')
50
52
  @click.option('--ssh-key', default='vscode', help='SSH key name to use (default: vscode)')
53
+ @click.option('--ssh-config', help='SSH config file to use (default: ~/.ssh/vscode/config)')
51
54
  @click.option('--aws-env', help='AWS environment directory (default: ~/.aws, use name of directory in ~/.aws/aws-envs/)')
52
- def setup(profile: str, ssh_key: str, aws_env: str):
55
+ def setup(profile: str, ssh_key: str, ssh_config: str, aws_env: str):
53
56
  """Set up AWS profile, SSH keys, and configuration for CloudX.
54
57
 
55
58
  This command will:
@@ -61,9 +64,10 @@ def setup(profile: str, ssh_key: str, aws_env: str):
61
64
  Example usage:
62
65
  cloudx-proxy setup
63
66
  cloudx-proxy setup --profile myprofile --ssh-key mykey
67
+ cloudx-proxy setup --ssh-config ~/.ssh/cloudx/config
64
68
  """
65
69
  try:
66
- setup = CloudXSetup(profile=profile, ssh_key=ssh_key, aws_env=aws_env)
70
+ setup = CloudXSetup(profile=profile, ssh_key=ssh_key, ssh_config=ssh_config, aws_env=aws_env)
67
71
 
68
72
  print("\n\033[1;95m=== cloudx-proxy Setup ===\033[0m\n")
69
73
 
cloudx_proxy/core.py CHANGED
@@ -7,7 +7,7 @@ from botocore.exceptions import ClientError
7
7
 
8
8
  class CloudXProxy:
9
9
  def __init__(self, instance_id: str, port: int = 22, profile: str = "vscode",
10
- region: str = None, ssh_key: str = "vscode", aws_env: str = None):
10
+ region: str = None, ssh_key: str = "vscode", ssh_config: str = None, aws_env: str = None):
11
11
  """Initialize CloudX client for SSH tunneling via AWS SSM.
12
12
 
13
13
  Args:
@@ -39,8 +39,14 @@ class CloudXProxy:
39
39
  self.ec2 = self.session.client('ec2')
40
40
  self.ec2_connect = self.session.client('ec2-instance-connect')
41
41
 
42
- # Set up SSH key path
43
- self.ssh_dir = os.path.expanduser("~/.ssh/vscode")
42
+ # Set up SSH configuration and key paths
43
+ if ssh_config:
44
+ self.ssh_config_file = os.path.expanduser(ssh_config)
45
+ self.ssh_dir = os.path.dirname(self.ssh_config_file)
46
+ else:
47
+ self.ssh_dir = os.path.expanduser("~/.ssh/vscode")
48
+ self.ssh_config_file = os.path.join(self.ssh_dir, "config")
49
+
44
50
  self.ssh_key = os.path.join(self.ssh_dir, f"{ssh_key}.pub")
45
51
 
46
52
  def log(self, message: str) -> None:
cloudx_proxy/setup.py CHANGED
@@ -9,20 +9,28 @@ import boto3
9
9
  from botocore.exceptions import ClientError
10
10
 
11
11
  class CloudXSetup:
12
- def __init__(self, profile: str = "vscode", ssh_key: str = "vscode", aws_env: str = None):
12
+ def __init__(self, profile: str = "vscode", ssh_key: str = "vscode", ssh_config: str = None, aws_env: str = None):
13
13
  """Initialize cloudx-proxy setup.
14
14
 
15
15
  Args:
16
16
  profile: AWS profile name (default: "vscode")
17
17
  ssh_key: SSH key name (default: "vscode")
18
+ ssh_config: SSH config file path (default: None, uses ~/.ssh/vscode/config)
18
19
  aws_env: AWS environment directory (default: None)
19
20
  """
20
21
  self.profile = profile
21
22
  self.ssh_key = ssh_key
22
23
  self.aws_env = aws_env
23
24
  self.home_dir = str(Path.home())
24
- self.ssh_dir = Path(self.home_dir) / ".ssh" / "vscode"
25
- self.ssh_config_file = self.ssh_dir / "config"
25
+
26
+ # Set up ssh config paths based on provided config or default
27
+ if ssh_config:
28
+ self.ssh_config_file = Path(os.path.expanduser(ssh_config))
29
+ self.ssh_dir = self.ssh_config_file.parent
30
+ else:
31
+ self.ssh_dir = Path(self.home_dir) / ".ssh" / "vscode"
32
+ self.ssh_config_file = self.ssh_dir / "config"
33
+
26
34
  self.ssh_key_file = self.ssh_dir / f"{ssh_key}"
27
35
  self.default_env = None
28
36
 
@@ -330,8 +338,10 @@ Host cloudx-{cloudx_env}-{hostname}
330
338
  if f"Host cloudx-{cloudx_env}-*" in current_config:
331
339
  self.print_status(f"Found existing config for cloudx-{cloudx_env}-*", True, 2)
332
340
  choice = self.prompt(
333
- "Would you like to \n 1: override the existing config\n "
334
- " 2: add settings to the specific host entry?\nSelect an option ",
341
+ "Would you like to \n"
342
+ " 1: override the existing config\n"
343
+ " 2: add settings to the specific host entry?\n"
344
+ "Select an option",
335
345
  "1"
336
346
  )
337
347
  if choice == "2":
@@ -358,6 +368,7 @@ Host cloudx-{cloudx_env}-{hostname}
358
368
  # Create base config
359
369
  self.print_status(f"Creating new config for cloudx-{cloudx_env}-*", None, 2)
360
370
  # Build ProxyCommand with only non-default parameters
371
+ # We don't need to include ssh_config here as SSH will handle that through the config
361
372
  proxy_command = "uvx cloudx-proxy connect %h %p"
362
373
  if self.profile != "vscode":
363
374
  proxy_command += f" --profile {self.profile}"
@@ -420,7 +431,9 @@ Host cloudx-{cloudx_env}-{hostname}
420
431
  f.write(host_entry)
421
432
  self.print_status("Host entry added", True, 2)
422
433
 
423
- # Ensure main SSH config includes our config
434
+ # Handle system SSH config integration
435
+ system_config_path = Path(self.home_dir) / ".ssh" / "config"
436
+
424
437
  # Ensure ~/.ssh directory has proper permissions
425
438
  ssh_parent_dir = Path(self.home_dir) / ".ssh"
426
439
  if not ssh_parent_dir.exists():
@@ -428,36 +441,41 @@ Host cloudx-{cloudx_env}-{hostname}
428
441
  self.print_status(f"Created SSH directory: {ssh_parent_dir}", True, 2)
429
442
  self._set_directory_permissions(ssh_parent_dir)
430
443
 
431
- main_config = Path(self.home_dir) / ".ssh" / "config"
432
- include_line = f"Include {self.ssh_config_file}\n"
433
-
434
- if main_config.exists():
435
- content = main_config.read_text()
436
- if include_line not in content:
437
- with open(main_config, 'a') as f:
438
- f.write(f"\n{include_line}")
439
- self.print_status("Added include line to main SSH config", True, 2)
440
- else:
441
- self.print_status("Main SSH config already includes our config", True, 2)
442
-
443
- # Set correct permissions on main config file
444
- if platform.system() != 'Windows':
445
- import stat
446
- main_config.chmod(stat.S_IRUSR | stat.S_IWUSR) # 600 permissions
447
- self.print_status("Set main config file permissions to 600", True, 2)
444
+ # If our config file is the system config, we're done
445
+ if self.ssh_config_file.samefile(system_config_path) if self.ssh_config_file.exists() and system_config_path.exists() else str(self.ssh_config_file) == str(system_config_path):
446
+ self.print_status("Using system SSH config directly, no Include needed", True, 2)
448
447
  else:
449
- main_config.write_text(include_line)
450
- self.print_status("Created main SSH config with include line", True, 2)
448
+ # Otherwise, make sure the system config includes our config file
449
+ include_line = f"Include {self.ssh_config_file}\n"
451
450
 
452
- # Set correct permissions on newly created main config file
453
- if platform.system() != 'Windows':
454
- import stat
455
- main_config.chmod(stat.S_IRUSR | stat.S_IWUSR) # 600 permissions
456
- self.print_status("Set main config file permissions to 600", True, 2)
451
+ if system_config_path.exists():
452
+ content = system_config_path.read_text()
453
+ if include_line not in content:
454
+ with open(system_config_path, 'a') as f:
455
+ f.write(f"\n{include_line}")
456
+ self.print_status("Added include line to system SSH config", True, 2)
457
+ else:
458
+ self.print_status("System SSH config already includes our config", True, 2)
459
+
460
+ # Set correct permissions on system config file
461
+ if platform.system() != 'Windows':
462
+ import stat
463
+ system_config_path.chmod(stat.S_IRUSR | stat.S_IWUSR) # 600 permissions
464
+ self.print_status("Set system config file permissions to 600", True, 2)
465
+ else:
466
+ system_config_path.write_text(include_line)
467
+ self.print_status("Created system SSH config with include line", True, 2)
468
+
469
+ # Set correct permissions on newly created system config file
470
+ if platform.system() != 'Windows':
471
+ import stat
472
+ system_config_path.chmod(stat.S_IRUSR | stat.S_IWUSR) # 600 permissions
473
+ self.print_status("Set system config file permissions to 600", True, 2)
457
474
 
458
475
  self.print_status("SSH configuration summary:", None)
459
- self.print_status(f"Main config: {main_config}", None, 2)
476
+ self.print_status(f"System config: {system_config_path}", None, 2)
460
477
  self.print_status(f"cloudx-proxy config: {self.ssh_config_file}", None, 2)
478
+ self.print_status(f"SSH key directory: {self.ssh_dir}", None, 2)
461
479
  self.print_status(f"Connect using: ssh cloudx-{cloudx_env}-{hostname}", None, 2)
462
480
 
463
481
  return True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cloudx-proxy
3
- Version: 0.3.14
3
+ Version: 0.3.15
4
4
  Summary: SSH proxy command to connect VSCode with Cloud9/CloudX instance using AWS Systems Manager
5
5
  Author-email: easytocloud <info@easytocloud.com>
6
6
  License: MIT License
@@ -0,0 +1,11 @@
1
+ cloudx_proxy/__init__.py,sha256=ZZ2O_m9OFJm18AxMSuYJt4UjSuSqyJlYRaZMoets498,61
2
+ cloudx_proxy/_version.py,sha256=HSn5cGZLA_vnXREa9sRtSYCA5Ii9CJlQbi1YMzsfUGM,513
3
+ cloudx_proxy/cli.py,sha256=tP-Ftf2VNKtaiu26x5nDKCMZOPKoa4XCNDd5-okoE4s,3827
4
+ cloudx_proxy/core.py,sha256=iHloywyiDcWRXzFxgX0TdcOPHujW2u83WUMllk4m9Es,7588
5
+ cloudx_proxy/setup.py,sha256=zZMMGAAQMqXlfVJ8_M4f5-SEcYqsFQ82kQv18ikdta0,25409
6
+ cloudx_proxy-0.3.15.dist-info/LICENSE,sha256=i7P2OR4zsJYsMWcCUDe_B9ZfGi9bU0K5I2nKfDrW_N8,1068
7
+ cloudx_proxy-0.3.15.dist-info/METADATA,sha256=qOT0s-RuqhXnU69PHxWELyeBKNgluZyHpO-R6O5d2q8,14038
8
+ cloudx_proxy-0.3.15.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
9
+ cloudx_proxy-0.3.15.dist-info/entry_points.txt,sha256=HGt743N2lVlKd7O1qWq3C0aEHyS5PjPnxzDHh7hwtSg,54
10
+ cloudx_proxy-0.3.15.dist-info/top_level.txt,sha256=2wtEote1db21j-VvkCJFfT-dLlauuG5indjggYh3xDg,13
11
+ cloudx_proxy-0.3.15.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- cloudx_proxy/__init__.py,sha256=ZZ2O_m9OFJm18AxMSuYJt4UjSuSqyJlYRaZMoets498,61
2
- cloudx_proxy/_version.py,sha256=dAYECGus8vEags4_X66QYJmiBFCY-yJJXDyexsFv72w,513
3
- cloudx_proxy/cli.py,sha256=7wi00p5CUl0Dt8huMEkP85SWgA_vzcoCzch0wctvqHk,3488
4
- cloudx_proxy/core.py,sha256=XQbVlPaqQQ352Ao_JJlN-PpqIdQtSBec0lNRB1s0JSk,7288
5
- cloudx_proxy/setup.py,sha256=Ing3UnTG_zeMZAcNI3SQbmTJzrY1UWUHUbu6UT14lao,24178
6
- cloudx_proxy-0.3.14.dist-info/LICENSE,sha256=i7P2OR4zsJYsMWcCUDe_B9ZfGi9bU0K5I2nKfDrW_N8,1068
7
- cloudx_proxy-0.3.14.dist-info/METADATA,sha256=qvR4_o1puGZ2WNjb0Y5GLW8Ff2aX_IH7k8YPZx9-ORM,14038
8
- cloudx_proxy-0.3.14.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
9
- cloudx_proxy-0.3.14.dist-info/entry_points.txt,sha256=HGt743N2lVlKd7O1qWq3C0aEHyS5PjPnxzDHh7hwtSg,54
10
- cloudx_proxy-0.3.14.dist-info/top_level.txt,sha256=2wtEote1db21j-VvkCJFfT-dLlauuG5indjggYh3xDg,13
11
- cloudx_proxy-0.3.14.dist-info/RECORD,,