0
# SSH Key Management
1
2
Operations for managing SSH public keys associated with Cloud Shell environments, enabling secure SSH connections to running environments.
3
4
## Capabilities
5
6
### Add Public Key
7
8
Add an SSH public key to a Cloud Shell environment (long-running operation).
9
10
```python { .api }
11
def add_public_key(
12
self,
13
request: Optional[Union[cloudshell.AddPublicKeyRequest, dict]] = None,
14
*,
15
retry: OptionalRetry = gapic_v1.method.DEFAULT,
16
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
17
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
18
) -> operation.Operation:
19
"""
20
Add public SSH key to environment. This is a long-running operation.
21
22
Args:
23
request: AddPublicKeyRequest object or dict
24
retry: Retry configuration for the request
25
timeout: Timeout for the request
26
metadata: Additional metadata to send with the request
27
28
Returns:
29
Long-running operation that resolves to AddPublicKeyResponse
30
31
Raises:
32
google.api_core.exceptions.GoogleAPICallError: API call failed
33
google.api_core.exceptions.InvalidArgument: Invalid SSH key format
34
"""
35
```
36
37
### Remove Public Key
38
39
Remove an SSH public key from a Cloud Shell environment (long-running operation).
40
41
```python { .api }
42
def remove_public_key(
43
self,
44
request: Optional[Union[cloudshell.RemovePublicKeyRequest, dict]] = None,
45
*,
46
retry: OptionalRetry = gapic_v1.method.DEFAULT,
47
timeout: Union[float, object] = gapic_v1.method.DEFAULT,
48
metadata: Sequence[Tuple[str, Union[str, bytes]]] = (),
49
) -> operation.Operation:
50
"""
51
Remove public SSH key from environment. This is a long-running operation.
52
53
Args:
54
request: RemovePublicKeyRequest object or dict
55
retry: Retry configuration for the request
56
timeout: Timeout for the request
57
metadata: Additional metadata to send with the request
58
59
Returns:
60
Long-running operation that resolves to RemovePublicKeyResponse
61
62
Raises:
63
google.api_core.exceptions.GoogleAPICallError: API call failed
64
google.api_core.exceptions.NotFound: SSH key not found
65
"""
66
```
67
68
## Request Types
69
70
### AddPublicKeyRequest
71
72
```python { .api }
73
class AddPublicKeyRequest(proto.Message):
74
"""Request to add SSH public key to environment."""
75
76
environment: str # Environment name (e.g., users/me/environments/default)
77
key: str # SSH public key in supported format (OpenSSH format)
78
```
79
80
### RemovePublicKeyRequest
81
82
```python { .api }
83
class RemovePublicKeyRequest(proto.Message):
84
"""Request to remove SSH public key from environment."""
85
86
environment: str # Environment name (e.g., users/me/environments/default)
87
key: str # SSH public key to remove (must match exactly)
88
```
89
90
## Response Types
91
92
### AddPublicKeyResponse
93
94
```python { .api }
95
class AddPublicKeyResponse(proto.Message):
96
"""Response from add public key operation."""
97
98
key: str # Key that was added (normalized format)
99
```
100
101
### RemovePublicKeyResponse
102
103
```python { .api }
104
class RemovePublicKeyResponse(proto.Message):
105
"""Response from remove public key operation."""
106
# Empty message
107
```
108
109
## Operation Metadata Types
110
111
### AddPublicKeyMetadata
112
113
```python { .api }
114
class AddPublicKeyMetadata(proto.Message):
115
"""Operation metadata for add key operations."""
116
# Empty message
117
```
118
119
### RemovePublicKeyMetadata
120
121
```python { .api }
122
class RemovePublicKeyMetadata(proto.Message):
123
"""Operation metadata for remove key operations."""
124
# Empty message
125
```
126
127
## Usage Examples
128
129
### Add SSH Public Key
130
131
```python
132
from google.cloud.shell import CloudShellServiceClient, AddPublicKeyRequest
133
134
client = CloudShellServiceClient()
135
136
# Read SSH public key from file
137
with open("~/.ssh/id_rsa.pub", "r") as f:
138
public_key = f.read().strip()
139
140
request = AddPublicKeyRequest(
141
environment="users/me/environments/default",
142
key=public_key
143
)
144
145
operation = client.add_public_key(request=request)
146
print(f"Operation name: {operation.name}")
147
148
# Wait for completion
149
response = operation.result()
150
print(f"Added key: {response.key[:50]}...")
151
```
152
153
### Remove SSH Public Key
154
155
```python
156
from google.cloud.shell import CloudShellServiceClient, RemovePublicKeyRequest
157
158
client = CloudShellServiceClient()
159
160
# Get current environment to see existing keys
161
environment = client.get_environment(
162
name="users/me/environments/default"
163
)
164
165
if environment.public_keys:
166
# Remove the first key
167
key_to_remove = environment.public_keys[0]
168
169
request = RemovePublicKeyRequest(
170
environment="users/me/environments/default",
171
key=key_to_remove
172
)
173
174
operation = client.remove_public_key(request=request)
175
operation.result()
176
print("SSH key removed successfully")
177
else:
178
print("No SSH keys to remove")
179
```
180
181
### Manage Multiple SSH Keys
182
183
```python
184
from google.cloud.shell import CloudShellServiceClient
185
import os
186
import glob
187
188
client = CloudShellServiceClient()
189
190
# Add multiple SSH keys from ~/.ssh directory
191
ssh_dir = os.path.expanduser("~/.ssh")
192
pub_key_files = glob.glob(os.path.join(ssh_dir, "*.pub"))
193
194
for key_file in pub_key_files:
195
with open(key_file, "r") as f:
196
public_key = f.read().strip()
197
198
operation = client.add_public_key(
199
environment="users/me/environments/default",
200
key=public_key
201
)
202
203
try:
204
response = operation.result(timeout=60)
205
print(f"Added key from {key_file}")
206
except Exception as e:
207
print(f"Failed to add key from {key_file}: {e}")
208
```
209
210
### List Current SSH Keys
211
212
```python
213
from google.cloud.shell import CloudShellServiceClient
214
215
client = CloudShellServiceClient()
216
217
environment = client.get_environment(
218
name="users/me/environments/default"
219
)
220
221
print(f"Environment has {len(environment.public_keys)} SSH keys:")
222
for i, key in enumerate(environment.public_keys):
223
# Show first and last 20 characters of each key
224
key_preview = f"{key[:20]}...{key[-20:]}" if len(key) > 40 else key
225
print(f" {i+1}. {key_preview}")
226
```
227
228
### Async SSH Key Management
229
230
```python
231
import asyncio
232
from google.cloud.shell import CloudShellServiceAsyncClient, AddPublicKeyRequest
233
234
async def manage_ssh_keys():
235
async with CloudShellServiceAsyncClient() as client:
236
# Add key
237
with open("~/.ssh/id_ed25519.pub", "r") as f:
238
public_key = f.read().strip()
239
240
add_operation = await client.add_public_key(
241
AddPublicKeyRequest(
242
environment="users/me/environments/default",
243
key=public_key
244
)
245
)
246
247
response = await add_operation.result()
248
print(f"Added SSH key: {response.key[:50]}...")
249
250
# Verify key was added
251
environment = await client.get_environment(
252
name="users/me/environments/default"
253
)
254
print(f"Environment now has {len(environment.public_keys)} SSH keys")
255
256
asyncio.run(manage_ssh_keys())
257
```
258
259
### Error Handling
260
261
```python
262
from google.cloud.shell import CloudShellServiceClient, AddPublicKeyRequest
263
from google.api_core import exceptions
264
265
client = CloudShellServiceClient()
266
267
try:
268
# Try to add invalid SSH key
269
operation = client.add_public_key(
270
AddPublicKeyRequest(
271
environment="users/me/environments/default",
272
key="invalid-ssh-key-format"
273
)
274
)
275
response = operation.result()
276
except exceptions.InvalidArgument as e:
277
print(f"Invalid SSH key format: {e}")
278
except exceptions.GoogleAPICallError as e:
279
print(f"API call failed: {e}")
280
```
281
282
### SSH Key Formats
283
284
The Google Cloud Shell API supports SSH public keys in OpenSSH format. Common key types include:
285
286
#### RSA Key Example
287
```
288
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7YjmZH3+l8f... user@example.com
289
```
290
291
#### Ed25519 Key Example
292
```
293
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILhLxNd8s6+m... user@example.com
294
```
295
296
#### ECDSA Key Example
297
```
298
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTY... user@example.com
299
```
300
301
### Best Practices
302
303
1. **Key Generation**: Generate strong SSH keys using `ssh-keygen -t ed25519` or `ssh-keygen -t rsa -b 4096`
304
2. **Key Management**: Regularly rotate SSH keys and remove unused keys
305
3. **Error Handling**: Always handle potential errors like invalid key formats or network failures
306
4. **Environment State**: Check environment state before managing keys - some operations may require the environment to be running
307
5. **Key Persistence**: SSH keys persist across environment restarts but may be removed when environments are deleted