124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler';
|
|
import { Action } from '../action.enum';
|
|
import * as Joi from 'joi';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository } from 'typeorm';
|
|
import { KeySpec, KeyUsage, KmsKey } from './kms-key.entity';
|
|
import { breakdownArn } from '../util/breakdown-arn';
|
|
import { KmsService } from './kms.service';
|
|
import * as crypto from 'crypto';
|
|
|
|
type QueryParams = {
|
|
GrantTokens: string[];
|
|
KeyId: string;
|
|
}
|
|
|
|
interface StandardOutput {
|
|
KeyId: string;
|
|
KeySpec: KeySpec;
|
|
KeyUsage: KeyUsage;
|
|
PublicKey: string;
|
|
CustomerMasterKeySpec: KeySpec;
|
|
}
|
|
|
|
interface EncryptDecrypt extends StandardOutput {
|
|
KeyUsage: 'ENCRYPT_DECRYPT';
|
|
EncryptionAlgorithms: ('SYMMETRIC_DEFAULT' | 'RSAES_OAEP_SHA_1' | 'RSAES_OAEP_SHA_256' | 'SM2PKE')[];
|
|
}
|
|
|
|
interface SignVerify extends StandardOutput {
|
|
KeyUsage: 'SIGN_VERIFY';
|
|
SigningAlgorithms: ('RSASSA_PSS_SHA_256' | 'RSASSA_PSS_SHA_384' | 'RSASSA_PSS_SHA_512' | 'RSASSA_PKCS1_V1_5_SHA_256' | 'RSASSA_PKCS1_V1_5_SHA_384' | 'RSASSA_PKCS1_V1_5_SHA_512' | 'ECDSA_SHA_256' | 'ECDSA_SHA_384' | 'ECDSA_SHA_512' | 'SM2DSA')[];
|
|
}
|
|
|
|
type Output = EncryptDecrypt | SignVerify | StandardOutput;
|
|
|
|
@Injectable()
|
|
export class GetPublicKeyHandler extends AbstractActionHandler<QueryParams> {
|
|
|
|
constructor(
|
|
|
|
@InjectRepository(KmsKey)
|
|
private readonly keyRepo: Repository<KmsKey>,
|
|
private readonly kmsService: KmsService,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
format = Format.Json;
|
|
action = Action.KmsGetPublicKey;
|
|
validator = Joi.object<QueryParams, true>({
|
|
KeyId: Joi.string().required(),
|
|
GrantTokens: Joi.array().items(Joi.string()),
|
|
});
|
|
|
|
protected async handle({ KeyId }: QueryParams, awsProperties: AwsProperties): Promise<Output> {
|
|
|
|
const searchable = KeyId.startsWith('arn') ? breakdownArn(KeyId) : {
|
|
service: 'kms',
|
|
region: awsProperties.region,
|
|
accountId: awsProperties.accountId,
|
|
identifier: KeyId,
|
|
};
|
|
const [ type, pk ] = searchable.identifier.split('/');
|
|
const keyId: Promise<string> = type === 'key' ?
|
|
Promise.resolve(pk) :
|
|
this.kmsService.findKeyIdFromAlias(pk, searchable);
|
|
|
|
|
|
const keyRecord = await this.keyRepo.findOne({ where: {
|
|
id: await keyId,
|
|
region: searchable.region,
|
|
accountId: searchable.accountId,
|
|
}});
|
|
|
|
const pubKeyObject = crypto.createPublicKey({
|
|
key: keyRecord.key,//.split(String.raw`\n`).join('\n'),
|
|
format: 'pem',
|
|
});
|
|
|
|
if (keyRecord.usage === 'ENCRYPT_DECRYPT') {
|
|
return {
|
|
CustomerMasterKeySpec: keyRecord.keySpec,
|
|
EncryptionAlgorithms: [ "SYMMETRIC_DEFAULT" ],
|
|
KeyId: keyRecord.arn,
|
|
KeySpec: keyRecord.keySpec,
|
|
KeyUsage: keyRecord.usage,
|
|
PublicKey: Buffer.from(pubKeyObject.export({
|
|
format: 'der',
|
|
type: 'spki',
|
|
})).toString('base64'),
|
|
}
|
|
}
|
|
|
|
if (keyRecord.usage === 'SIGN_VERIFY') {
|
|
const PublicKey = Buffer.from(pubKeyObject.export({
|
|
format: 'der',
|
|
type: 'spki',
|
|
})).toString('base64')
|
|
|
|
console.log({PublicKey})
|
|
return {
|
|
CustomerMasterKeySpec: keyRecord.keySpec,
|
|
KeyId: keyRecord.arn,
|
|
KeySpec: keyRecord.keySpec,
|
|
KeyUsage: keyRecord.usage,
|
|
PublicKey,
|
|
SigningAlgorithms: [ 'RSASSA_PKCS1_V1_5_SHA_256' ]
|
|
}
|
|
}
|
|
|
|
return {
|
|
CustomerMasterKeySpec: keyRecord.keySpec,
|
|
KeyId: keyRecord.arn,
|
|
KeySpec: keyRecord.keySpec,
|
|
KeyUsage: keyRecord.usage,
|
|
PublicKey: Buffer.from(pubKeyObject.export({
|
|
format: 'pem',
|
|
type: 'spki',
|
|
})).toString('utf-8'),
|
|
}
|
|
}
|
|
}
|