Skip to content

Commit 3fa7e12

Browse files
authored
Merge pull request #26 from Keyfactor/ab#69134
Ab#69134
2 parents d6b1d71 + 5b92c69 commit 3fa7e12

30 files changed

+473
-368
lines changed

.github/workflows/keyfactor-bootstrap-workflow.yml renamed to .github/workflows/keyfactor-starter-workflow.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Keyfactor Bootstrap Workflow
1+
name: Keyfactor Bootstrap Workflow
22

33
on:
44
workflow_dispatch:
@@ -11,9 +11,10 @@ on:
1111

1212
jobs:
1313
call-starter-workflow:
14-
uses: keyfactor/actions/.github/workflows/starter.yml@v2
14+
uses: keyfactor/actions/.github/workflows/starter.yml@3.1.2
1515
secrets:
1616
token: ${{ secrets.V2BUILDTOKEN}}
1717
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
1818
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
1919
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
20+
scan_token: ${{ secrets.SAST_TOKEN }}

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2.2.0
2+
* Add entry parameter for ACM tags
3+
* Modify to produce .net6/8 dual builds
4+
* Modify README to use doctool
5+
16
2.1.0
27
* Allow EC2 default credentials to also run the Assume Role command
38
* Add sts:ExtenalId parameter option to Assume Role calls (not applicable when using OAuth)

Images/CertStore-1.gif

-15.4 KB
Binary file not shown.

Images/CertStore-IAM.gif

-79.1 KB
Binary file not shown.

Images/CertStore2.gif

-21.2 KB
Binary file not shown.

Images/CertStoreCredentials.gif

-18.9 KB
Binary file not shown.

Images/CertStoreType-Advanced.gif

-14.9 KB
Binary file not shown.

Images/CertStoreType-Basic-IAM.gif

-93.3 KB
Binary file not shown.

Images/CertStoreType-Basic-Okta.gif

-17.7 KB
Binary file not shown.
-123 KB
Binary file not shown.
-18.5 KB
Binary file not shown.

Images/CertStoreType-EntryParams.gif

-26.4 KB
Binary file not shown.

README.md

Lines changed: 262 additions & 298 deletions
Large diffs are not rendered by default.

aws-orchestrator-core/Jobs/Inventory.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,10 @@ protected virtual CurrentInventoryItem BuildInventoryItem(string alias, string r
176176
Logger.LogTrace($"Certificate: {certificate}");
177177
string base64Cert = RemoveAnchors(certificate);
178178
Logger.LogTrace($"Base64 Certificate: {base64Cert}");
179-
var regionDict = new Dictionary<string, object>
179+
var entryParams = new Dictionary<string, object>
180180
{
181-
{ "AWS Region", region }
181+
{ "AWS Region", region },
182+
{ "ACM Tags", GetCertificateTagsFromArn(alias) }
182183
};
183184
CurrentInventoryItem acsi = new CurrentInventoryItem()
184185
{
@@ -187,7 +188,7 @@ protected virtual CurrentInventoryItem BuildInventoryItem(string alias, string r
187188
ItemStatus = OrchestratorInventoryItemStatus.Unknown,
188189
PrivateKeyEntry = true,
189190
UseChainLevel = false,
190-
Parameters = regionDict
191+
Parameters = entryParams
191192
};
192193

193194
return acsi;
@@ -218,6 +219,34 @@ private string GetCertificateFromArn(string arn)
218219
}
219220
}
220221

222+
private string GetCertificateTagsFromArn(string arn)
223+
{
224+
try
225+
{
226+
Logger.MethodEntry();
227+
Logger.LogTrace($"arn: {arn}");
228+
ListTagsForCertificateRequest getTagsRequest = new ListTagsForCertificateRequest() { CertificateArn = arn };
229+
ListTagsForCertificateResponse getTagsResponse = AsyncHelpers.RunSync(() => AcmClient.ListTagsForCertificateAsync(getTagsRequest));
230+
231+
string tags = "";
232+
foreach (Amazon.CertificateManager.Model.Tag tag in getTagsResponse.Tags)
233+
{
234+
tags += $",{tag.Key}={tag.Value}";
235+
}
236+
237+
return tags.Length > 0 ? tags.Substring(1) : tags;
238+
}
239+
catch (Exception e)
240+
{
241+
Logger.LogError($"Error Occurred in Inventory.GetCertificateTagsFromArn: {e.Message}");
242+
throw;
243+
}
244+
finally
245+
{
246+
Logger.MethodExit();
247+
}
248+
}
249+
221250
//Remove Anchor Tags From Encoded Cert
222251
private string RemoveAnchors(string base64Cert)
223252
{

aws-orchestrator-core/Jobs/Management.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,16 @@
2727
using System.IO;
2828
using System.Net;
2929
using System.Text;
30+
using System.Collections.Generic;
3031
using Amazon;
3132
using Org.BouncyCastle.OpenSsl;
3233
using System.Linq;
3334

3435
using ILogger = Microsoft.Extensions.Logging.ILogger;
3536
using Keyfactor.Orchestrators.Extensions.Interfaces;
37+
using static Org.BouncyCastle.Math.EC.ECCurve;
38+
using System.Drawing;
39+
using Amazon.IdentityManagement.Model;
3640

3741
namespace Keyfactor.AnyAgent.AwsCertificateManager.Jobs
3842
{
@@ -73,6 +77,8 @@ internal JobResult PerformAddition(Credentials awsCredentials, ManagementJobConf
7377
};
7478
}
7579

80+
List<Amazon.CertificateManager.Model.Tag> acmTags = ParseACMTags(config.JobProperties);
81+
7682
Logger.LogTrace($"Targeting AWS Region - {region}");
7783
var endpoint = RegionEndpoint.GetBySystemName(region);
7884
Logger.LogTrace($"Got Endpoint From Job Properties JSON: {JsonConvert.SerializeObject(endpoint)}");
@@ -178,8 +184,12 @@ internal JobResult PerformAddition(Credentials awsCredentials, ManagementJobConf
178184
}
179185
}
180186
icr.CertificateArn = config.JobCertificate.Alias?.Length >= 20 ? config.JobCertificate.Alias.Trim() : null; //If an arn is provided, use it, this will perform a renewal/replace
187+
if (icr.CertificateArn == null )
188+
{
189+
icr.Tags = acmTags;
190+
}
181191
Logger.LogTrace($"Certificate arn {icr.CertificateArn}");
182-
192+
183193
ImportCertificateResponse IcrResponse = AsyncHelpers.RunSync(() => AcmClient.ImportCertificateAsync(icr));
184194
Logger.LogTrace($"IcrResponse JSON: {JsonConvert.SerializeObject(IcrResponse)}");
185195
// Ensure 200 Response
@@ -332,5 +342,30 @@ private static MemoryStream CertStringToStream(string certString)
332342
byte[] certBytes = Encoding.ASCII.GetBytes(certString);
333343
return new MemoryStream(certBytes);
334344
}
345+
346+
private List<Amazon.CertificateManager.Model.Tag> ParseACMTags(Dictionary<string, object> jobProperties)
347+
{
348+
List<Amazon.CertificateManager.Model.Tag> acmTags = new List<Amazon.CertificateManager.Model.Tag>();
349+
350+
if (jobProperties != null && jobProperties.ContainsKey("ACM Tags") && jobProperties["ACM Tags"] != null)
351+
{
352+
string acmTagsString = jobProperties["ACM Tags"].ToString();
353+
string[] acmTagsAry = acmTagsString.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
354+
355+
foreach(string acmTagString in acmTagsAry)
356+
{
357+
string[] acmTagAry = acmTagString.Split("=", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
358+
if (acmTagAry.Length != 2)
359+
{
360+
throw new Exception($"Error parsing ACM Tags - invalid format. Found {acmTagAry.Length.ToString()} items for a tag instead of 2 (key/value).");
361+
}
362+
363+
Amazon.CertificateManager.Model.Tag acmTag = new Amazon.CertificateManager.Model.Tag() { Key = acmTagAry[0], Value = acmTagAry[1] };
364+
acmTags.Add(acmTag);
365+
}
366+
}
367+
368+
return acmTags;
369+
}
335370
}
336371
}

aws-orchestrator-core/aws-orchestrator-core.csproj

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>netcoreapp3.1</TargetFramework>
5-
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
4+
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
5+
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
6+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
7+
<ImplicitUsings>disable</ImplicitUsings>
68
<RootNamespace>Keyfactor.AnyAgent.AwsCertificateManager</RootNamespace>
79
<AssemblyName>Keyfactor.AnyAgent.AwsCertificateManager</AssemblyName>
810
</PropertyGroup>
9-
10-
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
11-
<Exec Command="echo F | xcopy &quot;$(SolutionDir)sample-manifest.json&quot; &quot;$(TargetDir)\manifest.json&quot; /Y" />
12-
</Target>
1311

1412
<ItemGroup>
1513
<PackageReference Include="AWSSDK.CertificateManager" Version="3.7.101.21" />
@@ -27,6 +25,10 @@
2725
<PackageReference Include="RestSharp" Version="106.13.0" />
2826
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
2927
<PackageReference Include="System.Drawing.Common" Version="5.0.3" />
28+
29+
<None Update="manifest.json">
30+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
31+
</None>
3032
</ItemGroup>
3133

3234
</Project>
File renamed without changes.

docsource/aws-acm.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Overview

docsource/content.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
## Overview
2+
3+
AWS Certificate Manager is a service that lets you easily provision, manage, and deploy public and private Secure Sockets Layer/Transport Layer Security (SSL/TLS) certificates for use with AWS services and your internal connected resources. SSL/TLS certificates are used to secure network communications and establish the identity of websites over the Internet as well as resources on private networks. AWS Certificate Manager removes the time-consuming manual process of purchasing, uploading, and renewing SSL/TLS certificates. The orchestrator supports Okta OAth authentication, as well as AWS IAM accounts. The Okta Support allows authentication against a 3rd party identity provider in AWS. From there you can get temporary credentials for a role that you setup in each AWS Account.
4+
5+
This integration also supports the reading of existing certificate ACM key/value pair tags during inventory and adding these tags when adding new certificates. Modifying and adding ACM tags during certificate renewal, however, is NOT supported. This is due to the fact that the AWS API does not allow for ACM tag modification when updating a certificate in one step. This would need to be done in multiple steps, leading to the possibility of the certificate being left in an error state if any intermediate step were to fail. However, while the modification/addition of ACM tags is not supported, all existing ACM tags WILL remain in place during renewal.
6+
7+
### Documentation
8+
9+
- [Cert Manager API](https://docs.aws.amazon.com/acm/latest/userguide/sdk.html)
10+
- [Aws Region Codes](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.RegionsAndAvailabilityZones.html)
11+
12+
13+
## Requirements
14+
15+
### Setting up AWS Authentication
16+
17+
Depending on your choice of authentication providers, choose the appropriate section:
18+
<details>
19+
<summary>AWS Certificate Manager <code>AWS-ACM</code></summary>
20+
21+
### AWS Setup
22+
Options for authenticating:
23+
1. Okta or other OAuth configuration (refer to `AwsCerManO` below)
24+
2. IAM User Auth configuration (refer to `AwsCerManA` below)
25+
3. EC2 Role Auth or other default method supported by the [AWS SDK](https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/creds-assign.html)
26+
27+
As one option for #3, to set up Role Auth for an EC2 instance, follow the steps below. Note, this applies specifically __when the orchestrator is running `ACM-AWS` inside of an EC2 instance__. When the option to assume an EC2 role is selected, the Account ID and Role will be assumed using the default credentials supplied in the EC2 instance via the AWS SDK.
28+
1. Assign or note the existing IAM Role assigned to the EC2 instance running
29+
2. Make sure that role has access to ACM
30+
3. When configuring the `AWS-ACM` store, do not select either IAM or OAuth methods in the store's settings. This will make it use the AWS SDK to lookup EC2 credentials.
31+
32+
</details>
33+
34+
<details>
35+
<summary>[Deprecated] AWS Certificate Manager with Okta Auth Configuration <code>AwsCerManO</code></summary>
36+
37+
### AWS Setup
38+
1. A 3rd party [identity provider](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) similar to [this](docsource/images/AWSIdentityProvider.gif) needs to be setup in AWS for each account.
39+
2. An Aws [Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html) similar to [this](docsource/images/AWSRole1.gif) needs Added for each AWS account.
40+
3. Ensure the [trust relationship](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/edit_trust.html) is setup for that role. Should look like [this](docsource/images/AWSRole2.gif).
41+
42+
### OKTA Setup
43+
1. Ensure your Authorization Server Is Setup in OKTA. Here is a [sample](docsource/images/OktaSampleAuthorizationServer.gif).
44+
2. Ensure the appropriate scopes are setup in Okta. Here is a [sample](docsource/images/OktaSampleAuthorizationServer-scopes.gif).
45+
3. Setup an Okta App with similar settings to [this](docsource/images/OktaApp1.gif) and [this](docsource/images/OktaApp2.gif).
46+
47+
</details>
48+
49+
<details>
50+
<summary>[Deprecated] AWS Certificate Manager with IAM Auth Configuration <code>AwsCerManA</code></summary>
51+
52+
### AWS Setup
53+
1. An Aws [Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html) Needs Added for the permissions you want to grant, see [sample](docsource/images/AWSRole1.gif).
54+
2. A [Trust Relationship](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/edit_trust.html) is setup for that role. Should look like something like [this](docsource/images/AssumeRoleTrust.gif).
55+
3. AWS does not support programmatic access for AWS SSO accounts. The account used here must be a [standard AWS IAM User](docsource/images/UserAccount.gif) with an Access Key credential type.
56+
57+
</details>
58+
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)