-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(azure-signing-manager): add azure signing manager
add azure signing manager that allows for keys to be stored in an Azure Key Vault and to be used with the Polymesh SDK DA-1322
- Loading branch information
1 parent
e9a191a
commit 9e4212d
Showing
24 changed files
with
1,410 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
"polywallet", | ||
"Resonse", | ||
"satoshi", | ||
"secp", | ||
"sonarcloud", | ||
"tscpaths", | ||
"Unsub" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"presets": [["@nrwl/web/babel", { "useBuiltIns": "usage" }]] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"extends": ["../../.eslintrc.json"], | ||
"ignorePatterns": ["!**/*"], | ||
"overrides": [ | ||
{ | ||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.ts", "*.tsx"], | ||
"rules": {} | ||
}, | ||
{ | ||
"files": ["*.js", "*.jsx"], | ||
"rules": {} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# azure-signing-manager | ||
|
||
This library was generated with [Nx](https://nx.dev). | ||
|
||
## Running unit tests | ||
|
||
Run `nx test azure-signing-manager` to execute the unit tests via [Jest](https://jestjs.io). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module.exports = { | ||
displayName: 'azure-signing-manager', | ||
preset: '../../jest.preset.js', | ||
globals: { | ||
'ts-jest': { | ||
tsconfig: '<rootDir>/tsconfig.spec.json', | ||
}, | ||
}, | ||
testEnvironment: 'node', | ||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], | ||
coverageDirectory: '../../coverage/packages/azure-signing-manager', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"name": "@polymeshassociation/azure-signing-manager", | ||
"version": "0.0.1", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@polymeshassociation/signing-manager-types": "^3.3.0", | ||
"@azure/keyvault-keys": "4.8.0", | ||
"@azure/identity": "4.4.1", | ||
"secp256k1": "5.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/secp256k1": "4.0.6" | ||
}, | ||
"peerDependencies": { | ||
"@polymeshassociation/polymesh-sdk": ">=15.0.0" | ||
}, | ||
"main": "./index.js", | ||
"typings": "./index.d.ts", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/PolymeshAssociation/signing-managers.git" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"root": "packages/azure-signing-manager", | ||
"sourceRoot": "packages/azure-signing-manager/src", | ||
"projectType": "library", | ||
"targets": { | ||
"build": { | ||
"executor": "@nrwl/node:package", | ||
"outputs": ["{options.outputPath}"], | ||
"options": { | ||
"outputPath": "dist/packages/azure-signing-manager", | ||
"tsConfig": "packages/azure-signing-manager/tsconfig.lib.json", | ||
"packageJson": "packages/azure-signing-manager/package.json", | ||
"main": "packages/azure-signing-manager/src/index.ts", | ||
"assets": ["packages/azure-signing-manager/*.md"], | ||
"srcRootForCompilationRoot": "packages/azure-signing-manager/src" | ||
} | ||
}, | ||
"lint": { | ||
"executor": "@nrwl/linter:eslint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": ["packages/azure-signing-manager/**/*.ts"] | ||
} | ||
}, | ||
"test": { | ||
"executor": "@nrwl/jest:jest", | ||
"outputs": ["coverage/packages/azure-signing-manager"], | ||
"options": { | ||
"jestConfig": "packages/azure-signing-manager/jest.config.js", | ||
"passWithNoTests": true | ||
} | ||
}, | ||
"release": { | ||
"executor": "@ng-easy/builders:semantic-release", | ||
"configurations": { | ||
"local": { | ||
"force": true | ||
} | ||
} | ||
}, | ||
"run-local": { | ||
"executor": "./tools/executors/run-local:run-local", | ||
"options": { | ||
"runInBrowser": false, | ||
"path": "packages/azure-signing-manager/sandbox/index.ts", | ||
"port": 9000 | ||
} | ||
} | ||
}, | ||
"tags": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './lib/azure-signing-manager'; | ||
export * from './types'; |
132 changes: 132 additions & 0 deletions
132
packages/azure-signing-manager/src/lib/azure-hsm/azure-hsm.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { | ||
CryptographyClient, | ||
KeyClient, | ||
KeyProperties, | ||
KeyVaultKey, | ||
KnownSignatureAlgorithms, | ||
} from '@azure/keyvault-keys'; | ||
import { createMock, DeepMocked } from '@golevelup/ts-jest'; | ||
import { when } from 'jest-when'; | ||
|
||
import { AzureHsm } from './azure-hsm'; | ||
import { AzureSignerError } from './types'; | ||
import { createPagedAsyncIterableIterator } from './util'; | ||
|
||
const mockKeyClient = createMock<KeyClient>(); | ||
const mockCryptographyClient = createMock<CryptographyClient>(); | ||
const mockKeyVaultKey = createMock<KeyVaultKey>(); | ||
|
||
jest.mock('@azure/keyvault-keys', () => ({ | ||
...jest.requireActual('@azure/keyvault-keys'), | ||
KeyClient: jest.fn().mockImplementation(() => mockKeyClient), | ||
CryptographyClient: jest.fn().mockImplementation(() => mockCryptographyClient), | ||
KeyVaultKey: jest.fn().mockImplementation(() => mockKeyVaultKey), | ||
})); | ||
|
||
describe('AzureHsm', () => { | ||
let azure: AzureHsm; | ||
let mockKey: DeepMocked<KeyVaultKey>; | ||
let mockNewKey: DeepMocked<KeyVaultKey>; | ||
let mockPartialKey: DeepMocked<KeyVaultKey>; | ||
|
||
const x = Buffer.from('d6eb9ae6b44331da8c92a0bd88850b94c7f32981aaf42d1c1345e05af810470a', 'hex'); | ||
const y = Buffer.from('7b4603950822dd8806494a3aff5d6bc2e437b71f7c7de64e9d84a60411dc1293', 'hex'); | ||
const publicKey = '0x63eb973f33ad5737a1ea2e4100c04e806c403b5994d986f0c71a2fd80dbbd179'; | ||
|
||
beforeEach(() => { | ||
azure = new AzureHsm({ keyVaultUrl: 'https://example.com' }); | ||
mockKey = createMock<KeyVaultKey>({ key: { x, y } }); | ||
mockNewKey = createMock<KeyVaultKey>({ key: { x, y } }); | ||
mockPartialKey = createMock<KeyVaultKey>({ key: { x: undefined, y: undefined } }); | ||
|
||
const mockKeyProperties: KeyProperties[] = [ | ||
{ name: 'someKey', vaultUrl: 'http://example.com/keyOne' }, | ||
]; | ||
|
||
const mockIterator = createPagedAsyncIterableIterator(mockKeyProperties); | ||
|
||
mockKeyClient.listPropertiesOfKeys.mockReturnValue(mockIterator); | ||
|
||
mockKeyClient.getKey.mockRejectedValue({ code: 'KeyNotFound' }); | ||
|
||
mockKeyClient.createKey.mockImplementation(async name => { | ||
when(mockKeyClient.getKey).calledWith(name).mockResolvedValue(mockKey); | ||
|
||
return mockKey; | ||
}); | ||
when(mockKeyClient.getKey).calledWith('someKey').mockResolvedValue(mockKey); | ||
|
||
when(mockKeyClient.getKey).calledWith('partialKey').mockResolvedValue(mockPartialKey); | ||
|
||
mockCryptographyClient.sign.mockResolvedValue({ | ||
result: Buffer.from( | ||
'b4b24959854a6afdba21e1007955c6c728725009feab9886408d6dc4fb9712e3ab5f30be4f06d2f12f01a10ccd374278d44ab133ed8ee5998341034f9347f156', | ||
'hex' | ||
), | ||
algorithm: KnownSignatureAlgorithms.ES256K, | ||
}); | ||
|
||
mockKeyClient.getCryptographyClient.mockReturnValue(mockCryptographyClient); | ||
}); | ||
|
||
describe('createKey', () => { | ||
it('should create a key', async () => { | ||
const result = await azure.createKey('newKey'); | ||
|
||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
name: 'newKey', | ||
keyVaultKey: mockNewKey, | ||
}) | ||
); | ||
}); | ||
}); | ||
|
||
describe('fetchAllKeys', () => { | ||
it('should return all of the key', async () => { | ||
const result = await azure.fetchAllKeys(); | ||
|
||
expect(result).toEqual( | ||
expect.arrayContaining([expect.objectContaining({ name: 'someKey', keyVaultKey: mockKey })]) | ||
); | ||
}); | ||
}); | ||
|
||
describe('getAzureKeyByPubKey', () => { | ||
it('should return the key', async () => { | ||
const key = await azure.getAzureKeyByPubKey(publicKey); | ||
|
||
expect(key).toEqual(expect.objectContaining({ name: 'someKey', keyVaultKey: mockKey })); | ||
}); | ||
}); | ||
|
||
describe('getAzureKey', () => { | ||
it('should return the azure key', async () => { | ||
const result = await azure.getAzureKey('someKey'); | ||
|
||
expect(result).toEqual(expect.objectContaining({ name: 'someKey', keyVaultKey: mockKey })); | ||
}); | ||
|
||
it('should return undefined if key is not found', () => { | ||
return expect(azure.getAzureKey('unknownKey')).resolves.toEqual(undefined); | ||
}); | ||
|
||
it('should throw an error if the key is missing details', async () => { | ||
const expectedError = new AzureSignerError({ message: 'essential key details missing' }); | ||
|
||
return expect(azure.getAzureKey('partialKey')).rejects.toThrow(expectedError); | ||
}); | ||
}); | ||
|
||
describe('signData', () => { | ||
it('should sign the data', async () => { | ||
const bytes = Buffer.from('00', 'hex'); | ||
|
||
const result = await azure.signData(publicKey, bytes); | ||
|
||
expect(result).toEqual( | ||
'0x02b4b24959854a6afdba21e1007955c6c728725009feab9886408d6dc4fb9712e3ab5f30be4f06d2f12f01a10ccd374278d44ab133ed8ee5998341034f9347f15601' | ||
); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.