-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDeployer.cs
More file actions
126 lines (117 loc) · 5.46 KB
/
Deployer.cs
File metadata and controls
126 lines (117 loc) · 5.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Pulumi;
using Pulumi.Aws.Iam;
using Amazon.IdentityManagement.Model;
using Amazon.IdentityManagement;
using VirtualFinland.Infrastructure.Common;
namespace VirtualFinland.Infrastructure.Features;
//
// IAM role for CI/CD pipelines
//
public class Deployer
{
public static async Task<Pulumi.Aws.Iam.Role> InitializeGitHubOIDCProvider(StackSetup setup)
{
// GitHub OIDC provider configuration
var githubConfig = new Config("github");
var githubOrganization = githubConfig.Require("organization");
var githubIssuerUrl = githubConfig.Require("oidc-issuer");
var githubIssuerUrlWithoutProtocol = githubIssuerUrl.Replace("https://", "");
// @see: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html
var githubThumbprints = githubConfig.RequireObject<List<string>>("oidc-thumbprints");
var githubClientIds = new List<string> { githubConfig.Require("oidc-client-id") };
// Create an OIDC provider for GitHub
var openIdConnectProviderName = "github-oidc-provider"; // Using a static name as there can only be one per aws account
var currentAwsAccount = Pulumi.Aws.GetCallerIdentity.InvokeAsync();
var currentOidcProviderId = $"arn:aws:iam::{currentAwsAccount.Result.AccountId}:oidc-provider/{githubIssuerUrlWithoutProtocol}";
// Check if the OIDC provider already exists
var iamClient = new AmazonIdentityManagementServiceClient();
var request = new ListOpenIDConnectProvidersRequest();
var response = await iamClient.ListOpenIDConnectProvidersAsync(request);
var existingOidcProvider = response.OpenIDConnectProviderList.Find(provider => provider.Arn == currentOidcProviderId);
OpenIdConnectProvider? githubOidcProvider;
if (existingOidcProvider == null)
{
// Create a new OIDC provider
githubOidcProvider = new OpenIdConnectProvider(openIdConnectProviderName, new OpenIdConnectProviderArgs
{
Url = githubIssuerUrl,
ClientIdLists = githubClientIds,
ThumbprintLists = githubThumbprints,
Tags = setup.SharedResourceTags,
});
}
else
{
// Use the existing OIDC provider
githubOidcProvider = OpenIdConnectProvider.Get(openIdConnectProviderName, currentOidcProviderId);
}
// Create an IAM role assumable by the GitHub OIDC provider
// @see: https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect
var githubRole = new Pulumi.Aws.Iam.Role(setup.NameResource("github-oidc-role"), new RoleArgs
{
Description = "Temporary admin role for GitHub Actions",
Tags = setup.Tags,
MaxSessionDuration = 60 * 60, // 1 hour
AssumeRolePolicy = Output.JsonSerialize(Output.Create(new
{
Version = "2012-10-17",
Statement = new[]
{
new
{
Action = "sts:AssumeRoleWithWebIdentity",
Effect = "Allow",
Principal = new { Federated = githubOidcProvider.Arn },
Condition = new Dictionary<string, object>
{
{ "ForAllValues:StringEquals", new Dictionary<string, object>
{
{ $"{githubIssuerUrlWithoutProtocol}:aud", githubClientIds[0] },
{ $"{githubIssuerUrlWithoutProtocol}:repository_owner", githubOrganization },
{ $"{githubIssuerUrlWithoutProtocol}:environment", setup.Environment }
}
},
{ "ForAllValues:StringLike", new Dictionary<string, object>
{
{ $"{githubIssuerUrlWithoutProtocol}:sub", $"repo:{githubOrganization}/*" }
}
}
}
}
}
})),
});
// Temporary policy for updating stacks
var githubStackUpdaterPolicy = new Policy(setup.NameResource("github-deployer-policy"), new PolicyArgs
{
Description = "Broad policy for updating Pulumi stacks",
PolicyDocument = JsonSerializer.Serialize(new Dictionary<string, object?>
{
{ "Version", "2012-10-17" },
{
"Statement", new[]
{
new Dictionary<string, object?>
{
{ "Sid", "GrantAdminAccess" },
{ "Action", "*" },
{ "Effect", "Allow" },
{ "Resource", "*" }
},
}
}
}),
Tags = setup.Tags,
});
// Attach policy to role
_ = new RolePolicyAttachment(setup.NameResource("github-deployer-policy-attachment"), new()
{
Role = githubRole.Name,
PolicyArn = githubStackUpdaterPolicy.Arn,
});
return githubRole;
}
}