Skip to content

Commit

Permalink
Merge branch 'master' into typescript-eks-refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
kaiz-io authored Feb 25, 2024
2 parents e3e55c0 + 30348c5 commit c69b0fe
Show file tree
Hide file tree
Showing 19 changed files with 658 additions and 134 deletions.
27 changes: 27 additions & 0 deletions csharp/ec2-instance-dev-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# EC2 based dev server

This sample create an EC2 instance that can be used and a backend server for .NET development.

Remote development using tools such as [JetBrains Rider](https://www.jetbrains.com/help/rider/Remote_development_overview.html)
and [VS Code](https://code.visualstudio.com/docs/remote/ssh) where a client machine runs the development environment that connects to a backend server using SSH.

This example will create:
* VPC with one private and one public subnet
* EC2 instance with .NET SDK and Docker installed and configured, placed in a private subnet
* EC Instance Connect Endpoint for secure connection to the EC2 instance using SSH

![](/Users/dhelper/Dev/aws-samples/aws-cdk-examples/csharp/ec2-instance-dev-server/Remote Dev Server.png)

## To Build and Deploy

```bash
$ dotnet build
$ cdk bootstrap
$ cdk deploy
```

## To Destroy

```bash
# Destroy all project resources.
$ cdk destroy
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 64 additions & 0 deletions csharp/ec2-instance-dev-server/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"app": "dotnet run --project src/Ec2InstanceDevServer/Ec2InstanceDevServer.csproj",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"src/*/obj",
"src/*/bin",
"src/*.sln",
"src/*/GlobalSuppressions.cs",
"src/*/*.csproj"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true
}
}
34 changes: 34 additions & 0 deletions csharp/ec2-instance-dev-server/src/Ec2InstanceDevServer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ec2InstanceDevServer", "Ec2InstanceDevServer\Ec2InstanceDevServer.csproj", "{F3A1BD42-FBF4-41CE-B376-0296624A2330}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|x64.ActiveCfg = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|x64.Build.0 = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|x86.ActiveCfg = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Debug|x86.Build.0 = Debug|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|Any CPU.Build.0 = Release|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|x64.ActiveCfg = Release|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|x64.Build.0 = Release|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|x86.ActiveCfg = Release|Any CPU
{F3A1BD42-FBF4-41CE-B376-0296624A2330}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<!-- Roll forward to future major versions of the netcoreapp as needed -->
<RollForward>Major</RollForward>
</PropertyGroup>

<ItemGroup>
<!-- CDK Construct Library dependencies -->
<PackageReference Include="Amazon.CDK.Lib" Version="2.128.0" />
<PackageReference Include="Constructs" Version="[10.0.0,11.0.0)" />

<!-- jsii Roslyn analyzers (un-comment to obtain compile-time checks for missing required props
<PackageReference Include="Amazon.Jsii.Analyzers" Version="*" PrivateAssets="all" />
-->
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Amazon.CDK;
using Constructs;

namespace Ec2InstanceDevServer
{
public class Ec2InstanceDevServerStack : Stack
{
internal Ec2InstanceDevServerStack(Construct scope, string id, IStackProps props = null) : base(scope, id,
props)
{
var vpcStack = new VpcStack(this, "VpcStack");
var ec2Stack = new Ec2Stack(this, "Ec2Stack", vpcStack.VPC);

Output("instance-id", ec2Stack.Ec2Instance.InstanceId);


if (ec2Stack.KeyPairPrivateKey is not null)
{
var ssmParameterName = ec2Stack.KeyPairPrivateKey.ParameterName;
var keyPairFileName = $"{ec2Stack.KeyPairName}.pem";

Output("Download key command",
$"aws ssm get-parameter --name {ssmParameterName} --query Parameter.Value --with-decryption --output text > {keyPairFileName} && chmod 400 {keyPairFileName}");
}

Output("Open tunnel command", $"aws ec2-instance-connect open-tunnel --instance-id {ec2Stack.Ec2Instance.InstanceId} --local-port 1234");
}

private void Output(string name, string value)
{
new CfnOutput(this, name, new CfnOutputProps { Value = value });
}
}
}
112 changes: 112 additions & 0 deletions csharp/ec2-instance-dev-server/src/Ec2InstanceDevServer/Ec2Stack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using Amazon.CDK;
using Amazon.CDK.AWS.EC2;
using Amazon.CDK.AWS.SSM;
using Constructs;

namespace Ec2InstanceDevServer;

internal class Ec2Stack : NestedStack
{
public IInstance Ec2Instance { get; }

public string KeyPairName { get; set; } = "dev-server-key-pair";
public IStringParameter KeyPairPrivateKey { get; }

public Ec2Stack(Construct scope, string id, IVpc vpc, INestedStackProps props = null) : base(scope, id, props)
{
var rootDevice = GetBlockDevice();
var userData = GetUserData();
var instanceAmi = GetMachineImage(userData);
var instanceSg = GetSecurityGroup(vpc);

// To use an existing key pair replace with
//keypair = KeyPair.FromKeyPairName(this, "dev-server-key-pair", "<key pair name>");
var keypair = new KeyPair(this, "keypair", new KeyPairProps
{
KeyPairName = KeyPairName
});

KeyPairPrivateKey = keypair.PrivateKey;

var ec2Instance = new Instance_(this, "DevServer", new InstanceProps
{
InstanceType = InstanceType.Of(InstanceClass.M5, InstanceSize.XLARGE),
Vpc = vpc,
MachineImage = instanceAmi,
VpcSubnets = new SubnetSelection
{
SubnetType = SubnetType.PRIVATE_WITH_EGRESS
},
KeyPair = keypair,
SecurityGroup = instanceSg,
BlockDevices = new IBlockDevice[]
{
rootDevice
},
});

Ec2Instance = ec2Instance;
}

private SecurityGroup GetSecurityGroup(IVpc vpc)
{
// Update security group with specific client IP address
var instanceSg = new SecurityGroup(this, "DevServerSg", new SecurityGroupProps
{
Vpc = vpc,
AllowAllOutbound = true,
Description = "Dev Server SG"
});

instanceSg.Connections.AllowFrom(Peer.AnyIpv4(), Port.Tcp(22), "SSH");
return instanceSg;
}

private static BlockDevice GetBlockDevice()
{
var rootDevice = new BlockDevice
{
DeviceName = "/dev/sda1",
Volume = BlockDeviceVolume.Ebs(30, new EbsDeviceOptions
{
DeleteOnTermination = true,
Encrypted = true,
VolumeType = EbsDeviceVolumeType.GP2
})
};
return rootDevice;
}

private static UserData GetUserData()
{
// Install dotnet, docker, etc. and register dev ssl, certificates for debugging
var userData = UserData.ForLinux();
userData.AddCommands(
"#!/bin/bash",
"apt-get update",
"apt-get install -y dotnet-sdk-6.0",
"dotnet dev-certs https --trust",
"apt-get install -y apt-transport-https ca-certificates curl software-properties-common",
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -",
"add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\"",
"apt-get update",
"apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin",
"usermod -aG docker ubuntu",
"id ubuntu",
"newgrp docker"
);
return userData;
}

private static IMachineImage GetMachineImage(UserData userData)
{
var instanceAmi = MachineImage.FromSsmParameter(
"/aws/service/canonical/ubuntu/server/jammy/stable/current/amd64/hvm/ebs-gp2/ami-id",
new SsmParameterImageOptions
{
Os = OperatingSystemType.LINUX,
UserData = userData
});
return instanceAmi;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Potential Code Quality Issues", "RECS0026:Possible unassigned object created by 'new'", Justification = "Constructs add themselves to the scope in which they are created")]
44 changes: 44 additions & 0 deletions csharp/ec2-instance-dev-server/src/Ec2InstanceDevServer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Amazon.CDK;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ec2InstanceDevServer
{
sealed class Program
{
public static void Main(string[] args)
{
var app = new App();
new Ec2InstanceDevServerStack(app, "Ec2InstanceDevServerStack", new StackProps
{
// If you don't specify 'env', this stack will be environment-agnostic.
// Account/Region-dependent features and context lookups will not work,
// but a single synthesized template can be deployed anywhere.

// Uncomment the next block to specialize this stack for the AWS Account
// and Region that are implied by the current CLI configuration.
/*
Env = new Amazon.CDK.Environment
{
Account = System.Environment.GetEnvironmentVariable("CDK_DEFAULT_ACCOUNT"),
Region = System.Environment.GetEnvironmentVariable("CDK_DEFAULT_REGION"),
}
*/

// Uncomment the next block if you know exactly what Account and Region you
// want to deploy the stack to.
/*
Env = new Amazon.CDK.Environment
{
Account = "123456789012",
Region = "us-east-1",
}
*/

// For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html
});
app.Synth();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Amazon.CDK;
using Amazon.CDK.AWS.EC2;
using Constructs;

namespace Ec2InstanceDevServer;

public class VpcStack : NestedStack
{
public IVpc VPC { get; }
public CfnInstanceConnectEndpoint InstanceConnectEndpoint { get; }

public VpcStack(Construct scope, string id, INestedStackProps props = null) : base(scope, id, props)
{
VPC = new Vpc(this, "DevServerVPC", new VpcProps
{
MaxAzs = 1
});

var ec2InstanceConnectEndpointSg = new SecurityGroup(this, "instanceConnectEpSg", new SecurityGroupProps
{
Vpc = VPC,
AllowAllOutbound = true,
Description = "EC2 instance connect endpoint SG"
});

InstanceConnectEndpoint = new CfnInstanceConnectEndpoint(this, "InstanceConnectEndpoint",
new CfnInstanceConnectEndpointProps
{
SubnetId = VPC.PrivateSubnets[0].SubnetId,
PreserveClientIp = true,
SecurityGroupIds = new[]{ec2InstanceConnectEndpointSg.SecurityGroupId}
});
}
}
Binary file removed go/eks/cluster-graviton/cluster
Binary file not shown.
Loading

0 comments on commit c69b0fe

Please sign in to comment.