|
1 | | -import { errorInstances } from '../errors'; |
| 1 | +import type { AWSError } from 'aws-sdk'; |
| 2 | +import { ArsenalError, errorInstances } from '../errors'; |
2 | 3 |
|
3 | 4 | /** |
4 | 5 | * Normalize errors according to arsenal definitions with a custom prefix |
@@ -28,6 +29,61 @@ export function arsenalErrorKMIP(err: string | Error) { |
28 | 29 | return _normalizeArsenalError(err, 'KMIP:'); |
29 | 30 | } |
30 | 31 |
|
31 | | -export function arsenalErrorAWSKMS(err: string | Error) { |
| 32 | +// List of AWS KMS errors that are specific to KMS and where the error |
| 33 | +// can be returned to the user as is with a specific status code. |
| 34 | +// Avoid any error that might leak sensitive information such as hostnames |
| 35 | +// or ip addresses from network related errors. |
| 36 | +// KeyId is not considered sensitive. |
| 37 | +// Reference: https://docs.aws.amazon.com/kms/latest/APIReference/CommonErrors.html |
| 38 | +// See specific actions like CreateKey, Encrypt, Decrypt, etc. for more details. |
| 39 | +// Other errors not listed will return only the same error code but http status 500 |
| 40 | +// and message will be generic and details will be in logs only. |
| 41 | +const allowedKmsErrors = { |
| 42 | + 'AccessDeniedException': 400, |
| 43 | + 'AlreadyExistsException': 400, |
| 44 | + 'DisabledException': 400, |
| 45 | + 'IncorrectKeyException': 400, |
| 46 | + 'InvalidAliasNameException': 400, |
| 47 | + 'InvalidArnException': 400, |
| 48 | + 'InvalidCiphertextException': 400, |
| 49 | + 'InvalidGrantTokenException': 400, |
| 50 | + 'InvalidKeyUsageException': 400, |
| 51 | + 'KMSInternalException': 500, |
| 52 | + 'KMSInvalidStateException': 400, |
| 53 | + 'KeyUnavailableException': 500, |
| 54 | + 'LimitExceededException': 400, |
| 55 | + 'MalformedPolicyDocumentException': 400, |
| 56 | + 'NotFoundException': 400, |
| 57 | + 'TagException': 400, |
| 58 | + 'UnsupportedOperationException': 400, |
| 59 | +}; |
| 60 | + |
| 61 | +const allowedKmsErrorCodes = Object.keys(allowedKmsErrors); |
| 62 | + |
| 63 | +function isAWSError(err: string | Error | AWSError): err is AWSError { |
| 64 | + return (err as AWSError).code !== undefined |
| 65 | + && (err as AWSError).retryable !== undefined; |
| 66 | +} |
| 67 | + |
| 68 | +export function arsenalErrorAWSKMS(err: string | Error | AWSError) { |
| 69 | + if (isAWSError(err)) { |
| 70 | + if (allowedKmsErrorCodes.includes(err.code)) { |
| 71 | + return ArsenalError.unflatten({ |
| 72 | + is_arsenal_error: true, |
| 73 | + type: `KMS.${err.code}`, // aws s3 prefix kms errors with KMS. |
| 74 | + code: allowedKmsErrors[err.code], |
| 75 | + description: err.message, |
| 76 | + stack: err.stack, |
| 77 | + }); |
| 78 | + } else { |
| 79 | + return ArsenalError.unflatten({ |
| 80 | + is_arsenal_error: true, |
| 81 | + type: `KMS.${err.code}`, // aws s3 prefix kms errors with KMS. |
| 82 | + code: 500, |
| 83 | + description: `unexpected AWS_KMS error`, |
| 84 | + stack: err.stack, |
| 85 | + }); |
| 86 | + } |
| 87 | + } |
32 | 88 | return _normalizeArsenalError(err, 'AWS_KMS:'); |
33 | 89 | } |
0 commit comments