Skip to content

Commit 961994f

Browse files
authored
ci: add GCP KMS to TypeScript CI pipeline (#35)
- Add gcp-kms to unit and integration test matrices - Add GCP authentication step using google-github-actions/auth@v2 - Add GCP_KMS_KEY_NAME and GCP_KMS_SIGNER_PUBKEY env vars - Fix missing gcp-kms reference in keychain tsconfig.json - Format gcp-kms test file with prettier Co-authored-by: Jo D <dev-jodee@users.noreply.github.com>
1 parent 0de939b commit 961994f

File tree

3 files changed

+67
-37
lines changed

3 files changed

+67
-37
lines changed

.github/workflows/typescript-ci.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
working-directory: typescript
1515
strategy:
1616
matrix:
17-
package: [vault, privy, turnkey, fireblocks]
17+
package: [vault, privy, turnkey, fireblocks, gcp-kms]
1818
steps:
1919
- uses: actions/checkout@v4
2020
- uses: actions/setup-node@v4
@@ -37,7 +37,7 @@ jobs:
3737
working-directory: typescript
3838
strategy:
3939
matrix:
40-
package: [privy, turnkey, fireblocks]
40+
package: [privy, turnkey, fireblocks, gcp-kms]
4141
steps:
4242
- uses: actions/checkout@v4
4343
- uses: actions/setup-node@v4
@@ -48,6 +48,11 @@ jobs:
4848
version: 10.14.0
4949
- name: Install dependencies
5050
run: pnpm install
51+
- name: Setup GCP credentials
52+
if: matrix.package == 'gcp-kms'
53+
uses: google-github-actions/auth@v2
54+
with:
55+
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
5156
- name: Build packages
5257
run: pnpm build
5358
- name: Run integration tests for @solana/keychain-${{ matrix.package }}
@@ -66,6 +71,9 @@ jobs:
6671
FIREBLOCKS_API_KEY: ${{ secrets.FIREBLOCKS_API_KEY }}
6772
FIREBLOCKS_PRIVATE_KEY_PEM: ${{ secrets.FIREBLOCKS_PRIVATE_KEY_PEM }}
6873
FIREBLOCKS_VAULT_ACCOUNT_ID: ${{ secrets.FIREBLOCKS_VAULT_ACCOUNT_ID }}
74+
# GCP KMS
75+
GCP_KMS_KEY_NAME: ${{ secrets.GCP_KMS_KEY_NAME }}
76+
GCP_KMS_SIGNER_PUBKEY: ${{ secrets.GCP_KMS_SIGNER_PUBKEY }}
6977
run: pnpm -F @solana/keychain-${{ matrix.package }} run test:integration
7078

7179
typescript-lint:

typescript/packages/gcp-kms/src/__tests__/gcp-kms-signer.test.ts

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ vi.mock('@google-cloud/kms', () => {
2121
});
2222

2323
describe('GcpKmsSigner', () => {
24-
const TEST_KEY_NAME = 'projects/test-project/locations/us-east1/keyRings/test-ring/cryptoKeys/test-key/cryptoKeyVersions/1';
24+
const TEST_KEY_NAME =
25+
'projects/test-project/locations/us-east1/keyRings/test-ring/cryptoKeys/test-key/cryptoKeyVersions/1';
2526
const TEST_PUBLIC_KEY = address('11111111111111111111111111111111');
2627

2728
beforeEach(() => {
@@ -97,9 +98,11 @@ describe('GcpKmsSigner', () => {
9798

9899
describe('signMessages', () => {
99100
it('should sign a message successfully', async () => {
100-
mockAsymmetricSign.mockResolvedValue([{
101-
signature: new Uint8Array(64).fill(0x42),
102-
}]);
101+
mockAsymmetricSign.mockResolvedValue([
102+
{
103+
signature: new Uint8Array(64).fill(0x42),
104+
},
105+
]);
103106

104107
const signer = new GcpKmsSigner({
105108
keyName: TEST_KEY_NAME,
@@ -122,9 +125,11 @@ describe('GcpKmsSigner', () => {
122125
});
123126

124127
it('should handle multiple messages with delay', async () => {
125-
mockAsymmetricSign.mockResolvedValue([{
126-
signature: new Uint8Array(64).fill(0x42),
127-
}]);
128+
mockAsymmetricSign.mockResolvedValue([
129+
{
130+
signature: new Uint8Array(64).fill(0x42),
131+
},
132+
]);
128133

129134
const signer = new GcpKmsSigner({
130135
keyName: TEST_KEY_NAME,
@@ -149,9 +154,11 @@ describe('GcpKmsSigner', () => {
149154
});
150155

151156
it('should throw error on invalid signature length', async () => {
152-
mockAsymmetricSign.mockResolvedValue([{
153-
signature: new Uint8Array(32), // Wrong length
154-
}]);
157+
mockAsymmetricSign.mockResolvedValue([
158+
{
159+
signature: new Uint8Array(32), // Wrong length
160+
},
161+
]);
155162

156163
const signer = new GcpKmsSigner({
157164
keyName: TEST_KEY_NAME,
@@ -194,9 +201,11 @@ describe('GcpKmsSigner', () => {
194201

195202
describe('signTransactions', () => {
196203
it('should sign a transaction successfully', async () => {
197-
mockAsymmetricSign.mockResolvedValue([{
198-
signature: new Uint8Array(64).fill(0x42),
199-
}]);
204+
mockAsymmetricSign.mockResolvedValue([
205+
{
206+
signature: new Uint8Array(64).fill(0x42),
207+
},
208+
]);
200209

201210
const signer = new GcpKmsSigner({
202211
keyName: TEST_KEY_NAME,
@@ -216,9 +225,11 @@ describe('GcpKmsSigner', () => {
216225
});
217226

218227
it('should sign multiple transactions successfully', async () => {
219-
mockAsymmetricSign.mockResolvedValue([{
220-
signature: new Uint8Array(64).fill(0x42),
221-
}]);
228+
mockAsymmetricSign.mockResolvedValue([
229+
{
230+
signature: new Uint8Array(64).fill(0x42),
231+
},
232+
]);
222233

223234
const signer = new GcpKmsSigner({
224235
keyName: TEST_KEY_NAME,
@@ -237,9 +248,11 @@ describe('GcpKmsSigner', () => {
237248
});
238249

239250
it('should throw error on invalid signature length', async () => {
240-
mockAsymmetricSign.mockResolvedValue([{
241-
signature: new Uint8Array(32),
242-
}]);
251+
mockAsymmetricSign.mockResolvedValue([
252+
{
253+
signature: new Uint8Array(32),
254+
},
255+
]);
243256

244257
const signer = new GcpKmsSigner({
245258
keyName: TEST_KEY_NAME,
@@ -276,17 +289,21 @@ describe('GcpKmsSigner', () => {
276289

277290
const transaction = { messageBytes: new Uint8Array([1, 2, 3, 4]), signatures: {} } as any;
278291

279-
await expect(signer.signTransactions([transaction])).rejects.toThrow('GCP KMS Sign operation failed: GCP Error');
292+
await expect(signer.signTransactions([transaction])).rejects.toThrow(
293+
'GCP KMS Sign operation failed: GCP Error',
294+
);
280295
});
281296
});
282297

283298
describe('isAvailable', () => {
284299
it('should return true for valid Ed25519 key', async () => {
285-
mockGetCryptoKeyVersion.mockResolvedValue([{
286-
name: TEST_KEY_NAME,
287-
algorithm: 'EC_SIGN_ED25519',
288-
state: 'ENABLED',
289-
}]);
300+
mockGetCryptoKeyVersion.mockResolvedValue([
301+
{
302+
name: TEST_KEY_NAME,
303+
algorithm: 'EC_SIGN_ED25519',
304+
state: 'ENABLED',
305+
},
306+
]);
290307

291308
const signer = new GcpKmsSigner({
292309
keyName: TEST_KEY_NAME,
@@ -299,11 +316,13 @@ describe('GcpKmsSigner', () => {
299316
});
300317

301318
it('should return false for wrong algorithm', async () => {
302-
mockGetCryptoKeyVersion.mockResolvedValue([{
303-
name: TEST_KEY_NAME,
304-
algorithm: 'RSA_SIGN_PKCS1_2048_SHA256',
305-
state: 'ENABLED',
306-
}]);
319+
mockGetCryptoKeyVersion.mockResolvedValue([
320+
{
321+
name: TEST_KEY_NAME,
322+
algorithm: 'RSA_SIGN_PKCS1_2048_SHA256',
323+
state: 'ENABLED',
324+
},
325+
]);
307326

308327
const signer = new GcpKmsSigner({
309328
keyName: TEST_KEY_NAME,
@@ -316,11 +335,13 @@ describe('GcpKmsSigner', () => {
316335
});
317336

318337
it('should return false for disabled key', async () => {
319-
mockGetCryptoKeyVersion.mockResolvedValue([{
320-
name: TEST_KEY_NAME,
321-
algorithm: 'EC_SIGN_ED25519',
322-
state: 'DISABLED',
323-
}]);
338+
mockGetCryptoKeyVersion.mockResolvedValue([
339+
{
340+
name: TEST_KEY_NAME,
341+
algorithm: 'EC_SIGN_ED25519',
342+
state: 'DISABLED',
343+
},
344+
]);
324345

325346
const signer = new GcpKmsSigner({
326347
keyName: TEST_KEY_NAME,

typescript/packages/keychain/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
{ "path": "../core" },
1212
{ "path": "../aws-kms" },
1313
{ "path": "../fireblocks" },
14+
{ "path": "../gcp-kms" },
1415
{ "path": "../privy" },
1516
{ "path": "../turnkey" },
1617
{ "path": "../vault" }

0 commit comments

Comments
 (0)