Added IAM support
This commit is contained in:
parent
2c78be1b3f
commit
29d36a57d6
|
|
@ -1,56 +1,216 @@
|
|||
export enum Action {
|
||||
|
||||
// IAM
|
||||
IamAddClientIDToOpenIDConnectProvider = 'AddClientIDToOpenIDConnectProvider',
|
||||
IamAddRoleToInstanceProfile = 'AddRoleToInstanceProfile',
|
||||
IamAddUserToGroup = 'AddUserToGroup',
|
||||
IamAttachGroupPolicy = 'AttachGroupPolicy',
|
||||
IamAttachRolePolicy = 'AttachRolePolicy',
|
||||
IamAttachUserPolicy = 'AttachUserPolicy',
|
||||
IamChangePassword = 'ChangePassword',
|
||||
IamCreateAccessKey = 'CreateAccessKey',
|
||||
IamCreateAccountAlias = 'CreateAccountAlias',
|
||||
IamCreateGroup = 'CreateGroup',
|
||||
IamCreateInstanceProfile = 'CreateInstanceProfile',
|
||||
IamCreateLoginProfile = 'CreateLoginProfile',
|
||||
IamCreateOpenIDConnectProvider = 'CreateOpenIDConnectProvider',
|
||||
IamCreatePolicy = 'CreatePolicy',
|
||||
IamCreatePolicyVersion = 'CreatePolicyVersion',
|
||||
IamCreateRole = 'CreateRole',
|
||||
IamCreateSAMLProvider = 'CreateSAMLProvider',
|
||||
IamCreateServiceLinkedRole = 'CreateServiceLinkedRole',
|
||||
IamCreateServiceSpecificCredential = 'CreateServiceSpecificCredential',
|
||||
IamCreateUser = 'CreateUser',
|
||||
IamCreateVirtualMFADevice = 'CreateVirtualMFADevice',
|
||||
IamDeactivateMFADevice = 'DeactivateMFADevice',
|
||||
IamDeleteAccessKey = 'DeleteAccessKey',
|
||||
IamDeleteAccountAlias = 'DeleteAccountAlias',
|
||||
IamDeleteAccountPasswordPolicy = 'DeleteAccountPasswordPolicy',
|
||||
IamDeleteGroup = 'DeleteGroup',
|
||||
IamDeleteGroupPolicy = 'DeleteGroupPolicy',
|
||||
IamDeleteInstanceProfile = 'DeleteInstanceProfile',
|
||||
IamDeleteLoginProfile = 'DeleteLoginProfile',
|
||||
IamDeleteOpenIDConnectProvider = 'DeleteOpenIDConnectProvider',
|
||||
IamDeletePolicy = 'DeletePolicy',
|
||||
IamDeletePolicyVersion = 'DeletePolicyVersion',
|
||||
IamDeleteRole = 'DeleteRole',
|
||||
IamDeleteRolePermissionsBoundary = 'DeleteRolePermissionsBoundary',
|
||||
IamDeleteRolePolicy = 'DeleteRolePolicy',
|
||||
IamDeleteSAMLProvider = 'DeleteSAMLProvider',
|
||||
IamDeleteServerCertificate = 'DeleteServerCertificate',
|
||||
IamDeleteServiceLinkedRole = 'DeleteServiceLinkedRole',
|
||||
IamDeleteServiceSpecificCredential = 'DeleteServiceSpecificCredential',
|
||||
IamDeleteSigningCertificate = 'DeleteSigningCertificate',
|
||||
IamDeleteSSHPublicKey = 'DeleteSSHPublicKey',
|
||||
IamDeleteUser = 'DeleteUser',
|
||||
IamDeleteUserPermissionsBoundary = 'DeleteUserPermissionsBoundary',
|
||||
IamDeleteUserPolicy = 'DeleteUserPolicy',
|
||||
IamDeleteVirtualMFADevice = 'DeleteVirtualMFADevice',
|
||||
IamDetachGroupPolicy = 'DetachGroupPolicy',
|
||||
IamDetachRolePolicy = 'DetachRolePolicy',
|
||||
IamDetachUserPolicy = 'DetachUserPolicy',
|
||||
IamEnableMFADevice = 'EnableMFADevice',
|
||||
IamGenerateCredentialReport = 'GenerateCredentialReport',
|
||||
IamGenerateOrganizationsAccessReport = 'GenerateOrganizationsAccessReport',
|
||||
IamGenerateServiceLastAccessedDetails = 'GenerateServiceLastAccessedDetails',
|
||||
IamGetAccessKeyLastUsed = 'GetAccessKeyLastUsed',
|
||||
IamGetAccountAuthorizationDetails = 'GetAccountAuthorizationDetails',
|
||||
IamGetAccountPasswordPolicy = 'GetAccountPasswordPolicy',
|
||||
IamGetAccountSummary = 'GetAccountSummary',
|
||||
IamGetContextKeysForCustomPolicy = 'GetContextKeysForCustomPolicy',
|
||||
IamGetContextKeysForPrincipalPolicy = 'GetContextKeysForPrincipalPolicy',
|
||||
IamGetCredentialReport = 'GetCredentialReport',
|
||||
IamGetGroup = 'GetGroup',
|
||||
IamGetGroupPolicy = 'GetGroupPolicy',
|
||||
IamGetInstanceProfile = 'GetInstanceProfile',
|
||||
IamGetLoginProfile = 'GetLoginProfile',
|
||||
IamGetOpenIDConnectProvider = 'GetOpenIDConnectProvider',
|
||||
IamGetOrganizationsAccessReport = 'GetOrganizationsAccessReport',
|
||||
IamGetPolicy = 'GetPolicy',
|
||||
IamGetPolicyVersion = 'GetPolicyVersion',
|
||||
IamGetRole = 'GetRole',
|
||||
IamGetRolePolicy = 'GetRolePolicy',
|
||||
IamGetSAMLProvider = 'GetSAMLProvider',
|
||||
IamGetServerCertificate = 'GetServerCertificate',
|
||||
IamGetServiceLastAccessedDetails = 'GetServiceLastAccessedDetails',
|
||||
IamGetServiceLastAccessedDetailsWithEntities = 'GetServiceLastAccessedDetailsWithEntities',
|
||||
IamGetServiceLinkedRoleDeletionStatus = 'GetServiceLinkedRoleDeletionStatus',
|
||||
IamGetSSHPublicKey = 'GetSSHPublicKey',
|
||||
IamGetUser = 'GetUser',
|
||||
IamGetUserPolicy = 'GetUserPolicy',
|
||||
IamListAccessKeys = 'ListAccessKeys',
|
||||
IamListAccountAliases = 'ListAccountAliases',
|
||||
IamListAttachedGroupPolicies = 'ListAttachedGroupPolicies',
|
||||
IamListAttachedRolePolicies = 'ListAttachedRolePolicies',
|
||||
IamListAttachedUserPolicies = 'ListAttachedUserPolicies',
|
||||
IamListEntitiesForPolicy = 'ListEntitiesForPolicy',
|
||||
IamListGroupPolicies = 'ListGroupPolicies',
|
||||
IamListGroups = 'ListGroups',
|
||||
IamListGroupsForUser = 'ListGroupsForUser',
|
||||
IamListInstanceProfiles = 'ListInstanceProfiles',
|
||||
IamListInstanceProfilesForRole = 'ListInstanceProfilesForRole',
|
||||
IamListInstanceProfileTags = 'ListInstanceProfileTags',
|
||||
IamListMFADevices = 'ListMFADevices',
|
||||
IamListMFADeviceTags = 'ListMFADeviceTags',
|
||||
IamListOpenIDConnectProviders = 'ListOpenIDConnectProviders',
|
||||
IamListOpenIDConnectProviderTags = 'ListOpenIDConnectProviderTags',
|
||||
IamListPolicies = 'ListPolicies',
|
||||
IamListPoliciesGrantingServiceAccess = 'ListPoliciesGrantingServiceAccess',
|
||||
IamListPolicyTags = 'ListPolicyTags',
|
||||
IamListPolicyVersions = 'ListPolicyVersions',
|
||||
IamListRolePolicies = 'ListRolePolicies',
|
||||
IamListRoles = 'ListRoles',
|
||||
IamListRoleTags = 'ListRoleTags',
|
||||
IamListSAMLProviders = 'ListSAMLProviders',
|
||||
IamListSAMLProviderTags = 'ListSAMLProviderTags',
|
||||
IamListServerCertificates = 'ListServerCertificates',
|
||||
IamListServerCertificateTags = 'ListServerCertificateTags',
|
||||
IamListServiceSpecificCredentials = 'ListServiceSpecificCredentials',
|
||||
IamListSigningCertificates = 'ListSigningCertificates',
|
||||
IamListSSHPublicKeys = 'ListSSHPublicKeys',
|
||||
IamListUserPolicies = 'ListUserPolicies',
|
||||
IamListUsers = 'ListUsers',
|
||||
IamListUserTags = 'ListUserTags',
|
||||
IamListVirtualMFADevices = 'ListVirtualMFADevices',
|
||||
IamPutGroupPolicy = 'PutGroupPolicy',
|
||||
IamPutRolePermissionsBoundary = 'PutRolePermissionsBoundary',
|
||||
IamPutRolePolicy = 'PutRolePolicy',
|
||||
IamPutUserPermissionsBoundary = 'PutUserPermissionsBoundary',
|
||||
IamPutUserPolicy = 'PutUserPolicy',
|
||||
IamRemoveClientIDFromOpenIDConnectProvider = 'RemoveClientIDFromOpenIDConnectProvider',
|
||||
IamRemoveRoleFromInstanceProfile = 'RemoveRoleFromInstanceProfile',
|
||||
IamRemoveUserFromGroup = 'RemoveUserFromGroup',
|
||||
IamResetServiceSpecificCredential = 'ResetServiceSpecificCredential',
|
||||
IamResyncMFADevice = 'ResyncMFADevice',
|
||||
IamSetDefaultPolicyVersion = 'SetDefaultPolicyVersion',
|
||||
IamSetSecurityTokenServicePreferences = 'SetSecurityTokenServicePreferences',
|
||||
IamSimulateCustomPolicy = 'SimulateCustomPolicy',
|
||||
IamSimulatePrincipalPolicy = 'SimulatePrincipalPolicy',
|
||||
IamTagInstanceProfile = 'TagInstanceProfile',
|
||||
IamTagMFADevice = 'TagMFADevice',
|
||||
IamTagOpenIDConnectProvider = 'TagOpenIDConnectProvider',
|
||||
IamTagPolicy = 'TagPolicy',
|
||||
IamTagRole = 'TagRole',
|
||||
IamTagSAMLProvider = 'TagSAMLProvider',
|
||||
IamTagServerCertificate = 'TagServerCertificate',
|
||||
IamTagUser = 'TagUser',
|
||||
IamUntagInstanceProfile = 'UntagInstanceProfile',
|
||||
IamUntagMFADevice = 'UntagMFADevice',
|
||||
IamUntagOpenIDConnectProvider = 'UntagOpenIDConnectProvider',
|
||||
IamUntagPolicy = 'UntagPolicy',
|
||||
IamUntagRole = 'UntagRole',
|
||||
IamUntagSAMLProvider = 'UntagSAMLProvider',
|
||||
IamUntagServerCertificate = 'UntagServerCertificate',
|
||||
IamUntagUser = 'UntagUser',
|
||||
IamUpdateAccessKey = 'UpdateAccessKey',
|
||||
IamUpdateAccountPasswordPolicy = 'UpdateAccountPasswordPolicy',
|
||||
IamUpdateAssumeRolePolicy = 'UpdateAssumeRolePolicy',
|
||||
IamUpdateGroup = 'UpdateGroup',
|
||||
IamUpdateLoginProfile = 'UpdateLoginProfile',
|
||||
IamUpdateOpenIDConnectProviderThumbprint = 'UpdateOpenIDConnectProviderThumbprint',
|
||||
IamUpdateRole = 'UpdateRole',
|
||||
IamUpdateRoleDescription = 'UpdateRoleDescription',
|
||||
IamUpdateSAMLProvider = 'UpdateSAMLProvider',
|
||||
IamUpdateServerCertificate = 'UpdateServerCertificate',
|
||||
IamUpdateServiceSpecificCredential = 'UpdateServiceSpecificCredential',
|
||||
IamUpdateSigningCertificate = 'UpdateSigningCertificate',
|
||||
IamUpdateSSHPublicKey = 'UpdateSSHPublicKey',
|
||||
IamUpdateUser = 'UpdateUser',
|
||||
IamUploadServerCertificate = 'UploadServerCertificate',
|
||||
IamUploadSigningCertificate = 'UploadSigningCertificate',
|
||||
IamUploadSSHPublicKey = 'UploadSSHPublicKey',
|
||||
|
||||
// KMS
|
||||
KmsCancelKeyDeletion = 'CancelKeyDeletion',
|
||||
KmsConnectCustomKeyStore = 'ConnectCustomKeyStore',
|
||||
KmsCreateAlias = 'CreateAlias',
|
||||
KmsCreateCustomKeyStore = 'CreateCustomKeyStore',
|
||||
KmsCreateGrant = 'CreateGrant',
|
||||
KmsCreateKey = 'CreateKey',
|
||||
KmsDecrypt = 'Decrypt',
|
||||
KmsDeleteAlias = 'DeleteAlias',
|
||||
KmsDeleteCustomKeyStore = 'DeleteCustomKeyStore',
|
||||
KmsDeleteImportedKeyMaterial = 'DeleteImportedKeyMaterial',
|
||||
KmsDescribeCustomKeyStores = 'DescribeCustomKeyStores',
|
||||
KmsDescribeKey = 'DescribeKey',
|
||||
KmsDisableKey = 'DisableKey',
|
||||
KmsDisableKeyRotation = 'DisableKeyRotation',
|
||||
KmsDisconnectCustomKeyStore = 'DisconnectCustomKeyStore',
|
||||
KmsEnableKey = 'EnableKey',
|
||||
KmsEnableKeyRotation = 'EnableKeyRotation',
|
||||
KmsEncrypt = 'Encrypt',
|
||||
KmsGenerateDataKey = 'GenerateDataKey',
|
||||
KmsGenerateDataKeyPair = 'GenerateDataKeyPair',
|
||||
KmsGenerateDataKeyPairWithoutPlaintext = 'GenerateDataKeyPairWithoutPlaintext',
|
||||
KmsGenerateDataKeyWithoutPlaintext = 'GenerateDataKeyWithoutPlaintext',
|
||||
KmsGenerateMac = 'GenerateMac',
|
||||
KmsGenerateRandom = 'GenerateRandom',
|
||||
KmsGetKeyPolicy = 'GetKeyPolicy',
|
||||
KmsGetKeyRotationStatus = 'GetKeyRotationStatus',
|
||||
KmsGetParametersForImport = 'GetParametersForImport',
|
||||
KmsGetPublicKey = 'GetPublicKey',
|
||||
KmsImportKeyMaterial = 'ImportKeyMaterial',
|
||||
KmsListAliases = 'ListAliases',
|
||||
KmsListGrants = 'ListGrants',
|
||||
KmsListKeyPolicies = 'ListKeyPolicies',
|
||||
KmsListKeys = 'ListKeys',
|
||||
KmsListResourceTags = 'ListResourceTags',
|
||||
KmsListRetirableGrants = 'ListRetirableGrants',
|
||||
KmsPutKeyPolicy = 'PutKeyPolicy',
|
||||
KmsReEncrypt = 'ReEncrypt',
|
||||
KmsReplicateKey = 'ReplicateKey',
|
||||
KmsRetireGrant = 'RetireGrant',
|
||||
KmsRevokeGrant = 'RevokeGrant',
|
||||
KmsScheduleKeyDeletion = 'ScheduleKeyDeletion',
|
||||
KmsSign = 'Sign',
|
||||
KmsTagResource = 'TagResource',
|
||||
KmsUntagResource = 'UntagResource',
|
||||
KmsUpdateAlias = 'UpdateAlias',
|
||||
KmsUpdateCustomKeyStore = 'UpdateCustomKeyStore',
|
||||
KmsUpdateKeyDescription = 'UpdateKeyDescription',
|
||||
KmsUpdatePrimaryRegion = 'UpdatePrimaryRegion',
|
||||
KmsVerify = 'Verify',
|
||||
KmsVerifyMac = 'VerifyMac',
|
||||
KmsCancelKeyDeletion = 'TrentService.CancelKeyDeletion',
|
||||
KmsConnectCustomKeyStore = 'TrentService.ConnectCustomKeyStore',
|
||||
KmsCreateAlias = 'TrentService.CreateAlias',
|
||||
KmsCreateCustomKeyStore = 'TrentService.CreateCustomKeyStore',
|
||||
KmsCreateGrant = 'TrentService.CreateGrant',
|
||||
KmsCreateKey = 'TrentService.CreateKey',
|
||||
KmsDecrypt = 'TrentService.Decrypt',
|
||||
KmsDeleteAlias = 'TrentService.DeleteAlias',
|
||||
KmsDeleteCustomKeyStore = 'TrentService.DeleteCustomKeyStore',
|
||||
KmsDeleteImportedKeyMaterial = 'TrentService.DeleteImportedKeyMaterial',
|
||||
KmsDescribeCustomKeyStores = 'TrentService.DescribeCustomKeyStores',
|
||||
KmsDescribeKey = 'TrentService.DescribeKey',
|
||||
KmsDisableKey = 'TrentService.DisableKey',
|
||||
KmsDisableKeyRotation = 'TrentService.DisableKeyRotation',
|
||||
KmsDisconnectCustomKeyStore = 'TrentService.DisconnectCustomKeyStore',
|
||||
KmsEnableKey = 'TrentService.EnableKey',
|
||||
KmsEnableKeyRotation = 'TrentService.EnableKeyRotation',
|
||||
KmsEncrypt = 'TrentService.Encrypt',
|
||||
KmsGenerateDataKey = 'TrentService.GenerateDataKey',
|
||||
KmsGenerateDataKeyPair = 'TrentService.GenerateDataKeyPair',
|
||||
KmsGenerateDataKeyPairWithoutPlaintext = 'TrentService.GenerateDataKeyPairWithoutPlaintext',
|
||||
KmsGenerateDataKeyWithoutPlaintext = 'TrentService.GenerateDataKeyWithoutPlaintext',
|
||||
KmsGenerateMac = 'TrentService.GenerateMac',
|
||||
KmsGenerateRandom = 'TrentService.GenerateRandom',
|
||||
KmsGetKeyPolicy = 'TrentService.GetKeyPolicy',
|
||||
KmsGetKeyRotationStatus = 'TrentService.GetKeyRotationStatus',
|
||||
KmsGetParametersForImport = 'TrentService.GetParametersForImport',
|
||||
KmsGetPublicKey = 'TrentService.GetPublicKey',
|
||||
KmsImportKeyMaterial = 'TrentService.ImportKeyMaterial',
|
||||
KmsListAliases = 'TrentService.ListAliases',
|
||||
KmsListGrants = 'TrentService.ListGrants',
|
||||
KmsListKeyPolicies = 'TrentService.ListKeyPolicies',
|
||||
KmsListKeys = 'TrentService.ListKeys',
|
||||
KmsListResourceTags = 'TrentService.ListResourceTags',
|
||||
KmsListRetirableGrants = 'TrentService.ListRetirableGrants',
|
||||
KmsPutKeyPolicy = 'TrentService.PutKeyPolicy',
|
||||
KmsReEncrypt = 'TrentService.ReEncrypt',
|
||||
KmsReplicateKey = 'TrentService.ReplicateKey',
|
||||
KmsRetireGrant = 'TrentService.RetireGrant',
|
||||
KmsRevokeGrant = 'TrentService.RevokeGrant',
|
||||
KmsScheduleKeyDeletion = 'TrentService.ScheduleKeyDeletion',
|
||||
KmsSign = 'TrentService.Sign',
|
||||
KmsTagResource = 'TrentService.TagResource',
|
||||
KmsUntagResource = 'TrentService.UntagResource',
|
||||
KmsUpdateAlias = 'TrentService.UpdateAlias',
|
||||
KmsUpdateCustomKeyStore = 'TrentService.UpdateCustomKeyStore',
|
||||
KmsUpdateKeyDescription = 'TrentService.UpdateKeyDescription',
|
||||
KmsUpdatePrimaryRegion = 'TrentService.UpdatePrimaryRegion',
|
||||
KmsVerify = 'TrentService.Verify',
|
||||
KmsVerifyMac = 'TrentService.VerifyMac',
|
||||
|
||||
// SecretsManager
|
||||
SecretsManagerCancelRotateSecret = 'secretsmanager.CancelRotateSecret',
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export class AppController {
|
|||
}, {})
|
||||
|
||||
const queryParams = { __path: request.path, ...body, ...lowerCasedHeaders };
|
||||
console.log({ queryParams })
|
||||
const actionKey = queryParams['x-amz-target'] ? 'x-amz-target' : 'Action';
|
||||
const { error: actionError } = Joi.object({
|
||||
[actionKey]: Joi.string().valid(...Object.values(Action)).required(),
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import { AuditInterceptor } from './audit/audit.interceptor';
|
|||
import { KmsModule } from './kms/kms.module';
|
||||
import { KMSHandlers } from './kms/kms.constants';
|
||||
import { configValidator } from './config/config.validator';
|
||||
import { IamModule } from './iam/iam.module';
|
||||
import { IAMHandlers } from './iam/iam.constants';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
|
|
@ -35,6 +37,7 @@ import { configValidator } from './config/config.validator';
|
|||
}),
|
||||
}),
|
||||
TypeOrmModule.forFeature([Audit]),
|
||||
IamModule,
|
||||
KmsModule,
|
||||
SecretsManagerModule,
|
||||
SnsModule,
|
||||
|
|
@ -54,6 +57,7 @@ import { configValidator } from './config/config.validator';
|
|||
SqsHandlers,
|
||||
SecretsManagerHandlers,
|
||||
KMSHandlers,
|
||||
IAMHandlers,
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
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 * as uuid from 'uuid';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
import { IamRole } from './iam-role.entity';
|
||||
|
||||
type QueryParams = {
|
||||
PolicyArn: string;
|
||||
RoleName: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AttachRolePolicyHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamRole)
|
||||
private readonly roleRepo: Repository<IamRole>,
|
||||
@InjectRepository(IamRolePolicyAttachment)
|
||||
private readonly attachRepo: Repository<IamRolePolicyAttachment>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamAttachRolePolicy;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
PolicyArn: Joi.string().required(),
|
||||
RoleName: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ PolicyArn, RoleName }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId} });
|
||||
|
||||
await this.attachRepo.create({
|
||||
id: uuid.v4(),
|
||||
policyArn: PolicyArn,
|
||||
roleId: role.id,
|
||||
accountId: awsProperties.accountId,
|
||||
}).save();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
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 * as uuid from 'uuid';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
import { breakdownArn } from '../util/breakdown-arn';
|
||||
|
||||
type QueryParams = {
|
||||
PolicyArn: string;
|
||||
PolicyDocument: string;
|
||||
SetAsDefault: boolean;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CreatePolicyVersionHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamPolicy)
|
||||
private readonly policyRepo: Repository<IamPolicy>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamCreatePolicyVersion;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
PolicyArn: Joi.string().required(),
|
||||
PolicyDocument: Joi.string().required(),
|
||||
SetAsDefault: Joi.boolean().required(),
|
||||
});
|
||||
|
||||
protected async handle({ PolicyArn, PolicyDocument, SetAsDefault }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const { identifier, accountId } = breakdownArn(PolicyArn);
|
||||
const [_policy, name] = identifier.split('/');
|
||||
const currentPolicy = await this.policyRepo.findOne({ where: { accountId, name, isDefault: true } });
|
||||
|
||||
if (SetAsDefault) {
|
||||
await this.policyRepo.update({ accountId, name }, { isDefault: false })
|
||||
}
|
||||
|
||||
const policy = await this.policyRepo.create({
|
||||
id: uuid.v4(),
|
||||
name: name,
|
||||
isDefault: SetAsDefault,
|
||||
version: currentPolicy.version + 1,
|
||||
document: PolicyDocument,
|
||||
accountId: awsProperties.accountId,
|
||||
}).save();
|
||||
|
||||
return {
|
||||
PolicyVersion: {
|
||||
IsDefaultVersion: policy.isDefault,
|
||||
VersionId: `v${policy.version}`,
|
||||
CreateDate: new Date(policy.createdAt).toISOString(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
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 * as uuid from 'uuid';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
|
||||
type QueryParams = {
|
||||
PolicyName: string;
|
||||
PolicyDocument: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CreatePolicyHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamPolicy)
|
||||
private readonly policyRepo: Repository<IamPolicy>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamCreatePolicy;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
PolicyName: Joi.string().required(),
|
||||
PolicyDocument: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ PolicyName, PolicyDocument }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const policy = await this.policyRepo.create({
|
||||
id: uuid.v4(),
|
||||
name: PolicyName,
|
||||
document: PolicyDocument,
|
||||
accountId: awsProperties.accountId,
|
||||
}).save();
|
||||
|
||||
return {
|
||||
Policy: {
|
||||
PolicyName: policy.name,
|
||||
DefaultVersionId: 'v1',
|
||||
PolicyId: policy.id,
|
||||
Path: '/',
|
||||
Arn: policy.arn,
|
||||
AttachmentCount: 0,
|
||||
CreateDate: new Date(policy.createdAt).toISOString(),
|
||||
UpdateDate: new Date(policy.updatedAt).toISOString(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
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 { IamRole } from './iam-role.entity';
|
||||
import * as uuid from 'uuid';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
|
||||
type QueryParams = {
|
||||
RoleName: string;
|
||||
Path: string;
|
||||
AssumeRolePolicyDocument: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CreateRoleHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamRole)
|
||||
private readonly roleRepo: Repository<IamRole>,
|
||||
@InjectRepository(IamPolicy)
|
||||
private readonly policyRepo: Repository<IamPolicy>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamCreateRole;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
RoleName: Joi.string().required(),
|
||||
Path: Joi.string().required(),
|
||||
AssumeRolePolicyDocument: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ RoleName, Path, AssumeRolePolicyDocument }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const policy = await this.policyRepo.create({
|
||||
id: uuid.v4(),
|
||||
name: `${RoleName}-AssumeRolePolicyDocument`,
|
||||
document: AssumeRolePolicyDocument,
|
||||
accountId: awsProperties.accountId,
|
||||
}).save();
|
||||
|
||||
const id = uuid.v4();
|
||||
|
||||
await this.roleRepo.create({
|
||||
id,
|
||||
roleName: RoleName,
|
||||
path: Path,
|
||||
accountId: awsProperties.accountId,
|
||||
assumeRolePolicyDocumentId: policy.id,
|
||||
}).save();
|
||||
|
||||
const role = await this.roleRepo.findOne({ where: { id }});
|
||||
|
||||
return {
|
||||
Role: role.metadata,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { Injectable, NotFoundException } 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 { IamPolicy } from './iam-policy.entity';
|
||||
import { breakdownArn } from '../util/breakdown-arn';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
|
||||
type QueryParams = {
|
||||
PolicyArn: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class GetPolicyHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamPolicy)
|
||||
private readonly policyRepo: Repository<IamPolicy>,
|
||||
@InjectRepository(IamRolePolicyAttachment)
|
||||
private readonly attachmentRepo: Repository<IamRolePolicyAttachment>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamGetPolicy;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
PolicyArn: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ PolicyArn }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const { identifier, accountId } = breakdownArn(PolicyArn);
|
||||
const [_policy, name] = identifier.split('/');
|
||||
const policy = await this.policyRepo.findOne({ where: { name, accountId, isDefault: true }});
|
||||
|
||||
if (!policy) {
|
||||
throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.');
|
||||
}
|
||||
|
||||
const attachmentCount = await this.attachmentRepo.count({ where: { policyArn: policy.arn } });
|
||||
|
||||
return {
|
||||
Policy: {
|
||||
PolicyName: policy.name,
|
||||
DefaultVersionId: `v${policy.version}`,
|
||||
PolicyId: policy.id,
|
||||
Path: '/',
|
||||
Arn: policy.arn,
|
||||
AttachmentCount: attachmentCount,
|
||||
CreateDate: new Date(policy.createdAt).toISOString(),
|
||||
UpdateDate: new Date(policy.updatedAt).toISOString(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { Injectable, NotFoundException } 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 { IamRole } from './iam-role.entity';
|
||||
|
||||
type QueryParams = {
|
||||
RoleName: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class GetRoleHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamRole)
|
||||
private readonly roleRepo: Repository<IamRole>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamGetRole;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
RoleName: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } });
|
||||
|
||||
if (!role) {
|
||||
throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.');
|
||||
}
|
||||
|
||||
return {
|
||||
Role: role.metadata,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, OneToMany, OneToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
import { IamRole } from './iam-role.entity';
|
||||
|
||||
@Entity({ name: 'iam_policy' })
|
||||
export class IamPolicy extends BaseEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: string;
|
||||
|
||||
@Column({ default: 1 })
|
||||
version: number;
|
||||
|
||||
@Column({ name: 'is_default', default: true })
|
||||
isDefault: boolean;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
document: string;
|
||||
|
||||
@Column({ name: 'account_id', nullable: false })
|
||||
accountId: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: string;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: string;
|
||||
|
||||
@OneToOne(() => IamRole, role => role.assumeRolePolicyDocument)
|
||||
iamRole: IamRole;
|
||||
|
||||
get arn() {
|
||||
return `arn:aws:iam::${this.accountId}:policy/${this.name}`;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
|
||||
@Entity({ name: 'iam_role_policy_attachment' })
|
||||
export class IamRolePolicyAttachment extends BaseEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: string;
|
||||
|
||||
@Column({ name: 'policy_arn' })
|
||||
policyArn: string;
|
||||
|
||||
@Column({ name: 'role_name' })
|
||||
roleId: string;
|
||||
|
||||
@Column({ name: 'account_id'})
|
||||
accountId: string;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, OneToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
|
||||
@Entity({ name: 'iam_role' })
|
||||
export class IamRole extends BaseEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: string
|
||||
|
||||
@Column({ name: 'role_name' })
|
||||
roleName: string;
|
||||
|
||||
@Column()
|
||||
path: string;
|
||||
|
||||
@Column({ name: 'assume_role_policy_document_id', nullable: false })
|
||||
assumeRolePolicyDocumentId: string;
|
||||
|
||||
@Column({ name: 'account_id', nullable: false })
|
||||
accountId: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: string;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: string;
|
||||
|
||||
@OneToOne(() => IamPolicy, (policy) => policy.id, { eager: true })
|
||||
@JoinColumn({ name: 'assume_role_policy_document_id' })
|
||||
assumeRolePolicyDocument: IamPolicy;
|
||||
|
||||
get arn() {
|
||||
const identifier = this.path.split('/');
|
||||
identifier.push(this.roleName);
|
||||
return `arn:aws:iam::${this.accountId}:role/${identifier.join('/')}`;
|
||||
}
|
||||
|
||||
get metadata() {
|
||||
return {
|
||||
Path: this.path,
|
||||
Arn: this.arn,
|
||||
RoleName: this.roleName,
|
||||
AssumeRolePolicyDocument: this.assumeRolePolicyDocument.document,
|
||||
CreateDate: new Date(this.createdAt).toISOString(),
|
||||
RoleId: this.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { AbstractActionHandler } from '../abstract-action.handler';
|
||||
import { Action } from '../action.enum';
|
||||
|
||||
export type IAMHandlers = Record<Action, AbstractActionHandler>;
|
||||
export const IAMHandlers = Symbol.for('IAMHandlers');
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Format } from '../abstract-action.handler';
|
||||
import { Action } from '../action.enum';
|
||||
import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module';
|
||||
import { DefaultActionHandlerProvider } from '../default-action-handler/default-action-handler.provider';
|
||||
import { ExistingActionHandlersProvider } from '../default-action-handler/existing-action-handlers.provider';
|
||||
import { AttachRolePolicyHandler } from './attach-role-policy.handler';
|
||||
import { CreatePolicyVersionHandler } from './create-policy-version.handler';
|
||||
import { CreatePolicyHandler } from './create-policy.handler';
|
||||
import { CreateRoleHandler } from './create-role.handler';
|
||||
import { GetPolicyHandler } from './get-policy.handler';
|
||||
import { GetRoleHandler } from './get-role.handler';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
import { IamRole } from './iam-role.entity';
|
||||
import { IAMHandlers } from './iam.constants';
|
||||
import { ListAttachedRolePoliciesHandler } from './list-attached-role-policies';
|
||||
import { ListRolePoliciesHandler } from './list-role-policies.handler';
|
||||
|
||||
const handlers = [
|
||||
AttachRolePolicyHandler,
|
||||
CreatePolicyHandler,
|
||||
CreatePolicyVersionHandler,
|
||||
CreateRoleHandler,
|
||||
GetPolicyHandler,
|
||||
GetRoleHandler,
|
||||
ListAttachedRolePoliciesHandler,
|
||||
ListRolePoliciesHandler,
|
||||
]
|
||||
|
||||
const actions = [
|
||||
Action.IamAddClientIDToOpenIDConnectProvider,
|
||||
Action.IamAddRoleToInstanceProfile,
|
||||
Action.IamAddUserToGroup,
|
||||
Action.IamAttachGroupPolicy,
|
||||
Action.IamAttachRolePolicy,
|
||||
Action.IamAttachUserPolicy,
|
||||
Action.IamChangePassword,
|
||||
Action.IamCreateAccessKey,
|
||||
Action.IamCreateAccountAlias,
|
||||
Action.IamCreateGroup,
|
||||
Action.IamCreateInstanceProfile,
|
||||
Action.IamCreateLoginProfile,
|
||||
Action.IamCreateOpenIDConnectProvider,
|
||||
Action.IamCreatePolicy,
|
||||
Action.IamCreatePolicyVersion,
|
||||
Action.IamCreateRole,
|
||||
Action.IamCreateSAMLProvider,
|
||||
Action.IamCreateServiceLinkedRole,
|
||||
Action.IamCreateServiceSpecificCredential,
|
||||
Action.IamCreateUser,
|
||||
Action.IamCreateVirtualMFADevice,
|
||||
Action.IamDeactivateMFADevice,
|
||||
Action.IamDeleteAccessKey,
|
||||
Action.IamDeleteAccountAlias,
|
||||
Action.IamDeleteAccountPasswordPolicy,
|
||||
Action.IamDeleteGroup,
|
||||
Action.IamDeleteGroupPolicy,
|
||||
Action.IamDeleteInstanceProfile,
|
||||
Action.IamDeleteLoginProfile,
|
||||
Action.IamDeleteOpenIDConnectProvider,
|
||||
Action.IamDeletePolicy,
|
||||
Action.IamDeletePolicyVersion,
|
||||
Action.IamDeleteRole,
|
||||
Action.IamDeleteRolePermissionsBoundary,
|
||||
Action.IamDeleteRolePolicy,
|
||||
Action.IamDeleteSAMLProvider,
|
||||
Action.IamDeleteServerCertificate,
|
||||
Action.IamDeleteServiceLinkedRole,
|
||||
Action.IamDeleteServiceSpecificCredential,
|
||||
Action.IamDeleteSigningCertificate,
|
||||
Action.IamDeleteSSHPublicKey,
|
||||
Action.IamDeleteUser,
|
||||
Action.IamDeleteUserPermissionsBoundary,
|
||||
Action.IamDeleteUserPolicy,
|
||||
Action.IamDeleteVirtualMFADevice,
|
||||
Action.IamDetachGroupPolicy,
|
||||
Action.IamDetachRolePolicy,
|
||||
Action.IamDetachUserPolicy,
|
||||
Action.IamEnableMFADevice,
|
||||
Action.IamGenerateCredentialReport,
|
||||
Action.IamGenerateOrganizationsAccessReport,
|
||||
Action.IamGenerateServiceLastAccessedDetails,
|
||||
Action.IamGetAccessKeyLastUsed,
|
||||
Action.IamGetAccountAuthorizationDetails,
|
||||
Action.IamGetAccountPasswordPolicy,
|
||||
Action.IamGetAccountSummary,
|
||||
Action.IamGetContextKeysForCustomPolicy,
|
||||
Action.IamGetContextKeysForPrincipalPolicy,
|
||||
Action.IamGetCredentialReport,
|
||||
Action.IamGetGroup,
|
||||
Action.IamGetGroupPolicy,
|
||||
Action.IamGetInstanceProfile,
|
||||
Action.IamGetLoginProfile,
|
||||
Action.IamGetOpenIDConnectProvider,
|
||||
Action.IamGetOrganizationsAccessReport,
|
||||
Action.IamGetPolicy,
|
||||
Action.IamGetPolicyVersion,
|
||||
Action.IamGetRole,
|
||||
Action.IamGetRolePolicy,
|
||||
Action.IamGetSAMLProvider,
|
||||
Action.IamGetServerCertificate,
|
||||
Action.IamGetServiceLastAccessedDetails,
|
||||
Action.IamGetServiceLastAccessedDetailsWithEntities,
|
||||
Action.IamGetServiceLinkedRoleDeletionStatus,
|
||||
Action.IamGetSSHPublicKey,
|
||||
Action.IamGetUser,
|
||||
Action.IamGetUserPolicy,
|
||||
Action.IamListAccessKeys,
|
||||
Action.IamListAccountAliases,
|
||||
Action.IamListAttachedGroupPolicies,
|
||||
Action.IamListAttachedRolePolicies,
|
||||
Action.IamListAttachedUserPolicies,
|
||||
Action.IamListEntitiesForPolicy,
|
||||
Action.IamListGroupPolicies,
|
||||
Action.IamListGroups,
|
||||
Action.IamListGroupsForUser,
|
||||
Action.IamListInstanceProfiles,
|
||||
Action.IamListInstanceProfilesForRole,
|
||||
Action.IamListInstanceProfileTags,
|
||||
Action.IamListMFADevices,
|
||||
Action.IamListMFADeviceTags,
|
||||
Action.IamListOpenIDConnectProviders,
|
||||
Action.IamListOpenIDConnectProviderTags,
|
||||
Action.IamListPolicies,
|
||||
Action.IamListPoliciesGrantingServiceAccess,
|
||||
Action.IamListPolicyTags,
|
||||
Action.IamListPolicyVersions,
|
||||
Action.IamListRolePolicies,
|
||||
Action.IamListRoles,
|
||||
Action.IamListRoleTags,
|
||||
Action.IamListSAMLProviders,
|
||||
Action.IamListSAMLProviderTags,
|
||||
Action.IamListServerCertificates,
|
||||
Action.IamListServerCertificateTags,
|
||||
Action.IamListServiceSpecificCredentials,
|
||||
Action.IamListSigningCertificates,
|
||||
Action.IamListSSHPublicKeys,
|
||||
Action.IamListUserPolicies,
|
||||
Action.IamListUsers,
|
||||
Action.IamListUserTags,
|
||||
Action.IamListVirtualMFADevices,
|
||||
Action.IamPutGroupPolicy,
|
||||
Action.IamPutRolePermissionsBoundary,
|
||||
Action.IamPutRolePolicy,
|
||||
Action.IamPutUserPermissionsBoundary,
|
||||
Action.IamPutUserPolicy,
|
||||
Action.IamRemoveClientIDFromOpenIDConnectProvider,
|
||||
Action.IamRemoveRoleFromInstanceProfile,
|
||||
Action.IamRemoveUserFromGroup,
|
||||
Action.IamResetServiceSpecificCredential,
|
||||
Action.IamResyncMFADevice,
|
||||
Action.IamSetDefaultPolicyVersion,
|
||||
Action.IamSetSecurityTokenServicePreferences,
|
||||
Action.IamSimulateCustomPolicy,
|
||||
Action.IamSimulatePrincipalPolicy,
|
||||
Action.IamTagInstanceProfile,
|
||||
Action.IamTagMFADevice,
|
||||
Action.IamTagOpenIDConnectProvider,
|
||||
Action.IamTagPolicy,
|
||||
Action.IamTagRole,
|
||||
Action.IamTagSAMLProvider,
|
||||
Action.IamTagServerCertificate,
|
||||
Action.IamTagUser,
|
||||
Action.IamUntagInstanceProfile,
|
||||
Action.IamUntagMFADevice,
|
||||
Action.IamUntagOpenIDConnectProvider,
|
||||
Action.IamUntagPolicy,
|
||||
Action.IamUntagRole,
|
||||
Action.IamUntagSAMLProvider,
|
||||
Action.IamUntagServerCertificate,
|
||||
Action.IamUntagUser,
|
||||
Action.IamUpdateAccessKey,
|
||||
Action.IamUpdateAccountPasswordPolicy,
|
||||
Action.IamUpdateAssumeRolePolicy,
|
||||
Action.IamUpdateGroup,
|
||||
Action.IamUpdateLoginProfile,
|
||||
Action.IamUpdateOpenIDConnectProviderThumbprint,
|
||||
Action.IamUpdateRole,
|
||||
Action.IamUpdateRoleDescription,
|
||||
Action.IamUpdateSAMLProvider,
|
||||
Action.IamUpdateServerCertificate,
|
||||
Action.IamUpdateServiceSpecificCredential,
|
||||
Action.IamUpdateSigningCertificate,
|
||||
Action.IamUpdateSSHPublicKey,
|
||||
Action.IamUpdateUser,
|
||||
Action.IamUploadServerCertificate,
|
||||
Action.IamUploadSigningCertificate,
|
||||
Action.IamUploadSSHPublicKey,
|
||||
]
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([IamPolicy, IamRole, IamRolePolicyAttachment]),
|
||||
AwsSharedEntitiesModule,
|
||||
],
|
||||
providers: [
|
||||
...handlers,
|
||||
ExistingActionHandlersProvider(handlers),
|
||||
DefaultActionHandlerProvider(IAMHandlers, Format.Xml, actions),
|
||||
],
|
||||
exports: [IAMHandlers],
|
||||
})
|
||||
export class IamModule {}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import { Injectable, NotFoundException } 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 { In, Repository } from 'typeorm';
|
||||
import { IamRole } from './iam-role.entity';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
import { IamPolicy } from './iam-policy.entity';
|
||||
import { breakdownArn } from '../util/breakdown-arn';
|
||||
|
||||
type QueryParams = {
|
||||
RoleName: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ListAttachedRolePoliciesHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamRole)
|
||||
private readonly roleRepo: Repository<IamRole>,
|
||||
@InjectRepository(IamPolicy)
|
||||
private readonly policyRepo: Repository<IamPolicy>,
|
||||
@InjectRepository(IamRolePolicyAttachment)
|
||||
private readonly attachmentRepo: Repository<IamRolePolicyAttachment>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamListAttachedRolePolicies;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
RoleName: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } });
|
||||
|
||||
if (!role) {
|
||||
throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.');
|
||||
}
|
||||
|
||||
const attachments = await this.attachmentRepo.find({ where: { roleId: role.id } })
|
||||
const policyIds = attachments.map(({ policyArn }) => breakdownArn(policyArn)).map(({ identifier }) => identifier.split('/')[1]);
|
||||
const policies = await this.policyRepo.find({ where: { name: In(policyIds), isDefault: true } });
|
||||
|
||||
return {
|
||||
AttachedPolicies: {
|
||||
member: [role.assumeRolePolicyDocument, ...policies].map(p => ({
|
||||
PolicyName: p.name,
|
||||
PolicyArn: p.arn,
|
||||
})),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { Injectable, NotFoundException } 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 { IamRole } from './iam-role.entity';
|
||||
import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity';
|
||||
|
||||
type QueryParams = {
|
||||
RoleName: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ListRolePoliciesHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(IamRole)
|
||||
private readonly roleRepo: Repository<IamRole>,
|
||||
@InjectRepository(IamRolePolicyAttachment)
|
||||
private readonly attachmentRepo: Repository<IamRolePolicyAttachment>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Xml;
|
||||
action = Action.IamListRolePolicies;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
RoleName: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } });
|
||||
|
||||
if (!role) {
|
||||
throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.');
|
||||
}
|
||||
|
||||
return {
|
||||
PolicyNames: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler';
|
||||
import { Action } from '../action.enum';
|
||||
import * as Joi from 'joi';
|
||||
import { KmsKeyAlias } from './kms-key-alias.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
type QueryParams = {
|
||||
AliasName: string;
|
||||
TargetKeyId: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CreateAliasHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(KmsKeyAlias)
|
||||
private readonly aliasRepo: Repository<KmsKeyAlias>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Json;
|
||||
action = Action.KmsCreateAlias;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
AliasName: Joi.string().required(),
|
||||
TargetKeyId: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ AliasName, TargetKeyId }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
await this.aliasRepo.save({
|
||||
name: AliasName.split('/')[1],
|
||||
targetKeyId: TargetKeyId,
|
||||
accountId: awsProperties.accountId,
|
||||
region: awsProperties.region,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler';
|
||||
import { Action } from '../action.enum';
|
||||
import * as Joi from 'joi';
|
||||
import { KmsKeyAlias } from './kms-key-alias.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { KmsKey } from './kms-key.entity';
|
||||
import { ArnParts, breakdownArn } from '../util/breakdown-arn';
|
||||
|
||||
type QueryParams = {
|
||||
KeyId: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DescribeKeyHandler extends AbstractActionHandler<QueryParams> {
|
||||
|
||||
constructor(
|
||||
@InjectRepository(KmsKeyAlias)
|
||||
private readonly aliasRepo: Repository<KmsKeyAlias>,
|
||||
@InjectRepository(KmsKey)
|
||||
private readonly keyRepo: Repository<KmsKey>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
format = Format.Json;
|
||||
action = Action.KmsDescribeKey;
|
||||
validator = Joi.object<QueryParams, true>({
|
||||
KeyId: Joi.string().required(),
|
||||
});
|
||||
|
||||
protected async handle({ KeyId }: QueryParams, awsProperties: AwsProperties) {
|
||||
|
||||
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.findKeyIdFromAlias(pk, searchable);
|
||||
|
||||
|
||||
const keyRecord = await this.keyRepo.findOne({ where: {
|
||||
id: await keyId,
|
||||
region: searchable.region,
|
||||
accountId: searchable.accountId,
|
||||
}});
|
||||
|
||||
return {
|
||||
KeyMetadata: keyRecord.metadata,
|
||||
}
|
||||
}
|
||||
|
||||
private async findKeyIdFromAlias(alias: string ,arn: ArnParts): Promise<string> {
|
||||
const record = await this.aliasRepo.findOne({ where: {
|
||||
name: alias,
|
||||
accountId: arn.accountId,
|
||||
region: arn.region,
|
||||
}});
|
||||
return record.targetKeyId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity({ name: 'kms_key_alias' })
|
||||
export class KmsKeyAlias extends BaseEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
name: string;
|
||||
|
||||
@Column({ name: 'target_key_id' })
|
||||
targetKeyId: string;
|
||||
|
||||
@Column({ name: 'account_id', nullable: false })
|
||||
accountId: string;
|
||||
|
||||
@Column({ name: 'region', nullable: false })
|
||||
region: string;
|
||||
|
||||
get arn() {
|
||||
return `arn:aws:kms:${this.region}:${this.accountId}:alias/${this.name}`;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity({ name: 'kms_key'})
|
||||
export class KmsKey extends BaseEntity {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: string;
|
||||
|
||||
@Column({ name: 'usage' })
|
||||
usage: string;
|
||||
|
||||
@Column({ name: 'description' })
|
||||
description: string;
|
||||
|
||||
@Column({ name: 'key_spec' })
|
||||
keySpec: string;
|
||||
|
||||
@Column({ name: 'key' })
|
||||
key: string;
|
||||
|
||||
@Column({ name: 'account_id', nullable: false })
|
||||
accountId: string;
|
||||
|
||||
@Column({ name: 'region', nullable: false })
|
||||
region: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: string;
|
||||
|
||||
get arn() {
|
||||
return `arn:aws:kms:${this.region}:${this.accountId}:key/${this.id}`;
|
||||
}
|
||||
|
||||
get metadata() {
|
||||
return {
|
||||
AWSAccountId: this.accountId,
|
||||
KeyId: this.id,
|
||||
Arn: this.arn,
|
||||
CreationDate: new Date(this.createdAt).toISOString(),
|
||||
Enabled: true,
|
||||
Description: this.description,
|
||||
KeyUsage: this.usage,
|
||||
KeyState: 'Enabled',
|
||||
KeyManager: "CUSTOMER",
|
||||
CustomerMasterKeySpec: this.keySpec,
|
||||
KeySpec: this.keySpec,
|
||||
DeletionDate: null,
|
||||
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"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,10 +5,15 @@ import { Action } from '../action.enum';
|
|||
import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module';
|
||||
import { DefaultActionHandlerProvider } from '../default-action-handler/default-action-handler.provider';
|
||||
import { ExistingActionHandlersProvider } from '../default-action-handler/existing-action-handlers.provider';
|
||||
import { CreateAliasHandler } from './create-alias.handler';
|
||||
import { DescribeKeyHandler } from './describe-key.handler';
|
||||
import { KmsKeyAlias } from './kms-key-alias.entity';
|
||||
import { KmsKey } from './kms-key.entity';
|
||||
import { KMSHandlers } from './kms.constants';
|
||||
|
||||
const handlers = [
|
||||
|
||||
CreateAliasHandler,
|
||||
DescribeKeyHandler,
|
||||
]
|
||||
|
||||
const actions = [
|
||||
|
|
@ -66,7 +71,7 @@ const actions = [
|
|||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([]),
|
||||
TypeOrmModule.forFeature([KmsKey, KmsKeyAlias]),
|
||||
AwsSharedEntitiesModule,
|
||||
],
|
||||
providers: [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
export type ArnParts = {
|
||||
service: string;
|
||||
region: string;
|
||||
accountId: string;
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
export const breakdownArn = (arn: string): ArnParts => {
|
||||
if (!arn.startsWith('arn')) {
|
||||
throw new Error('Invalid arn');
|
||||
}
|
||||
|
||||
const [_arn, _aws, service, region, accountId, ...identifierData] = arn.split(':');
|
||||
|
||||
return {
|
||||
service,
|
||||
region,
|
||||
accountId,
|
||||
identifier: identifierData.join(':'),
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue