Skip to content

Commit

Permalink
Merge pull request #50 from aws-samples/github-oidc
Browse files Browse the repository at this point in the history
added CDK code to create roles used by github actions.
  • Loading branch information
ppittle authored Nov 15, 2024
2 parents 1c61931 + 72c2d49 commit 1f96918
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 10 deletions.
25 changes: 22 additions & 3 deletions .github/workflows/TestAuth.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:
contents: read

jobs:
test:
test-SamDeploymentRole:

runs-on: ubuntu-latest
strategy:
Expand All @@ -23,11 +23,30 @@ jobs:
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_ROLE }}
role-to-assume: ${{ secrets.AWS_SAM_DEPLOYMENT_ROLE }}
role-session-name: TestAuthSession
aws-region: ${{ secrets.AWS_REGION }}

- name: Send metric success
run: |
aws cloudwatch put-metric-data --namespace TestingAuth --metric-name TestAuthFromGitHubAction --value 1 --dimensions OS=Ubuntu
aws cloudwatch put-metric-data --namespace TestingAuth --metric-name TestSamDeploymentAuthFromGitHubAction --value 1 --dimensions OS=Ubuntu
test-LoadTestRunnerRole:
runs-on: ubuntu-latest
strategy:
fail-fast: false

steps:
- uses: actions/checkout@v3

- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_LOAD_TEST_RUNNER_ROLE }}
role-session-name: TestAuthSession
aws-region: ${{ secrets.AWS_REGION }}

- name: Send metric success
run: |
aws cloudwatch put-metric-data --namespace TestingAuth --metric-name TestLoadTestRunnerAuthFromGitHubAction --value 1 --dimensions OS=Ubuntu
26 changes: 19 additions & 7 deletions DotnetServerlessDemo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "src\NET8\Shared\S
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NET8Native", "NET8Native", "{FDFE3CC3-D38F-42DD-8E35-319E35103396}"
ProjectSection(SolutionItems) = preProject
src\NET8Native\template.yaml = src\NET8Native\template.yaml
.github\workflows\net-8-native-aot-pipeline-canary.yaml = .github\workflows\net-8-native-aot-pipeline-canary.yaml
src\NET8Native\template.yaml = src\NET8Native\template.yaml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeleteProduct", "src\NET8Native\DeleteProduct\DeleteProduct.csproj", "{60D799A3-B9DF-4769-AFB7-3AFCB89272C7}"
Expand Down Expand Up @@ -156,21 +156,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "logsToMetrics", "metrics\sr
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NET9CustomRuntime", "NET9CustomRuntime", "{A85E5BE3-CA61-499F-B819-127944EC3A5C}"
ProjectSection(SolutionItems) = preProject
src\NET9CustomRuntime\template.yaml = src\NET9CustomRuntime\template.yaml
.github\workflows\net-9-pipeline-canary.yaml = .github\workflows\net-9-pipeline-canary.yaml
src\NET9CustomRuntime\template.yaml = src\NET9CustomRuntime\template.yaml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeleteProduct", "src\NET9CustomRuntime\DeleteProduct\DeleteProduct.csproj", "{8A545DEF-C766-42E4-948E-1807CD9B703F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeleteProduct", "src\NET9CustomRuntime\DeleteProduct\DeleteProduct.csproj", "{8A545DEF-C766-42E4-948E-1807CD9B703F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GetProduct", "src\NET9CustomRuntime\GetProduct\GetProduct.csproj", "{04D76857-7A53-4B70-8D3E-0FD2614AC7A1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetProduct", "src\NET9CustomRuntime\GetProduct\GetProduct.csproj", "{04D76857-7A53-4B70-8D3E-0FD2614AC7A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GetProducts", "src\NET9CustomRuntime\GetProducts\GetProducts.csproj", "{553409B3-DA20-436E-823F-F5F590CACC11}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetProducts", "src\NET9CustomRuntime\GetProducts\GetProducts.csproj", "{553409B3-DA20-436E-823F-F5F590CACC11}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PutProduct", "src\NET9CustomRuntime\PutProduct\PutProduct.csproj", "{78DE821A-CC51-4387-9863-C10C35F092CD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PutProduct", "src\NET9CustomRuntime\PutProduct\PutProduct.csproj", "{78DE821A-CC51-4387-9863-C10C35F092CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "src\NET9CustomRuntime\Shared\Shared.csproj", "{8F6D9BF5-2763-4136-B08B-262CFF237E00}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "src\NET9CustomRuntime\Shared\Shared.csproj", "{8F6D9BF5-2763-4136-B08B-262CFF237E00}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub", "GitHub", "{6EBD8D18-8091-4406-BEE5-99E9B3F3343E}"
ProjectSection(SolutionItems) = preProject
.github\workflows\TestAuth.yaml = .github\workflows\TestAuth.yaml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "generate-report", "generate-report", "{3CEA22A8-720D-48AA-BECC-4689DDD5B565}"
ProjectSection(SolutionItems) = preProject
Expand Down Expand Up @@ -202,6 +205,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sam-build-and-deploy-native
.github\actions\sam-build-and-deploy-native-arm\action.yml = .github\actions\sam-build-and-deploy-native-arm\action.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cdk", "cdk", "{29D197DC-CFF5-433E-9722-4999D6BDFF47}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "cdk", "cdk\cdk.csproj", "{0A754B66-7990-4022-96B0-8DA959F1878A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -396,6 +403,10 @@ Global
{8F6D9BF5-2763-4136-B08B-262CFF237E00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F6D9BF5-2763-4136-B08B-262CFF237E00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F6D9BF5-2763-4136-B08B-262CFF237E00}.Release|Any CPU.Build.0 = Release|Any CPU
{0A754B66-7990-4022-96B0-8DA959F1878A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A754B66-7990-4022-96B0-8DA959F1878A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A754B66-7990-4022-96B0-8DA959F1878A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A754B66-7990-4022-96B0-8DA959F1878A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -462,6 +473,7 @@ Global
{8DEAFADE-57B4-4DC6-B5E9-C6FF62169D90} = {6EBD8D18-8091-4406-BEE5-99E9B3F3343E}
{3732BFAB-E2FF-4492-978A-26187BC46F33} = {6EBD8D18-8091-4406-BEE5-99E9B3F3343E}
{7A31BEFB-05B0-40D6-8CA2-BC2D48C99F3B} = {6EBD8D18-8091-4406-BEE5-99E9B3F3343E}
{0A754B66-7990-4022-96B0-8DA959F1878A} = {29D197DC-CFF5-433E-9722-4999D6BDFF47}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {47CF4F5B-EF7B-4BFC-AA6A-31504BF0CA10}
Expand Down
53 changes: 53 additions & 0 deletions cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"app": "dotnet run --project cdk/cdk.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/core:includePrefixInUniqueNameGeneration": true
}
}
121 changes: 121 additions & 0 deletions cdk/GithubOIDCConnectionStack.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Collections.Generic;
using Amazon.CDK;
using Amazon.CDK.AWS.IAM;
using Constructs;

namespace AWS.DotnetServerlessDemo.Cdk;

public class GithubOIDCConnectionStack : Stack
{
private const string DotnetServerlessRepoName = "aws-samples/serverless-dotnet-demo";

internal GithubOIDCConnectionStack(Construct scope, string id, IStackProps props = null)
: base(scope, id, props)
{
var githubIdentity = CreateGitHubOidcTestRunner();

AddSamDeploymentRole(githubIdentity);
AddLoadTestRunnerRole(githubIdentity);
}

/// <remarks>
/// GitHub Documentation: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services
/// Example Blog: https://towardsthecloud.com/aws-cdk-openid-connect-github
/// </remarks>
private WebIdentityPrincipal CreateGitHubOidcTestRunner()
{
var githubProvider =
new OpenIdConnectProvider(
this,
"githubProvider",
new OpenIdConnectProviderProps
{
Url = "https://token.actions.githubusercontent.com",
ClientIds = new[] {"sts.amazonaws.com"}
}
);

var assumeRoleIdentity = new WebIdentityPrincipal(
githubProvider.OpenIdConnectProviderArn,
conditions: new Dictionary<string, object>
{
{
"StringLike",
new Dictionary<string, string>
{
{ "token.actions.githubusercontent.com:sub", $"repo:{DotnetServerlessRepoName}:*" },
{ "token.actions.githubusercontent.com:aud", "sts.amazonaws.com" }
}
}
}
);

return assumeRoleIdentity;
}

/// <summary>
/// Create a role that <paramref name="githubIdentity"/> can use to
/// invoke `sam deploy` commands from GitHub Actions.
/// </summary>
private void AddSamDeploymentRole(WebIdentityPrincipal githubIdentity)
{
var githubSamDeploymentRole = new Role(
this,
"githubSamDeploymentRole",
new RoleProps
{
AssumedBy = githubIdentity,
ManagedPolicies = new[]
{
ManagedPolicy.FromAwsManagedPolicyName("AdministratorAccess"),
ManagedPolicy.FromAwsManagedPolicyName("CloudWatchAgentServerPolicy")
},
RoleName = "githubSamDeploymentRole",
MaxSessionDuration = Duration.Hours(1)
}
);

new CfnOutput(
this,
"githubSamDeploymentRoleArn",
new CfnOutputProps
{
Value = githubSamDeploymentRole.RoleArn,
ExportName = "githubSamDeploymentRoleArn"
}
);
}

/// <summary>
/// Create a role that <paramref name="githubIdentity"/> can use to
/// invoke Load Test commands from GitHub Actions.
/// </summary>
private void AddLoadTestRunnerRole(WebIdentityPrincipal githubIdentity)
{
var githubLoadTestRunnerRole = new Role(
this,
"githubLoadTestRunnerRole",
new RoleProps
{
AssumedBy = githubIdentity,
ManagedPolicies = new[]
{
ManagedPolicy.FromAwsManagedPolicyName("AdministratorAccess"),
ManagedPolicy.FromAwsManagedPolicyName("CloudWatchAgentServerPolicy")
},
RoleName = "githubLoadTestRunnerRole",
MaxSessionDuration = Duration.Hours(1)
}
);

new CfnOutput(
this,
"githubLoadTestRunnerRoleArn",
new CfnOutputProps
{
Value = githubLoadTestRunnerRole.RoleArn,
ExportName = "githubLoadTestRunnerRoleArn"
}
);
}
}
5 changes: 5 additions & 0 deletions cdk/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[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"
)]
22 changes: 22 additions & 0 deletions cdk/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Amazon.CDK;

namespace AWS.DotnetServerlessDemo.Cdk;

sealed class Program
{
public static void Main(string[] args)
{
var app = new App();

new GithubOIDCConnectionStack(
app,
"GithubOIDCConnectionStack",
new StackProps
{
TerminationProtection = true
}
);

app.Synth();
}
}
20 changes: 20 additions & 0 deletions cdk/cdk.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

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

<ItemGroup>
<!-- CDK Construct Library dependencies -->
<PackageReference Include="Amazon.CDK.Lib" Version="2.84.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>

0 comments on commit 1f96918

Please sign in to comment.