Skip to content

Commit 9886d84

Browse files
feat(stellar): Add Google Cloud KMS signer support (#481)
Co-authored-by: Dylan Kilkenny <[email protected]>
1 parent 5398adf commit 9886d84

File tree

13 files changed

+1467
-67
lines changed

13 files changed

+1467
-67
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ The repository includes several ready-to-use examples to help you get started wi
6161
| [`evm-turnkey-signer`](./examples/evm-turnkey-signer/) | Using Turnkey Signer for EVM secure signing |
6262
| [`solana-turnkey-signer`](./examples/solana-turnkey-signer/) | Using Turnkey Signer for Solana secure signing |
6363
| [`solana-google-cloud-kms-signer`](./examples/solana-google-cloud-kms-signer/) | Using Google Cloud KMS Signer for Solana secure signing |
64+
| [`stellar-gcp-kms-signer`](./examples/stellar-gcp-kms-signer/) | Using Google Cloud KMS Signer for Stellar secure signing |
6465
| [`evm-cdp-signer`](./examples/evm-cdp-signer/) | Using CDP Signer for EVM secure signing |
6566
| [`network-configuration-config-file`](./examples/network-configuration-config-file/) | Using Custom network configuration via config file |
6667
| [`network-configuration-json-file`](./examples/network-configuration-json-file/) | Using Custom network configuration via json file |

docs/modules/ROOT/pages/signers.adoc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ The following table shows which signer types are compatible with each network ty
7070
|`google_cloud_kms`
7171
|✅ Supported
7272
|✅ Supported
73-
|❌ Not supported
73+
|✅ Supported
7474

7575
|`aws_kms`
7676
|✅ Supported
@@ -89,9 +89,9 @@ The following table shows which signer types are compatible with each network ty
8989
9090
- **EVM Networks**: Use secp256k1 cryptography. Most signers support EVM networks with proper key generation.
9191
- **Solana Networks**: Use ed25519 cryptography. Ensure your signer supports ed25519 key generation and signing.
92-
- **Stellar Networks**: Use ed25519 cryptography with specific Stellar requirements. Limited signer support due to network-specific implementation requirements.
92+
- **Stellar Networks**: Use ed25519 cryptography with specific Stellar requirements. Currently supported by local and Google Cloud KMS signers.
9393
- **AWS KMS**: Currently optimized for EVM networks with secp256k1 support.
94-
- **Google Cloud KMS**: Supports both secp256k1 (EVM) and ed25519 (Solana) key types.
94+
- **Google Cloud KMS**: Supports secp256k1 (EVM) and ed25519 (Solana, Stellar) key types.
9595
- **Turnkey**: Supports EVM and Solana networks with appropriate key management.
9696
====
9797

@@ -341,12 +341,17 @@ Uses Google Cloud Key Management Service for secure key operations.
341341

342342
[NOTE]
343343
====
344-
For EVM transaction signing, ensure your Google Cloud KMS key is created with:
344+
**Network-specific key requirements:**
345+
346+
For **EVM** transaction signing, ensure your Google Cloud KMS key is created with:
345347
- Protection level: HSM
346348
- Purpose: Asymmetric sign
347349
- Algorithm: "Elliptic Curve secp256k1 - SHA256 Digest"
348350
349-
This provides secp256k1 compatibility required for Ethereum transactions.
351+
For **Solana** and **Stellar** transaction signing, ensure your Google Cloud KMS key is created with:
352+
- Protection level: Software or HSM
353+
- Purpose: Asymmetric sign
354+
- Algorithm: "Elliptic Curve ED25519 Key"
350355
====
351356

352357
[source,json]

docs/modules/ROOT/pages/stellar.adoc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,17 @@ Soroban operations support different authorization modes:
469469
|Advanced: provide base64-encoded XDR entries. This allows you to provide pre-signed SorobanAuthorizationEntry objects for complex authorization scenarios. See the link:https://developers.stellar.org/docs/learn/smart-contract-internals/authorization[official Stellar documentation on authorization] for detailed information about SorobanAuthorizationEntries.
470470
|===
471471

472+
== Signer Support
473+
474+
Stellar networks support the following signer types:
475+
476+
- **Local Signer**: Uses encrypted keystore files (suitable for development)
477+
- **Google Cloud KMS**: Uses Google Cloud Key Management Service with ED25519 keys (recommended for production)
478+
479+
For detailed signer configuration, see the xref:signers.adoc[Signers Configuration] guide.
480+
481+
For a complete example of using Google Cloud KMS with Stellar, check out the link:https://github.com/OpenZeppelin/openzeppelin-relayer/tree/main/examples/stellar-gcp-kms-signer[stellar-gcp-kms-signer example].
482+
472483
== Security
473484

474485
- Do not expose the relayer directly to the public internet
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
REDIS_URL=redis://redis:6379
2+
API_KEY=your_api_key_here
3+
WEBHOOK_SIGNING_KEY=your_webhook_signing_key_here
4+
5+
# Google Cloud KMS Configuration
6+
# Extract these values from your service account JSON file
7+
GCP_PRIVATE_KEY_ID=your_private_key_id_from_service_account_json
8+
GCP_PRIVATE_KEY="-----BEGIN PRIVATE EXAMPLE KEY-----\nyour_private_key_here\n-----END PRIVATE EXAMPLE KEY-----\n"
9+
GCP_CLIENT_EMAIL=[email protected]
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Using Google Cloud KMS for Secure EVM Transaction Signing in OpenZeppelin Relayer
2+
3+
This example demonstrates how to use Google Cloud KMS hosted private key to securely sign Stellar transactions in OpenZeppelin Relayer.
4+
5+
## Prerequisites
6+
7+
1. A Google Cloud Platform account with KMS API enabled - [Get Started](https://cloud.google.com/kms)
8+
2. Rust and Cargo installed
9+
3. Git
10+
4. [Docker](https://docs.docker.com/get-docker/)
11+
5. [Docker Compose](https://docs.docker.com/compose/install/)
12+
13+
## Getting Started
14+
15+
### Step 1: Clone the Repository
16+
17+
Clone this repository to your local machine:
18+
19+
```bash
20+
git clone https://github.com/OpenZeppelin/openzeppelin-relayer
21+
cd openzeppelin-relayer
22+
```
23+
24+
### Step 2: Create KMS Key
25+
26+
1. Login to Google Cloud Console
27+
2. Navigate to Security -> Key Management
28+
3. Create a new key ring or use an existing one
29+
4. Click "Create Key" and choose the following options:
30+
1. Protection level: Software
31+
2. Purpose: Asymmetric sign
32+
3. Algorithm: Elliptic Curve ED25519 Key
33+
5. Take note of:
34+
- Project ID
35+
- Location (region)
36+
- Key ring ID
37+
- Key ID
38+
- Key version (usually 1 for new keys)
39+
40+
### Step 3: Setup Google Cloud Service Account
41+
42+
1. Go to IAM & Admin -> Service Accounts
43+
2. Create a new service account or use an existing one
44+
3. Grant the following roles:
45+
- Cloud KMS CryptoKey Signer
46+
- Cloud KMS CryptoKey Public Key Viewer
47+
4. Create and download a JSON key file for the service account
48+
5. Extract the following values from the JSON file:
49+
- `project_id`
50+
- `private_key_id`
51+
- `private_key` (PEM format)
52+
- `client_email`
53+
- `client_id`
54+
55+
### Step 4: Configure the Relayer Service
56+
57+
Create an environment file by copying the example:
58+
59+
```bash
60+
cp examples/stellar-gcp-kms-signer/.env.example examples/stellar-gcp-kms-signer/.env
61+
```
62+
63+
#### Populate Google Cloud KMS config
64+
65+
Edit the `config.json` file and update the following variables:
66+
67+
```json
68+
{
69+
"signers": [
70+
{
71+
"id": "gcp-kms-signer-stellar",
72+
"type": "google_cloud_kms",
73+
"config": {
74+
"service_account": {
75+
"project_id": "your-gcp-project-id",
76+
"private_key_id": {
77+
"type": "env",
78+
"value": "GCP_PRIVATE_KEY_ID"
79+
},
80+
"private_key": {
81+
"type": "env",
82+
"value": "GCP_PRIVATE_KEY"
83+
},
84+
"client_email": {
85+
"type": "env",
86+
"value": "GCP_CLIENT_EMAIL"
87+
},
88+
"client_id": "your-client-id"
89+
},
90+
"key": {
91+
"location": "us-west2",
92+
"key_ring_id": "your-key-ring",
93+
"key_id": "your-key-id",
94+
"key_version": 1
95+
}
96+
}
97+
}
98+
]
99+
}
100+
```
101+
102+
#### Populate Google Cloud KMS Credentials
103+
104+
Add these values to your `.env` file (extracted from the service account JSON):
105+
106+
```env
107+
GCP_PRIVATE_KEY_ID="private_key_id_from_service_account_json"
108+
GCP_PRIVATE_KEY="-----BEGIN PRIVATE EXAMPLE KEY-----\n...\n-----END PRIVATE EXAMPLE KEY-----\n"
109+
GCP_CLIENT_EMAIL="[email protected]"
110+
```
111+
112+
#### Generate Security Keys
113+
114+
Generate random keys for API authentication and webhook signing:
115+
116+
```bash
117+
# Generate API key
118+
cargo run --example generate_uuid
119+
120+
# Generate webhook signing key
121+
cargo run --example generate_uuid
122+
```
123+
124+
Add these to your `.env` file:
125+
126+
```env
127+
WEBHOOK_SIGNING_KEY=generated_webhook_key
128+
API_KEY=generated_api_key
129+
```
130+
131+
#### Configure Webhook URL
132+
133+
Update the `examples/stellar-gcp-kms-signer/config/config.json` file with your webhook configuration:
134+
135+
1. For testing, get a webhook URL from [Webhook.site](https://webhook.site)
136+
2. Update the config file:
137+
138+
```json
139+
{
140+
"notifications": [
141+
{
142+
"url": "your_webhook_url"
143+
}
144+
]
145+
}
146+
```
147+
148+
### Step 5: Run the Service
149+
150+
Start the service with Docker Compose:
151+
152+
```bash
153+
docker compose -f examples/stellar-gcp-kms-signer/docker-compose.yaml up
154+
```
155+
156+
### Step 6: Test the Service
157+
158+
#### 6.1 Check Relayer Status
159+
160+
First, verify that your relayer is running and properly configured:
161+
162+
```bash
163+
curl -X GET http://localhost:8080/api/v1/relayers \
164+
-H "Content-Type: application/json" \
165+
-H "AUTHORIZATION: Bearer YOUR_API_KEY"
166+
```
167+
168+
This should return information about your relayer, including its address derived from the Google Cloud KMS public key.
169+
170+
#### 6.2 Test Stellar Transaction Signing
171+
172+
Test the complete transaction signing and submission process:
173+
174+
```bash
175+
curl -X POST http://localhost:8080/api/v1/relayers/your-relayer-id/transactions \
176+
-H "Content-Type: application/json" \
177+
-H "AUTHORIZATION: Bearer YOUR_API_KEY" \
178+
-d '{
179+
"value": 1,
180+
"data": "0x",
181+
"to": "0x742d35cc6604c532532db3ae0f4d03e7c7b17e3e",
182+
"gas_limit": 21000,
183+
"speed": "average"
184+
}'
185+
```
186+
187+
**What this does:**
188+
189+
- Creates a transaction sending 1 wei to the specified address
190+
- Uses Google Cloud KMS to sign the transaction
191+
- Submits the signed transaction to the network
192+
- Returns transaction details including the transaction hash
193+
194+
### Troubleshooting
195+
196+
If you encounter issues:
197+
198+
1. **Authentication Issues**:
199+
200+
- Verify your service account JSON is correct
201+
- Ensure the service account has the required KMS permissions
202+
- Check that the project ID matches your GCP project
203+
204+
2. **Key Access Issues**:
205+
206+
- Verify the key location, key ring ID, and key ID are correct
207+
- Ensure the key is created with the correct algorithm (Elliptic Curve ED25519)
208+
- Check that the key version exists
209+
210+
3. **Signing Failures**:
211+
212+
- Verify the key has signing permissions
213+
- Check that the key algorithm supports ED25519 operations
214+
- Review service logs for detailed error messages
215+
216+
4. **Network Issues**:
217+
- Ensure your environment can reach Google Cloud KMS APIs
218+
- Check firewall settings if running in a restricted environment
219+
220+
### Additional Resources
221+
222+
- [Google Cloud KMS Documentation](https://cloud.google.com/kms/docs)
223+
- [Service Account Authentication](https://cloud.google.com/docs/authentication/getting-started)
224+
- [KMS Key Management](https://cloud.google.com/kms/docs/creating-keys)
225+
- [OpenZeppelin Relayer Documentation](https://docs.openzeppelin.com/relayer)
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"relayers": [
3+
{
4+
"id": "stellar-example",
5+
"name": "Stellar Example",
6+
"network": "testnet",
7+
"paused": false,
8+
"signer_id": "gcp-kms-signer-stellar",
9+
"network_type": "stellar",
10+
"policies": {
11+
"min_balance": 0
12+
}
13+
}
14+
],
15+
"notifications": [],
16+
17+
"signers": [
18+
{
19+
"id": "gcp-kms-signer-stellar",
20+
"type": "google_cloud_kms",
21+
"config": {
22+
"service_account": {
23+
"project_id": "macro-boulevard-473712-h8",
24+
"private_key_id": {
25+
"type": "env",
26+
"value": "GCP_PRIVATE_KEY_ID"
27+
},
28+
"private_key": {
29+
"type": "env",
30+
"value": "GCP_PRIVATE_KEY"
31+
},
32+
"client_email": {
33+
"type": "env",
34+
"value": "GCP_CLIENT_EMAIL"
35+
},
36+
"client_id": "108076383744345715915"
37+
},
38+
"key": {
39+
"location": "global",
40+
"key_ring_id": "relayer",
41+
"key_id": "relayer",
42+
"key_version": 1
43+
}
44+
}
45+
}
46+
],
47+
"networks": "./config/networks",
48+
"plugins": []
49+
}

0 commit comments

Comments
 (0)