in lib/identity-stack.ts [30:260]
constructor(scope: core.Construct, id: string, props: IdentityCoreProps) {
super(scope, id);
const orgName = core.Arn.parse(props.orgId).resourceName!;
const identityVPC = new ec2.Vpc(this, 'IdentityVPC', {
cidr: props.desiredVpcCidr,
subnetConfiguration: [
{
cidrMask: 20,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 20,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE,
}
]
});
this.Vpc = identityVPC;
const privateSubnetSelection = { subnetType: ec2.SubnetType.PRIVATE };
const publicSubnetSelection = { subnetType: ec2.SubnetType.PUBLIC };
const privateSubnets = identityVPC.selectSubnets(privateSubnetSelection).subnetIds;
const secretsManagerPolicy = new iam.PolicyStatement({
actions: ["kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:CreateGrant", "kms:DescribeKey"],
effect: iam.Effect.ALLOW,
resources: ["*"],
principals: [new iam.ServicePrincipal("secretsmanager.amazonaws.com")]
});
const allowRootManagment = new iam.PolicyStatement({
actions: ["kms:*"],
effect: iam.Effect.ALLOW,
resources: ["*"],
principals: [new iam.AccountRootPrincipal()]
});
const allowOuAccessTotransitSecretsKey = new iam.PolicyStatement({
actions: ["kms:Decrypt"],
effect: iam.Effect.ALLOW,
resources: ["*"],
principals: [new iam.OrganizationPrincipal(orgName)]
});
const kmsPolicyDoc = new iam.PolicyDocument({statements: [secretsManagerPolicy,allowRootManagment, allowOuAccessTotransitSecretsKey]})
const identitySecretsKey = new kms.Key(this, "IdentitySecretsKey", {
description: "Biotech Blueprint Identity Secrets Key",
enableKeyRotation: false,
enabled: true,
policy: kmsPolicyDoc
});
this.key = identitySecretsKey;
var identitySecret = new sm.Secret(this , "identitySecretKey", {
secretName: "ADAdminCreds",
generateSecretString : {
secretStringTemplate: JSON.stringify({ "username": "Admin" }),
generateStringKey: "password"
},
description: "Root Admin AD Credentials",
encryptionKey: identitySecretsKey
});
this.identitySecretsArn = identitySecret.secretArn;
const activeDirectory = new ds.CfnMicrosoftAD(this, 'IdentityAD', {
edition : "Standard",
enableSso : false,
name : props.corporateDnsApex,
password : core.Token.asString(identitySecret.secretValueFromJson('password')),
shortName : props.netBiosName,
vpcSettings : {
subnetIds : privateSubnets,
vpcId : identityVPC.vpcId
},
createAlias: false
});
const transitGatewayIDSecretValue = sm.Secret.fromSecretArn(scope, 'ImportedSecret', props.integrationSecretsArn).secretValue;
const transitGatewayAttachment = new ec2.CfnTransitGatewayAttachment(this, 'tgAttachment', {
subnetIds: privateSubnets,
transitGatewayId: core.Token.asString(transitGatewayIDSecretValue),
vpcId: identityVPC.vpcId,
});
const transitSecret = new sm.Secret(this , "transitGatewayAttachmentSecret", {
secretName: "ga",
generateSecretString : {
secretStringTemplate: JSON.stringify( {
GatewayAttachment: transitGatewayAttachment.ref,
}),
generateStringKey: "password"
},
description: "Transit Gateway Attachment ID",
encryptionKey: identitySecretsKey
});
const vpcCidrSecret = new sm.Secret(this , "transitGatewayVpcCidrSecret", {
secretName: "vc",
generateSecretString : {
secretStringTemplate: JSON.stringify( {
VpcCidr: identityVPC.vpcCidrBlock
}),
generateStringKey: "password"
},
description: "VPC CIDR To Associate with Identity Stack",
encryptionKey: identitySecretsKey
});
const domainControllerSecrets = new sm.Secret(this , "DomainControllerSercretsForAdConnector", {
secretName: "IdentityAccountDomainControllerSecretsForAdConnectors",
generateSecretString : {
secretStringTemplate: core.Stack.of(this).toJsonString({
DomainControllerDnsAddress0: core.Fn.select(0,activeDirectory.attrDnsIpAddresses),
DomainControllerDnsAddress1: core.Fn.select(1,activeDirectory.attrDnsIpAddresses),
DomainControlerAlias: activeDirectory.attrAlias,
DomainControllerShortName: activeDirectory.shortName,
DomainApex: activeDirectory.name,
AdConnectorServiceAccountUsername: "svc_adconnector",
AdConnectorSecretsKeyArn: identitySecretsKey.keyArn,
VpnUsersAdGroupSID: "undefined"
}),
generateStringKey: "password"
},
description: "Secrets for AD Connectors to join domain in identity account.",
encryptionKey: identitySecretsKey
});
const ouWideResourcePolicy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "secretsmanager:*",
"Principal": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": orgName
}
}
}
]
}
new sm.CfnResourcePolicy(this, "transitGtwyAttachmentSharePolicy", {secretId: transitSecret.secretArn, resourcePolicy: ouWideResourcePolicy});
new sm.CfnResourcePolicy(this, "transitGtwyVpcCidrSharePolicy", {secretId: vpcCidrSecret.secretArn, resourcePolicy: ouWideResourcePolicy});
new sm.CfnResourcePolicy(this, "DomainControllerSharePolicy", {secretId: domainControllerSecrets.secretArn, resourcePolicy: ouWideResourcePolicy});
const latestWindowsAmi = ssm.StringParameter.fromStringParameterAttributes(this, 'WindowsAmiParam', {
parameterName: '/aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base',
});
const DomainControllerAdminConsoleRole = new iam.Role(this, 'DomainControllerAdminConsoleRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com')
});
DomainControllerAdminConsoleRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
DomainControllerAdminConsoleRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMDirectoryServiceAccess'));
DomainControllerAdminConsoleRole.addToPolicy(new iam.PolicyStatement({
resources: [identitySecret.secretArn],
actions: ['secretsmanager:GetSecretValue',"secretsmanager:PutSecretValue"]
}));
DomainControllerAdminConsoleRole.addToPolicy(new iam.PolicyStatement({
resources: [identitySecretsKey.keyArn],
actions: ['kms:Decrypt', 'kms:GenerateDataKey']
}));
// TODO: Change subnets to private so this host is only accessible via VPN
const domainControllerConsoleInstance = new ec2.Instance(this, 'DCAdminConsole', {
machineImage: new ec2.WindowsImage(ec2.WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_FULL_BASE),
instanceType: new ec2.InstanceType('t3.small'),
vpc: identityVPC,
vpcSubnets: privateSubnetSelection,
role: DomainControllerAdminConsoleRole,
instanceName: "Domain Controller Console"
});
const rdpSecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
vpc: identityVPC,
description: 'Domain Controller Console Security Group',
allowAllOutbound: true // Can be set to false
});
rdpSecurityGroup.addIngressRule(ec2.Peer.ipv4(props.vpnTransitAccessCIDR), ec2.Port.tcp(3389), 'RDP Access');
domainControllerConsoleInstance.addSecurityGroup(rdpSecurityGroup);
const prepDomainControllerForAdConnectorsDoc = new ssm.CfnDocument(this, 'prepDomainSsmDoc', {
content: JSON.parse(fs.readFileSync('scripts/ssmdoc.PrepDomainController.json', { encoding: 'utf-8' })),
documentType: "Command"
});
const joinDomainAssociation = new ssm.CfnAssociation(this, 'joinDomainAssociation',{
name: prepDomainControllerForAdConnectorsDoc.ref,
targets: [
{ key: "InstanceIds", values: [domainControllerConsoleInstance.instanceId] }
]
});
joinDomainAssociation.addPropertyOverride('Parameters',{
directoryId: [activeDirectory.ref],
directoryName: [props.corporateDnsApex],
dnsIpAddress0: [core.Fn.select(0,activeDirectory.attrDnsIpAddresses)],
dnsIpAddress1: [core.Fn.select(1,activeDirectory.attrDnsIpAddresses)]
});
}