Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync dev and v4sdk-development #889

Closed
wants to merge 8 commits into from
30 changes: 30 additions & 0 deletions .github/workflows/change-file-in-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Change File Included in PR

on:
pull_request:
types: [opened, synchronize, reopened, labeled]

jobs:
check-files-in-directory:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'Release Not Needed') && !contains(github.event.pull_request.labels.*.name, 'Release PR') }}
name: Change File Included in PR
runs-on: ubuntu-latest

steps:
- name: Checkout PR code
uses: actions/checkout@v3

- name: Get List of Changed Files
id: changed-files
uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf #v45

- name: Check for Change File(s) in .autover/changes/
run: |
DIRECTORY=".autover/changes/"
if echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -q "$DIRECTORY"; then
echo "✅ One or more change files in '$DIRECTORY' are included in this PR."
else
echo "❌ No change files in '$DIRECTORY' are included in this PR."
echo "Refer to the 'Adding a change file to your contribution branch' section of https://github.com/aws/aws-dotnet-deploy/blob/main/CONTRIBUTING.md"
exit 1
fi
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## Release 2024-11-15

### AWS.Deploy.ServerMode.Client (1.28.0)
* Update Microsoft.AspNetCore.SignalR.Client version to fix System.Text.Json vulnerability
### AWS.Deploy.CLI (1.28.0)
* Update beanstalk platform resolution logic to additionally use 'Deprecated' versions in order to continue supporting .NET 6.
* Read region value for non default profiles
### AWS.Deploy.Recipes.CDK.Common (1.28.0)

## Release 2024-10-24

### AWS.Deploy.CLI (1.27.0)
Expand Down
45 changes: 45 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,51 @@ To send us a pull request, please:
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).

## Adding a `change file` to your contribution branch

Each contribution branch should include a `change file` that contains a changelog message for each project that has been updated, as well as the type of increment to perform for those changes when versioning the project.

A `change file` looks like the following example:
```json
{
"Projects": [
{
"Name": "AWS.Deploy.CLI",
"Type": "Patch",
"ChangelogMessages": [
"Fixed an issue causing a failure somewhere"
]
}
]
}
```
The `change file` lists all the modified projects, the changelog message for each project as well as the increment type.

These files are located in the repo at .autover/changes/

You can use the `AutoVer` tool to create the change file. You can install it using the following command:
```
dotnet tool install -g AutoVer
```

You can create the `change file` using the following command:
```
autover change --project-name "AWS.Deploy.CLI" -m "Fixed an issue causing a failure somewhere
```
Note: Make sure to run the command from the root of the repository.

You can update the command to specify which project you are updating.
The available projects are:
* AWS.Deploy.CLI
* AWS.Deploy.Recipes.CDK.Common
* AWS.Deploy.ServerMode.Client

The possible increment types are:
* Patch
* Minor
* Major

Note: You do not need to create a new `change file` for every changelog message or project within your branch. You can create one `change file` that contains all the modified projects and the changelog messages.

## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
Expand Down
2 changes: 1 addition & 1 deletion src/AWS.Deploy.CLI/AWS.Deploy.CLI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<NoWarn>$(NoWarn);1570;1591;ASP0000</NoWarn>
<RollForward>Major</RollForward>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>1.27.0</Version>
<Version>1.28.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
17 changes: 17 additions & 0 deletions src/AWS.Deploy.CLI/AWSCredentialsFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime;

namespace AWS.Deploy.CLI
{
/// <inheritdoc />
public class AWSCredentialsFactory : IAWSCredentialsFactory
{
/// <inheritdoc />
public AWSCredentials Create()
{
return FallbackCredentialsFactory.GetCredentials();
}
}
}
53 changes: 39 additions & 14 deletions src/AWS.Deploy.CLI/AWSUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using System.Linq;
using System.Threading.Tasks;
using Amazon.Runtime;
using Amazon.Runtime.CredentialManagement;
using AWS.Deploy.CLI.Utilities;
using AWS.Deploy.Common;
using AWS.Deploy.Common.IO;
Expand All @@ -17,7 +16,7 @@ namespace AWS.Deploy.CLI
{
public interface IAWSUtilities
{
Task<AWSCredentials> ResolveAWSCredentials(string? profileName);
Task<Tuple<AWSCredentials, string?>> ResolveAWSCredentials(string? profileName);
string ResolveAWSRegion(string? region, string? lastRegionUsed = null);
}

Expand All @@ -28,35 +27,54 @@ public class AWSUtilities : IAWSUtilities
private readonly IDirectoryManager _directoryManager;
private readonly IOptionSettingHandler _optionSettingHandler;
private readonly IServiceProvider _serviceProvider;
private readonly ICredentialProfileStoreChainFactory _credentialChainFactory;
private readonly ISharedCredentialsFileFactory _sharedCredentialsFileFactory;
private readonly IAWSCredentialsFactory _awsCredentialsFactory;

public AWSUtilities(
IServiceProvider serviceProvider,
IToolInteractiveService toolInteractiveService,
IConsoleUtilities consoleUtilities,
IDirectoryManager directoryManager,
IOptionSettingHandler optionSettingHandler)
IOptionSettingHandler optionSettingHandler,
ICredentialProfileStoreChainFactory credentialChainFactory,
ISharedCredentialsFileFactory sharedCredentialsFileFactory,
IAWSCredentialsFactory awsCredentialsFactory)
{
_serviceProvider = serviceProvider;
_toolInteractiveService = toolInteractiveService;
_consoleUtilities = consoleUtilities;
_directoryManager = directoryManager;
_optionSettingHandler = optionSettingHandler;
_credentialChainFactory = credentialChainFactory;
_sharedCredentialsFileFactory = sharedCredentialsFileFactory;
_awsCredentialsFactory = awsCredentialsFactory;
}

public async Task<AWSCredentials> ResolveAWSCredentials(string? profileName)

/// <summary>
/// At a high level there are 2 possible return values for this function:
/// 1. <Credentials, regionName> In this case, both the credentials and region were able to be read from the profile.
/// 2. <Credentials, null>: In this case, the region was not able to be read from the profile, so we return null for it. The null case will be handled later on by <see cref="ResolveAWSRegion">.
/// </summary>
public async Task<Tuple<AWSCredentials, string?>> ResolveAWSCredentials(string? profileName)
{
async Task<AWSCredentials> Resolve()
async Task<Tuple<AWSCredentials, string?>> Resolve()
{
var chain = new CredentialProfileStoreChain();
var chain = _credentialChainFactory.Create();

// Use provided profile to read credentials
if (!string.IsNullOrEmpty(profileName))
{
if (chain.TryGetAWSCredentials(profileName, out var profileCredentials) &&
// Skip checking CanLoadCredentials for AssumeRoleAWSCredentials because it might require an MFA token and the callback hasn't been setup yet.
(profileCredentials is AssumeRoleAWSCredentials || await CanLoadCredentials(profileCredentials)))
{
_toolInteractiveService.WriteLine($"Configuring AWS Credentials from Profile {profileName}.");
return profileCredentials;
chain.TryGetProfile(profileName, out var profile);
// Return the credentials since they must be found at this point.
// For region, we try to read it from the profile. If it's not found in the profile, then return null and region selection will be handled later on by ResolveAWSRegion.
return Tuple.Create<AWSCredentials, string?>(profileCredentials, profile.Region?.SystemName);
}
else
{
Expand All @@ -65,14 +83,17 @@ async Task<AWSCredentials> Resolve()
}
}

// Use default credentials
try
{
var fallbackCredentials = FallbackCredentialsFactory.GetCredentials();
var fallbackCredentials = _awsCredentialsFactory.Create();

if (await CanLoadCredentials(fallbackCredentials))
{
// Always return the credentials since they must be found at this point.
// For region, we return null here, since it will read from default region in ResolveAWSRegion
_toolInteractiveService.WriteLine("Configuring AWS Credentials using AWS SDK credential search.");
return fallbackCredentials;
return Tuple.Create<AWSCredentials, string?>(fallbackCredentials, null);
}
}
catch (AmazonServiceException ex)
Expand All @@ -82,7 +103,8 @@ async Task<AWSCredentials> Resolve()
_toolInteractiveService.WriteDebugLine(ex.PrettyPrint());
}

var sharedCredentials = new SharedCredentialsFile();
// Use Shared Credentials
var sharedCredentials = _sharedCredentialsFileFactory.Create();
if (sharedCredentials.ListProfileNames().Count == 0)
{
throw new NoAWSCredentialsFoundException(DeployToolErrorCode.UnableToResolveAWSCredentials, "Unable to resolve AWS credentials to access AWS.");
Expand All @@ -93,21 +115,24 @@ async Task<AWSCredentials> Resolve()
if (chain.TryGetAWSCredentials(selectedProfileName, out var selectedProfileCredentials) &&
(await CanLoadCredentials(selectedProfileCredentials)))
{
return selectedProfileCredentials;
// Return the credentials since they must be found at this point.
// For region, we try to read it from the profile. If it's not found in the profile, then return null and region selection will be handled later on by ResolveAWSRegion.
chain.TryGetProfile(selectedProfileName, out var profile);
return Tuple.Create<AWSCredentials, string?>(selectedProfileCredentials, profile.Region?.SystemName);
}

throw new NoAWSCredentialsFoundException(DeployToolErrorCode.UnableToCreateAWSCredentials, $"Unable to create AWS credentials for profile {selectedProfileName}.");
}

var credentials = await Resolve();
var credentialsAndRegion = await Resolve();

if (credentials is AssumeRoleAWSCredentials assumeRoleAWSCredentials)
if (credentialsAndRegion.Item1 is AssumeRoleAWSCredentials assumeRoleAWSCredentials)
{
var assumeOptions = assumeRoleAWSCredentials.Options;
assumeOptions.MfaTokenCodeCallback = ActivatorUtilities.CreateInstance<AssumeRoleMfaTokenCodeCallback>(_serviceProvider, assumeOptions).Execute;
}

return credentials;
return credentialsAndRegion;
}

private async Task<bool> CanLoadCredentials(AWSCredentials credentials)
Expand Down
12 changes: 6 additions & 6 deletions src/AWS.Deploy.CLI/Commands/CommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ private Command BuildDeployCommand()
deploymentSettings = await _deploymentSettingsHandler.ReadSettings(applyPath);
}

var awsCredentials = await _awsUtilities.ResolveAWSCredentials(input.Profile ?? deploymentSettings?.AWSProfile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region ?? deploymentSettings?.AWSRegion);
var (awsCredentials, regionFromProfile) = await _awsUtilities.ResolveAWSCredentials(input.Profile ?? deploymentSettings?.AWSProfile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region ?? deploymentSettings?.AWSRegion ?? regionFromProfile);

_commandLineWrapper.RegisterAWSContext(awsCredentials, awsRegion);
_awsClientFactory.RegisterAWSContext(awsCredentials, awsRegion);
Expand Down Expand Up @@ -318,8 +318,8 @@ private Command BuildDeleteCommand()
_toolInteractiveService.Diagnostics = input.Diagnostics;
_toolInteractiveService.DisableInteractive = input.Silent;

var awsCredentials = await _awsUtilities.ResolveAWSCredentials(input.Profile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region);
var (awsCredentials, regionFromProfile) = await _awsUtilities.ResolveAWSCredentials(input.Profile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region ?? regionFromProfile);

_awsClientFactory.ConfigureAWSOptions(awsOption =>
{
Expand Down Expand Up @@ -401,8 +401,8 @@ private Command BuildListCommand()
{
_toolInteractiveService.Diagnostics = input.Diagnostics;

var awsCredentials = await _awsUtilities.ResolveAWSCredentials(input.Profile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region);
var (awsCredentials, regionFromProfile) = await _awsUtilities.ResolveAWSCredentials(input.Profile);
var awsRegion = _awsUtilities.ResolveAWSRegion(input.Region ?? regionFromProfile);

_awsClientFactory.ConfigureAWSOptions(awsOptions =>
{
Expand Down
17 changes: 17 additions & 0 deletions src/AWS.Deploy.CLI/CredentialProfileStoreChainFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime.CredentialManagement;

namespace AWS.Deploy.CLI
{
/// <inheritdoc />
public class CredentialProfileStoreChainFactory : ICredentialProfileStoreChainFactory
{
/// <inheritdoc />
public CredentialProfileStoreChain Create()
{
return new CredentialProfileStoreChain();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ public static void AddCustomServices(this IServiceCollection serviceCollection,
serviceCollection.TryAdd(new ServiceDescriptor(typeof(IEnvironmentVariableManager), typeof(EnvironmentVariableManager), lifetime));
serviceCollection.TryAdd(new ServiceDescriptor(typeof(IDeployToolWorkspaceMetadata), typeof(DeployToolWorkspaceMetadata), lifetime));
serviceCollection.TryAdd(new ServiceDescriptor(typeof(IDeploymentSettingsHandler), typeof(DeploymentSettingsHandler), lifetime));
serviceCollection.TryAdd(new ServiceDescriptor(typeof(ICredentialProfileStoreChainFactory), typeof(CredentialProfileStoreChainFactory), lifetime));
serviceCollection.TryAdd(new ServiceDescriptor(typeof(ISharedCredentialsFileFactory), typeof(SharedCredentialsFileFactory), lifetime));
serviceCollection.TryAdd(new ServiceDescriptor(typeof(IAWSCredentialsFactory), typeof(AWSCredentialsFactory), lifetime));

var packageJsonTemplate = typeof(PackageJsonGenerator).Assembly.ReadEmbeddedFile(PackageJsonGenerator.TemplateIdentifier);
serviceCollection.TryAdd(new ServiceDescriptor(typeof(IPackageJsonGenerator), (serviceProvider) => new PackageJsonGenerator(packageJsonTemplate), lifetime));
Expand Down
18 changes: 18 additions & 0 deletions src/AWS.Deploy.CLI/IAWSCredentialsFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime;

namespace AWS.Deploy.CLI
{
/// <summary>
/// Represents a factory for creating <see cref="AWSCredentials">
/// </summary>
public interface IAWSCredentialsFactory
{
/// <summary>
/// Creates <see cref="AWSCredentials">
/// </summary>
AWSCredentials Create();
}
}
18 changes: 18 additions & 0 deletions src/AWS.Deploy.CLI/ICredentialProfileStoreChainFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime.CredentialManagement;

namespace AWS.Deploy.CLI
{
/// <summary>
/// Represents a factory for creating <see cref="CredentialProfileStoreChain">
/// </summary>
public interface ICredentialProfileStoreChainFactory
{
/// <summary>
/// Creates a <see cref="CredentialProfileStoreChain">
/// </summary>
CredentialProfileStoreChain Create();
}
}
18 changes: 18 additions & 0 deletions src/AWS.Deploy.CLI/ISharedCredentialsFileFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime.CredentialManagement;

namespace AWS.Deploy.CLI
{
/// <summary>
/// Represents a factory for creating <see cref="SharedCredentialsFile">
/// </summary>
public interface ISharedCredentialsFileFactory
{
/// <summary>
/// Creates <see cref="SharedCredentialsFile">
/// </summary>
SharedCredentialsFile Create();
}
}
17 changes: 17 additions & 0 deletions src/AWS.Deploy.CLI/SharedCredentialsFileFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime.CredentialManagement;

namespace AWS.Deploy.CLI
{
/// <inheritdoc />
public class SharedCredentialsFileFactory : ISharedCredentialsFileFactory
{
/// <inheritdoc />
public SharedCredentialsFile Create()
{
return new SharedCredentialsFile();
}
}
}
Loading
Loading