cloudx-proxy 0.3.3__tar.gz → 0.3.5__tar.gz
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-0.3.3 → cloudx_proxy-0.3.5}/CHANGELOG.md +9 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/PKG-INFO +60 -32
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/README.md +59 -31
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy/_version.py +2 -2
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy/setup.py +81 -33
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/PKG-INFO +60 -32
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/.github/workflows/release.yml +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/.gitignore +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/.releaserc +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/CONTRIBUTING.md +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/LICENSE +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy/__init__.py +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy/cli.py +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy/core.py +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/SOURCES.txt +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/dependency_links.txt +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/entry_points.txt +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/requires.txt +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/cloudx_proxy.egg-info/top_level.txt +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/package.json +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/pyproject.toml +0 -0
- {cloudx_proxy-0.3.3 → cloudx_proxy-0.3.5}/setup.cfg +0 -0
@@ -1,3 +1,12 @@
|
|
1
|
+
## [0.3.5](https://github.com/easytocloud/cloudX-proxy/compare/v0.3.4...v0.3.5) (2025-02-11)
|
2
|
+
|
3
|
+
|
4
|
+
### Bug Fixes
|
5
|
+
|
6
|
+
* repaired 1Password integration and ssh perms ([69f6a24](https://github.com/easytocloud/cloudX-proxy/commit/69f6a249c941044c4dc689c787c12c1a0d0e093a))
|
7
|
+
|
8
|
+
## [0.3.4](https://github.com/easytocloud/cloudX-proxy/compare/v0.3.3...v0.3.4) (2025-02-09)
|
9
|
+
|
1
10
|
## [0.3.3](https://github.com/easytocloud/cloudX-proxy/compare/v0.3.2...v0.3.3) (2025-02-09)
|
2
11
|
|
3
12
|
## [0.3.2](https://github.com/easytocloud/cloudX-proxy/compare/v0.3.1...v0.3.2) (2025-02-09)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: cloudx-proxy
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.5
|
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
|
@@ -95,14 +95,9 @@ cloudX-proxy enables seamless SSH connections from VSCode to EC2 instances using
|
|
95
95
|
- Uses the SSH configuration to connect to instances
|
96
96
|
- Handles file synchronization and terminal sessions
|
97
97
|
|
98
|
-
##
|
98
|
+
## Installation
|
99
99
|
|
100
|
-
The proxy
|
101
|
-
- Starting/stopping EC2 instances
|
102
|
-
- Establishing SSM sessions
|
103
|
-
- Pushing SSH keys via EC2 Instance Connect
|
104
|
-
|
105
|
-
The proxy supports easytocloud's AWS profile organizer for managing multiple AWS environments. You can store your AWS configuration and credentials in `~/.aws/aws-envs/<environment>` directories and use the `--aws-env` option to specify which environment to use.
|
100
|
+
The cloudX-proxy package is available on PyPI and can run using uvx without explicit installation.
|
106
101
|
|
107
102
|
## Setup
|
108
103
|
|
@@ -122,7 +117,7 @@ uvx cloudx-proxy setup --aws-env prod
|
|
122
117
|
The setup command will:
|
123
118
|
|
124
119
|
1. Configure AWS Profile:
|
125
|
-
- Creates/validates AWS profile
|
120
|
+
- Creates/validates AWS profile for IAM user in cloudX-{env}-{user} format
|
126
121
|
- Supports AWS environment directories via --aws-env
|
127
122
|
- Uses aws configure for credential input
|
128
123
|
|
@@ -145,7 +140,40 @@ The setup command will:
|
|
145
140
|
|
146
141
|
### SSH Configuration
|
147
142
|
|
148
|
-
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager.
|
143
|
+
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager. For example, running:
|
144
|
+
|
145
|
+
```bash
|
146
|
+
uvx cloudx-proxy setup --profile myprofile --ssh-key mykey
|
147
|
+
```
|
148
|
+
|
149
|
+
Will create a configuration like this:
|
150
|
+
|
151
|
+
```
|
152
|
+
# Base environment config (created once per environment)
|
153
|
+
Host cloudx-dev-*
|
154
|
+
User ec2-user
|
155
|
+
IdentityFile ~/.ssh/vscode/mykey
|
156
|
+
ProxyCommand uvx cloudx-proxy connect %h %p --profile myprofile --ssh-key mykey
|
157
|
+
|
158
|
+
# Host entry (added for specific instance)
|
159
|
+
Host cloudx-dev-myserver
|
160
|
+
HostName i-0123456789abcdef0
|
161
|
+
```
|
162
|
+
|
163
|
+
Allowing the user to:
|
164
|
+
|
165
|
+
```bash
|
166
|
+
ssh cloudx-dev-myserver
|
167
|
+
scp cloudx-dev-myserver:/path/to/file /local/path/to/file
|
168
|
+
```
|
169
|
+
without the need to provide any further credentials.
|
170
|
+
|
171
|
+
In these examples, ssh will use cloudx-proxy to connect to AWS with the `myprofile` credentials, allowing it to check the instance state and start the instance if it's stopped. Next cloudx-proxy will use `myprofile` to push the public part of the key `mykey` to the instance using SSM. Finally a tunnel is created between the local machine and the instance, using the SSM plugin, allowing SSH to connect to the instance using the private part of the `mykey` key.
|
172
|
+
|
173
|
+
VSCode will be able to connect to the instance using the same SSH configuration.
|
174
|
+
|
175
|
+
### SSH Configuration Details
|
176
|
+
The setup command creates:
|
149
177
|
|
150
178
|
1. A base configuration for each environment (cloudx-{env}-*) with:
|
151
179
|
- User and key settings
|
@@ -171,7 +199,7 @@ When adding new instances to an existing environment, you can choose to:
|
|
171
199
|
"remote.SSH.connectTimeout": 90
|
172
200
|
}
|
173
201
|
```
|
174
|
-
|
202
|
+
This extra long timeout is necessary to account for the time it takes to start the instance and establish the connection.
|
175
203
|
## Usage
|
176
204
|
|
177
205
|
### Command Line Options
|
@@ -239,28 +267,28 @@ Note: The connect command is typically used through the SSH ProxyCommand configu
|
|
239
267
|
5. VSCode will handle the rest, using cloudX-proxy to establish the connection
|
240
268
|
|
241
269
|
## AWS Permissions
|
270
|
+
### IAM User Permissions
|
242
271
|
|
243
|
-
The AWS user
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions.
|
272
|
+
The AWS IAM user has to be member of the AWS IAM Group that is created as part of the cloudX environment.
|
273
|
+
The group uses ABAC (Attribute Based Access Control) to allow access to the instances based on the tags.
|
274
|
+
The ABAC tag defaults to `cloudxuser` and should have the value of the username of the user that owns the instance.
|
275
|
+
|
276
|
+
Example:
|
277
|
+
- AWS IAM User `cloudx-dev-user1` is connecting to an instance with the tag `cloudxuser=cloudx-dev-user1`
|
278
|
+
|
279
|
+
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions. The user in the example is member of the `dev` group, part as part of the `cloudx-dev` environment.
|
280
|
+
|
281
|
+
The EC2 instance should have the tag `cloudxuser` with the value of the username of the user that is connecting to the instance. This is automatically set when the instance is created using the cloudX-instance product from Service Catalog in the AWS Console.
|
282
|
+
|
283
|
+
### EC2 Instance Permissions
|
284
|
+
|
285
|
+
The EC2 instance has a profile/role that provides enough permissions to allow the AWS SSM agent to connect to the instance, as well as
|
286
|
+
- CodeArtifact read only access, to use as a source for pip
|
287
|
+
- CodeCommit read only access, to pull code from the repository for installation
|
288
|
+
- Organizations read only access, to create aws sso configuration
|
289
|
+
- EC2 basic access, to allow the instance to introspect for tags and other metadata
|
290
|
+
|
291
|
+
These permissions are required to bootstrap the instance, so that after creation the instance can perform software installation and configuration without a user being present.
|
264
292
|
|
265
293
|
## Troubleshooting
|
266
294
|
|
@@ -45,14 +45,9 @@ cloudX-proxy enables seamless SSH connections from VSCode to EC2 instances using
|
|
45
45
|
- Uses the SSH configuration to connect to instances
|
46
46
|
- Handles file synchronization and terminal sessions
|
47
47
|
|
48
|
-
##
|
48
|
+
## Installation
|
49
49
|
|
50
|
-
The proxy
|
51
|
-
- Starting/stopping EC2 instances
|
52
|
-
- Establishing SSM sessions
|
53
|
-
- Pushing SSH keys via EC2 Instance Connect
|
54
|
-
|
55
|
-
The proxy supports easytocloud's AWS profile organizer for managing multiple AWS environments. You can store your AWS configuration and credentials in `~/.aws/aws-envs/<environment>` directories and use the `--aws-env` option to specify which environment to use.
|
50
|
+
The cloudX-proxy package is available on PyPI and can run using uvx without explicit installation.
|
56
51
|
|
57
52
|
## Setup
|
58
53
|
|
@@ -72,7 +67,7 @@ uvx cloudx-proxy setup --aws-env prod
|
|
72
67
|
The setup command will:
|
73
68
|
|
74
69
|
1. Configure AWS Profile:
|
75
|
-
- Creates/validates AWS profile
|
70
|
+
- Creates/validates AWS profile for IAM user in cloudX-{env}-{user} format
|
76
71
|
- Supports AWS environment directories via --aws-env
|
77
72
|
- Uses aws configure for credential input
|
78
73
|
|
@@ -95,7 +90,40 @@ The setup command will:
|
|
95
90
|
|
96
91
|
### SSH Configuration
|
97
92
|
|
98
|
-
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager.
|
93
|
+
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager. For example, running:
|
94
|
+
|
95
|
+
```bash
|
96
|
+
uvx cloudx-proxy setup --profile myprofile --ssh-key mykey
|
97
|
+
```
|
98
|
+
|
99
|
+
Will create a configuration like this:
|
100
|
+
|
101
|
+
```
|
102
|
+
# Base environment config (created once per environment)
|
103
|
+
Host cloudx-dev-*
|
104
|
+
User ec2-user
|
105
|
+
IdentityFile ~/.ssh/vscode/mykey
|
106
|
+
ProxyCommand uvx cloudx-proxy connect %h %p --profile myprofile --ssh-key mykey
|
107
|
+
|
108
|
+
# Host entry (added for specific instance)
|
109
|
+
Host cloudx-dev-myserver
|
110
|
+
HostName i-0123456789abcdef0
|
111
|
+
```
|
112
|
+
|
113
|
+
Allowing the user to:
|
114
|
+
|
115
|
+
```bash
|
116
|
+
ssh cloudx-dev-myserver
|
117
|
+
scp cloudx-dev-myserver:/path/to/file /local/path/to/file
|
118
|
+
```
|
119
|
+
without the need to provide any further credentials.
|
120
|
+
|
121
|
+
In these examples, ssh will use cloudx-proxy to connect to AWS with the `myprofile` credentials, allowing it to check the instance state and start the instance if it's stopped. Next cloudx-proxy will use `myprofile` to push the public part of the key `mykey` to the instance using SSM. Finally a tunnel is created between the local machine and the instance, using the SSM plugin, allowing SSH to connect to the instance using the private part of the `mykey` key.
|
122
|
+
|
123
|
+
VSCode will be able to connect to the instance using the same SSH configuration.
|
124
|
+
|
125
|
+
### SSH Configuration Details
|
126
|
+
The setup command creates:
|
99
127
|
|
100
128
|
1. A base configuration for each environment (cloudx-{env}-*) with:
|
101
129
|
- User and key settings
|
@@ -121,7 +149,7 @@ When adding new instances to an existing environment, you can choose to:
|
|
121
149
|
"remote.SSH.connectTimeout": 90
|
122
150
|
}
|
123
151
|
```
|
124
|
-
|
152
|
+
This extra long timeout is necessary to account for the time it takes to start the instance and establish the connection.
|
125
153
|
## Usage
|
126
154
|
|
127
155
|
### Command Line Options
|
@@ -189,28 +217,28 @@ Note: The connect command is typically used through the SSH ProxyCommand configu
|
|
189
217
|
5. VSCode will handle the rest, using cloudX-proxy to establish the connection
|
190
218
|
|
191
219
|
## AWS Permissions
|
220
|
+
### IAM User Permissions
|
192
221
|
|
193
|
-
The AWS user
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions.
|
222
|
+
The AWS IAM user has to be member of the AWS IAM Group that is created as part of the cloudX environment.
|
223
|
+
The group uses ABAC (Attribute Based Access Control) to allow access to the instances based on the tags.
|
224
|
+
The ABAC tag defaults to `cloudxuser` and should have the value of the username of the user that owns the instance.
|
225
|
+
|
226
|
+
Example:
|
227
|
+
- AWS IAM User `cloudx-dev-user1` is connecting to an instance with the tag `cloudxuser=cloudx-dev-user1`
|
228
|
+
|
229
|
+
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions. The user in the example is member of the `dev` group, part as part of the `cloudx-dev` environment.
|
230
|
+
|
231
|
+
The EC2 instance should have the tag `cloudxuser` with the value of the username of the user that is connecting to the instance. This is automatically set when the instance is created using the cloudX-instance product from Service Catalog in the AWS Console.
|
232
|
+
|
233
|
+
### EC2 Instance Permissions
|
234
|
+
|
235
|
+
The EC2 instance has a profile/role that provides enough permissions to allow the AWS SSM agent to connect to the instance, as well as
|
236
|
+
- CodeArtifact read only access, to use as a source for pip
|
237
|
+
- CodeCommit read only access, to pull code from the repository for installation
|
238
|
+
- Organizations read only access, to create aws sso configuration
|
239
|
+
- EC2 basic access, to allow the instance to introspect for tags and other metadata
|
240
|
+
|
241
|
+
These permissions are required to bootstrap the instance, so that after creation the instance can perform software installation and configuration without a user being present.
|
214
242
|
|
215
243
|
## Troubleshooting
|
216
244
|
|
@@ -2,6 +2,7 @@ import os
|
|
2
2
|
import time
|
3
3
|
import json
|
4
4
|
import subprocess
|
5
|
+
import platform
|
5
6
|
from pathlib import Path
|
6
7
|
from typing import Optional, Tuple
|
7
8
|
import boto3
|
@@ -142,16 +143,17 @@ class CloudXSetup:
|
|
142
143
|
|
143
144
|
if key_exists:
|
144
145
|
self.print_status(f"SSH key '{self.ssh_key}' exists", True, 2)
|
145
|
-
|
146
|
-
|
147
|
-
self.
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
if
|
152
|
-
self.
|
153
|
-
|
154
|
-
|
146
|
+
if platform.system() != 'Windows':
|
147
|
+
self.using_1password = self.prompt("Would you like to use 1Password SSH agent?", "N").lower() == 'y'
|
148
|
+
if self.using_1password:
|
149
|
+
self.print_status("Using 1Password SSH agent", True, 2)
|
150
|
+
else:
|
151
|
+
store_in_1password = self.prompt("Would you like to store the private key in 1Password?", "N").lower() == 'y'
|
152
|
+
if store_in_1password:
|
153
|
+
if self._store_key_in_1password():
|
154
|
+
self.print_status("Private key stored in 1Password", True, 2)
|
155
|
+
else:
|
156
|
+
self.print_status("Failed to store private key in 1Password", False, 2)
|
155
157
|
else:
|
156
158
|
self.print_status(f"Generating new SSH key '{self.ssh_key}'...", None, 2)
|
157
159
|
subprocess.run([
|
@@ -162,16 +164,17 @@ class CloudXSetup:
|
|
162
164
|
], check=True)
|
163
165
|
self.print_status("SSH key generated", True, 2)
|
164
166
|
|
165
|
-
|
166
|
-
|
167
|
-
self.
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
if
|
172
|
-
self.
|
173
|
-
|
174
|
-
|
167
|
+
if platform.system() != 'Windows':
|
168
|
+
self.using_1password = self.prompt("Would you like to use 1Password SSH agent?", "N").lower() == 'y'
|
169
|
+
if self.using_1password:
|
170
|
+
self.print_status("Using 1Password SSH agent", True, 2)
|
171
|
+
else:
|
172
|
+
store_in_1password = self.prompt("Would you like to store the private key in 1Password?", "N").lower() == 'y'
|
173
|
+
if store_in_1password:
|
174
|
+
if self._store_key_in_1password():
|
175
|
+
self.print_status("Private key stored in 1Password", True, 2)
|
176
|
+
else:
|
177
|
+
self.print_status("Failed to store private key in 1Password", False, 2)
|
175
178
|
|
176
179
|
return True
|
177
180
|
|
@@ -184,20 +187,51 @@ class CloudXSetup:
|
|
184
187
|
return False
|
185
188
|
|
186
189
|
def _store_key_in_1password(self) -> bool:
|
187
|
-
"""Store SSH private key in 1Password.
|
190
|
+
"""Store SSH private key in 1Password and configure SSH agent.
|
188
191
|
|
189
192
|
Returns:
|
190
193
|
bool: True if key was stored successfully
|
191
194
|
"""
|
192
195
|
try:
|
196
|
+
# Check if 1Password CLI is available
|
193
197
|
subprocess.run(['op', '--version'], check=True, capture_output=True)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
198
|
+
|
199
|
+
# Check if 1Password SSH agent is running
|
200
|
+
agent_sock = Path.home() / ".1password" / "agent.sock"
|
201
|
+
if platform.system() == 'Darwin':
|
202
|
+
agent_sock = Path.home() / "Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
203
|
+
|
204
|
+
if not agent_sock.exists():
|
205
|
+
self.print_status("1Password SSH agent not running. Please enable it in 1Password settings.", False, 2)
|
206
|
+
return False
|
207
|
+
|
208
|
+
print("Adding SSH key to 1Password SSH agent...")
|
209
|
+
try:
|
210
|
+
# First try to add to SSH agent
|
211
|
+
subprocess.run([
|
212
|
+
'op', 'ssh-add',
|
213
|
+
'--name', f'cloudx-proxy-{self.ssh_key}',
|
214
|
+
str(self.ssh_key_file)
|
215
|
+
], check=True)
|
216
|
+
|
217
|
+
# Read private key content before removing
|
218
|
+
with open(self.ssh_key_file, 'r') as f:
|
219
|
+
private_key = f.read()
|
220
|
+
|
221
|
+
# Store private key in 1Password as document for backup
|
222
|
+
subprocess.run([
|
223
|
+
'op', 'document', 'create',
|
224
|
+
'--title', f'cloudx-proxy SSH Key - {self.ssh_key}',
|
225
|
+
], input=private_key.encode(), check=True)
|
226
|
+
|
227
|
+
# Remove private key file but keep public key
|
228
|
+
os.remove(self.ssh_key_file)
|
229
|
+
self.print_status("Private key added to 1Password SSH agent and removed from disk", True, 2)
|
230
|
+
self.print_status("Backup copy stored in 1Password documents", True, 2)
|
231
|
+
return True
|
232
|
+
except subprocess.CalledProcessError as e:
|
233
|
+
self.print_status(f"Failed to add key to SSH agent: {e}", False, 2)
|
234
|
+
return False
|
201
235
|
except subprocess.CalledProcessError:
|
202
236
|
print("Error: 1Password CLI not installed or not signed in.")
|
203
237
|
return False
|
@@ -229,13 +263,19 @@ Host cloudx-{cloudx_env}-{hostname}
|
|
229
263
|
HostName {instance_id}
|
230
264
|
User ec2-user
|
231
265
|
"""
|
232
|
-
if self.using_1password:
|
233
|
-
|
266
|
+
if self.using_1password and platform.system() != 'Windows':
|
267
|
+
# Use platform-specific agent socket path
|
268
|
+
if platform.system() == 'Darwin': # macOS
|
269
|
+
agent_sock = "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
270
|
+
else: # Linux
|
271
|
+
agent_sock = "~/.1password/agent.sock"
|
272
|
+
host_entry += f""" IdentityAgent {agent_sock}
|
234
273
|
IdentityFile {self.ssh_key_file}.pub
|
235
274
|
IdentitiesOnly yes
|
236
275
|
"""
|
237
276
|
else:
|
238
277
|
host_entry += f""" IdentityFile {self.ssh_key_file}
|
278
|
+
IdentitiesOnly yes
|
239
279
|
"""
|
240
280
|
host_entry += f""" ProxyCommand {proxy_command}
|
241
281
|
"""
|
@@ -343,14 +383,22 @@ Host cloudx-{cloudx_env}-{hostname}
|
|
343
383
|
Host cloudx-{cloudx_env}-*
|
344
384
|
User ec2-user
|
345
385
|
"""
|
346
|
-
# Add
|
347
|
-
if self.using_1password:
|
348
|
-
|
386
|
+
# Add key configuration
|
387
|
+
if self.using_1password and platform.system() != 'Windows':
|
388
|
+
# Use platform-specific agent socket path
|
389
|
+
if platform.system() == 'Darwin': # macOS
|
390
|
+
agent_sock = "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"
|
391
|
+
else: # Linux
|
392
|
+
agent_sock = "~/.1password/agent.sock"
|
393
|
+
base_config += f""" IdentityAgent {agent_sock}
|
349
394
|
IdentityFile {self.ssh_key_file}.pub
|
350
395
|
IdentitiesOnly yes
|
396
|
+
|
351
397
|
"""
|
352
398
|
else:
|
353
399
|
base_config += f""" IdentityFile {self.ssh_key_file}
|
400
|
+
IdentitiesOnly yes
|
401
|
+
|
354
402
|
"""
|
355
403
|
# Add ProxyCommand
|
356
404
|
base_config += f""" ProxyCommand {proxy_command}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: cloudx-proxy
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.5
|
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
|
@@ -95,14 +95,9 @@ cloudX-proxy enables seamless SSH connections from VSCode to EC2 instances using
|
|
95
95
|
- Uses the SSH configuration to connect to instances
|
96
96
|
- Handles file synchronization and terminal sessions
|
97
97
|
|
98
|
-
##
|
98
|
+
## Installation
|
99
99
|
|
100
|
-
The proxy
|
101
|
-
- Starting/stopping EC2 instances
|
102
|
-
- Establishing SSM sessions
|
103
|
-
- Pushing SSH keys via EC2 Instance Connect
|
104
|
-
|
105
|
-
The proxy supports easytocloud's AWS profile organizer for managing multiple AWS environments. You can store your AWS configuration and credentials in `~/.aws/aws-envs/<environment>` directories and use the `--aws-env` option to specify which environment to use.
|
100
|
+
The cloudX-proxy package is available on PyPI and can run using uvx without explicit installation.
|
106
101
|
|
107
102
|
## Setup
|
108
103
|
|
@@ -122,7 +117,7 @@ uvx cloudx-proxy setup --aws-env prod
|
|
122
117
|
The setup command will:
|
123
118
|
|
124
119
|
1. Configure AWS Profile:
|
125
|
-
- Creates/validates AWS profile
|
120
|
+
- Creates/validates AWS profile for IAM user in cloudX-{env}-{user} format
|
126
121
|
- Supports AWS environment directories via --aws-env
|
127
122
|
- Uses aws configure for credential input
|
128
123
|
|
@@ -145,7 +140,40 @@ The setup command will:
|
|
145
140
|
|
146
141
|
### SSH Configuration
|
147
142
|
|
148
|
-
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager.
|
143
|
+
The setup command configures SSH to use cloudX-proxy as a ProxyCommand, enabling seamless connections through AWS Systems Manager. For example, running:
|
144
|
+
|
145
|
+
```bash
|
146
|
+
uvx cloudx-proxy setup --profile myprofile --ssh-key mykey
|
147
|
+
```
|
148
|
+
|
149
|
+
Will create a configuration like this:
|
150
|
+
|
151
|
+
```
|
152
|
+
# Base environment config (created once per environment)
|
153
|
+
Host cloudx-dev-*
|
154
|
+
User ec2-user
|
155
|
+
IdentityFile ~/.ssh/vscode/mykey
|
156
|
+
ProxyCommand uvx cloudx-proxy connect %h %p --profile myprofile --ssh-key mykey
|
157
|
+
|
158
|
+
# Host entry (added for specific instance)
|
159
|
+
Host cloudx-dev-myserver
|
160
|
+
HostName i-0123456789abcdef0
|
161
|
+
```
|
162
|
+
|
163
|
+
Allowing the user to:
|
164
|
+
|
165
|
+
```bash
|
166
|
+
ssh cloudx-dev-myserver
|
167
|
+
scp cloudx-dev-myserver:/path/to/file /local/path/to/file
|
168
|
+
```
|
169
|
+
without the need to provide any further credentials.
|
170
|
+
|
171
|
+
In these examples, ssh will use cloudx-proxy to connect to AWS with the `myprofile` credentials, allowing it to check the instance state and start the instance if it's stopped. Next cloudx-proxy will use `myprofile` to push the public part of the key `mykey` to the instance using SSM. Finally a tunnel is created between the local machine and the instance, using the SSM plugin, allowing SSH to connect to the instance using the private part of the `mykey` key.
|
172
|
+
|
173
|
+
VSCode will be able to connect to the instance using the same SSH configuration.
|
174
|
+
|
175
|
+
### SSH Configuration Details
|
176
|
+
The setup command creates:
|
149
177
|
|
150
178
|
1. A base configuration for each environment (cloudx-{env}-*) with:
|
151
179
|
- User and key settings
|
@@ -171,7 +199,7 @@ When adding new instances to an existing environment, you can choose to:
|
|
171
199
|
"remote.SSH.connectTimeout": 90
|
172
200
|
}
|
173
201
|
```
|
174
|
-
|
202
|
+
This extra long timeout is necessary to account for the time it takes to start the instance and establish the connection.
|
175
203
|
## Usage
|
176
204
|
|
177
205
|
### Command Line Options
|
@@ -239,28 +267,28 @@ Note: The connect command is typically used through the SSH ProxyCommand configu
|
|
239
267
|
5. VSCode will handle the rest, using cloudX-proxy to establish the connection
|
240
268
|
|
241
269
|
## AWS Permissions
|
270
|
+
### IAM User Permissions
|
242
271
|
|
243
|
-
The AWS user
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions.
|
272
|
+
The AWS IAM user has to be member of the AWS IAM Group that is created as part of the cloudX environment.
|
273
|
+
The group uses ABAC (Attribute Based Access Control) to allow access to the instances based on the tags.
|
274
|
+
The ABAC tag defaults to `cloudxuser` and should have the value of the username of the user that owns the instance.
|
275
|
+
|
276
|
+
Example:
|
277
|
+
- AWS IAM User `cloudx-dev-user1` is connecting to an instance with the tag `cloudxuser=cloudx-dev-user1`
|
278
|
+
|
279
|
+
Note: This user should be created using the cloudX-user product from Service Catalog in the AWS Console. This assures proper permissions and naming conventions. The user in the example is member of the `dev` group, part as part of the `cloudx-dev` environment.
|
280
|
+
|
281
|
+
The EC2 instance should have the tag `cloudxuser` with the value of the username of the user that is connecting to the instance. This is automatically set when the instance is created using the cloudX-instance product from Service Catalog in the AWS Console.
|
282
|
+
|
283
|
+
### EC2 Instance Permissions
|
284
|
+
|
285
|
+
The EC2 instance has a profile/role that provides enough permissions to allow the AWS SSM agent to connect to the instance, as well as
|
286
|
+
- CodeArtifact read only access, to use as a source for pip
|
287
|
+
- CodeCommit read only access, to pull code from the repository for installation
|
288
|
+
- Organizations read only access, to create aws sso configuration
|
289
|
+
- EC2 basic access, to allow the instance to introspect for tags and other metadata
|
290
|
+
|
291
|
+
These permissions are required to bootstrap the instance, so that after creation the instance can perform software installation and configuration without a user being present.
|
264
292
|
|
265
293
|
## Troubleshooting
|
266
294
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|