From a1401c3c5277417a725f56d56b52879192994b66 Mon Sep 17 00:00:00 2001 From: Mircea Nistor Date: Fri, 20 Aug 2021 12:59:30 +0200 Subject: [PATCH] feat(data-store): add migration of key stores --- .../fixtures/local-database-before-3.0.sqlite | Bin 0 -> 147456 bytes __tests__/migration.test.ts | 142 ++++++++++++++++++ __tests__/shared/didManager.ts | 2 +- packages/core/plugin.schema.json | 6 +- .../src/entities/PreMigrationEntities.ts | 15 ++ packages/data-store/src/index.ts | 5 +- .../src/migrations/createPrivateKeyStorage.ts | 83 ++++++++++ packages/data-store/src/migrations/index.ts | 3 +- packages/did-comm/src/utils.ts | 4 +- 9 files changed, 252 insertions(+), 8 deletions(-) create mode 100644 __tests__/fixtures/local-database-before-3.0.sqlite create mode 100644 __tests__/migration.test.ts create mode 100644 packages/data-store/src/entities/PreMigrationEntities.ts create mode 100644 packages/data-store/src/migrations/createPrivateKeyStorage.ts diff --git a/__tests__/fixtures/local-database-before-3.0.sqlite b/__tests__/fixtures/local-database-before-3.0.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..3dca8b1feb57d1cf3532f6d13835d32b518f4d49 GIT binary patch literal 147456 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 g$9B)AKmY5q { + describe('using pre-migration database fixture', () => { + type TestingAgentPlugins = IDIDManager & IKeyManager & IDataStore & IDataStoreORM & IResolver & IDIDComm + let agent: TAgent + let dbConnection: Promise + + beforeAll(async () => { + fs.copyFileSync(databaseBeforeFile, databaseFile) + + dbConnection = createConnection({ + name: 'test', + type: 'sqlite', + database: databaseFile, + synchronize: false, + migrations: migrations, + migrationsRun: true, + logging: false, + entities: Entities, + }) + + agent = createAgent({ + context: { + // authenticatedDid: 'did:example:3456' + }, + plugins: [ + new KeyManager({ + store: new KeyStore(dbConnection), + kms: { + local: new KeyManagementSystem({ + keyStore: new PrivateKeyStore(dbConnection, new SecretBox(secretKey)), + }), + }, + }), + new DIDManager({ + store: new DIDStore(dbConnection), + defaultProvider: 'did:ethr:goerli', + providers: { + 'did:ethr:goerli': new EthrDIDProvider({ + defaultKms: 'local', + network: 'goerli', + rpcUrl: 'https://goerli.infura.io/v3/' + infuraProjectId, + }), + 'did:web': new WebDIDProvider({ + defaultKms: 'local', + }), + 'did:key': new KeyDIDProvider({ + defaultKms: 'local', + }), + 'did:fake': new FakeDidProvider(), + }, + }), + new DIDResolverPlugin({ + resolver: new Resolver({ + ...ethrDidResolver({ infuraProjectId }), + ...webDidResolver(), + ...getDidKeyResolver(), + ...new FakeDidResolver(() => agent).getDidFakeResolver(), + }), + }), + new DataStore(dbConnection), + new DataStoreORM(dbConnection), + new DIDComm(), + ], + }) + return true + }) + afterAll(async () => { + await (await dbConnection).close() + fs.unlinkSync(databaseFile) + }) + + it('loads a migrated key', async () => { + // output of agent.keyManagerGet() before migration + const key = { + kid: '04539ffde912c094bc48b64c9ee71b2baece24c710bcad2c7bacced615f60ae53949cdc95379eb50556d11cb0afab0e5a6ca8cb475d413b2f12307cc2d7f5438de', + kms: 'local', + type: 'Secp256k1', + publicKeyHex: + '04539ffde912c094bc48b64c9ee71b2baece24c710bcad2c7bacced615f60ae53949cdc95379eb50556d11cb0afab0e5a6ca8cb475d413b2f12307cc2d7f5438de', + privateKeyHex: 'a5e81a8cd50cf5c31d5b87db3e153e2817f86de350a60edc2335f76d5c3b4e0d', + meta: { + algorithms: ['ES256K', 'ES256K-R', 'eth_signTransaction', 'eth_signTypedData', 'eth_signMessage'], + }, + } + const migratedKey = await agent.keyManagerGet({ kid: key.kid }) + expect(migratedKey.kid).toEqual(key.kid) + expect(migratedKey).not.toHaveProperty('privateKeyHex') + const signedMessage = await agent.keyManagerSign({ + data: 'hello world', + keyRef: migratedKey.kid, + algorithm: 'ES256K', + encoding: 'utf-8', + }) + expect(signedMessage).toEqual( + 'vzDocUViJh7ooOCZ-jBHKZddEsTa4yClHwhIL9SHJwjAv3bC6TZIcUnX36ZqNBWvLbnNAQvdtzqrVf3l0pv3QQ', + ) + }) + + it('unpacks DIDComm message intended for migrated managed key', async () => { + const packed = { + message: + '{"protected":"eyJ0eXAiOiJhcHBsaWNhdGlvbi9kaWRjb21tLWVuY3J5cHRlZCtqc29uIiwiZW5jIjoiWEMyMFAifQ","iv":"mBAgYLce2JpmKtmlNQLG6w9lm6kqf4Ne","ciphertext":"D9_7Xxj51xn3T9yBU-rZmxSTrR82Pi4G7hWCDSxSpRUlmUh2uJoqeCHixSTFeZvFAfw2ryROjrxbpCh5Arg-wqrW3WwKGpVFHXO_r0jHso5lNMO-vGjxOULN","tag":"9Qs-esw1tcnM0jE_Q3LxIQ","recipients":[{"encrypted_key":"kGNaBfhPS2VETu-_iYaUwy13sC1ZVm3i_qYiYkuEleA","header":{"alg":"ECDH-ES+XC20PKW","iv":"1sK1pyOwy_hNY_WsJPGdoFqE8ken51IA","tag":"MplY66h-bHnuSdP1ZGLYyw","epk":{"kty":"OKP","crv":"X25519","x":"UZx8Uf3BJ-m3wm7sBjvCp1UXuHA9v0Qu5KvWfWyBNio"},"kid":"did:key:z6MkiPXoC2uAWPdQpotWxzNMJpaDbfPxaQWcbux5avNwEMfD#z6LSqL9zfeZa53RwpAkjxN7Gizvzv4rjAT7GwhLVYLPXK5dC"}}]}', + } + const msg = await agent.unpackDIDCommMessage(packed) + expect(msg.message.body).toEqual({ hello: 'world' }) + }) + }) +}) diff --git a/__tests__/shared/didManager.ts b/__tests__/shared/didManager.ts index 028be200ca..557f6a0edf 100644 --- a/__tests__/shared/didManager.ts +++ b/__tests__/shared/didManager.ts @@ -298,7 +298,7 @@ export default (testContext: { id: `${did}#msg`, serviceEndpoint: 'https://example.org/messaging', type: 'Messaging', - } as Service, + }, ], }) }) diff --git a/packages/core/plugin.schema.json b/packages/core/plugin.schema.json index 09655d5e2c..225eba564d 100644 --- a/packages/core/plugin.schema.json +++ b/packages/core/plugin.schema.json @@ -655,7 +655,8 @@ ], "description": "Optional. Key metadata. This should be used to determine which algorithms are supported." } - } + }, + "description": "Represents an object type where a subset of keys are required and everything else is optional." }, "IKeyManagerSharedSecretArgs": { "type": "object", @@ -1271,7 +1272,8 @@ ], "description": "Optional. Key metadata. This should be used to determine which algorithms are supported." } - } + }, + "description": "Represents an object type where a subset of keys are required and everything else is optional." }, "IDIDManagerRemoveKeyArgs": { "type": "object", diff --git a/packages/data-store/src/entities/PreMigrationEntities.ts b/packages/data-store/src/entities/PreMigrationEntities.ts new file mode 100644 index 0000000000..0b1833da80 --- /dev/null +++ b/packages/data-store/src/entities/PreMigrationEntities.ts @@ -0,0 +1,15 @@ +import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm' + +@Entity('key') +export class PreMigrationKey extends BaseEntity { + @PrimaryColumn() + //@ts-ignore + kid: string + + @Column() + //@ts-ignore + type: KeyType + + @Column({ nullable: true }) + privateKeyHex?: string +} diff --git a/packages/data-store/src/index.ts b/packages/data-store/src/index.ts index 90c7439a56..4f249fbdf0 100644 --- a/packages/data-store/src/index.ts +++ b/packages/data-store/src/index.ts @@ -34,8 +34,9 @@ import { Presentation } from './entities/presentation' import { Service } from './entities/service' import { Message, MetaData } from './entities/message' import { PrivateKey } from './entities/private-key' -export const Entities = [Key, Identifier, Message, Claim, Credential, Presentation, Service, PrivateKey] -export { KeyType, Key, Identifier, Message, Claim, Credential, Presentation, MetaData, Service, PrivateKey } +import { PreMigrationKey } from './entities/PreMigrationEntities' +export const Entities = [Key, Identifier, Message, Claim, Credential, Presentation, Service, PrivateKey, PreMigrationKey] +export { KeyType, Key, Identifier, Message, Claim, Credential, Presentation, MetaData, Service, PrivateKey, PreMigrationKey } export { migrations } from './migrations' const schema = require('../plugin.schema.json') export { schema } diff --git a/packages/data-store/src/migrations/createPrivateKeyStorage.ts b/packages/data-store/src/migrations/createPrivateKeyStorage.ts new file mode 100644 index 0000000000..e8cae82400 --- /dev/null +++ b/packages/data-store/src/migrations/createPrivateKeyStorage.ts @@ -0,0 +1,83 @@ +import { MigrationInterface, QueryRunner, Table, TableColumn } from 'typeorm' +import { PrivateKey } from '..' +import { PreMigrationKey } from '../entities/PreMigrationEntities' +import Debug from 'debug' +const debug = Debug('veramo:data-store:key-migration') + +/** + * Migration of existing private keys from Veramo 2.x to Veramo 3.x + */ +export class CreatePrivateKeyStorage1629293428674 implements MigrationInterface { + async up(queryRunner: QueryRunner): Promise { + // 1.create new table + debug(`creating new private-key table`) + await queryRunner.createTable( + new Table({ + name: 'private-key', + columns: [ + { + name: 'alias', + type: 'varchar', + isPrimary: true, + }, + { + name: 'type', + type: 'varchar', + }, + { + name: 'privateKeyHex', + type: 'varchar', + }, + ], + }), + true, + ) + // 2. copy key data + const keys: PreMigrationKey[] = await queryRunner.manager.find(PreMigrationKey) + debug(`got ${keys.length} potential keys to migrate`) + const privKeys = keys + .filter((key) => typeof key.privateKeyHex !== 'undefined' && key.privateKeyHex !== null) + .map((key) => ({ + alias: key.kid, + type: key.type, + privateKeyHex: key.privateKeyHex, + })) + debug(`${privKeys.length} keys need to be migrated`) + await queryRunner.manager.createQueryBuilder().insert().into('private-key').values(privKeys).execute() + // 3. drop old column + debug(`dropping privKeyHex column from old key table`) + await queryRunner.dropColumn('key', 'privateKeyHex') + //4. done + debug(`migrated ${privKeys.length} keys to private key storage`) + } + + async down(queryRunner: QueryRunner): Promise { + // 1. add old column back + debug(`adding back privateKeyHex column to key table`) + await queryRunner.addColumn( + 'key', + new TableColumn({ + name: 'privateKeyHex', + type: 'varchar', + isNullable: true, + }), + ) + // 2. copy key data + debug(`checking keys to be rolled back`) + const keys: PrivateKey[] = await queryRunner.manager.find(PrivateKey) + debug(`copying ${keys.length} keys`) + for (const key of keys) { + await queryRunner.manager + .createQueryBuilder() + .update(PreMigrationKey) + .set({ privateKeyHex: key.privateKeyHex }) + .where('kid = :alias', { alias: key.alias }) + .execute() + } + debug(`dropping private-key table`) + // 3. drop the new private key table + await queryRunner.dropTable('private-key') + // 4. done + debug(`rolled back ${keys.length} keys`) + } +} diff --git a/packages/data-store/src/migrations/index.ts b/packages/data-store/src/migrations/index.ts index 0d0cada0e3..f706c3db55 100644 --- a/packages/data-store/src/migrations/index.ts +++ b/packages/data-store/src/migrations/index.ts @@ -1 +1,2 @@ -export const migrations = [] +import { CreatePrivateKeyStorage1629293428674 } from './createPrivateKeyStorage' +export const migrations = [CreatePrivateKeyStorage1629293428674] diff --git a/packages/did-comm/src/utils.ts b/packages/did-comm/src/utils.ts index 1e419debe7..cc05bfa2fb 100644 --- a/packages/did-comm/src/utils.ts +++ b/packages/did-comm/src/utils.ts @@ -196,8 +196,8 @@ export async function mapIdentifierKeysToDoc( export async function resolveDidOrThrow(didUrl: string, context: IAgentContext) { // TODO: add caching const docResult = await context.agent.resolveDid({ didUrl: didUrl }) - const err = docResult.didResolutionMetadata.error - const msg = docResult.didResolutionMetadata.message + const err = docResult?.didResolutionMetadata?.error + const msg = docResult?.didResolutionMetadata?.message const didDocument = docResult.didDocument if (!isDefined(didDocument) || err) { throw new Error(`not_found: could not resolve DID document for '${didUrl}': ${err} ${msg}`)