Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
aws-sdk-dotnet-automation committed Nov 18, 2024
2 parents 2963053 + 9f812e9 commit 5ed05e5
Show file tree
Hide file tree
Showing 20 changed files with 1,101 additions and 27 deletions.
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
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();
}
}
}
8 changes: 6 additions & 2 deletions src/AWS.Deploy.Orchestration/CDK/CDKBootstrapTemplate.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,11 @@ Resources:
- Id: CleanupOldVersions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 365
NoncurrentDays: 30
- Id: AbortIncompleteMultipartUploads
Status: Enabled
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 1
UpdateReplacePolicy: Delete
DeletionPolicy: Delete
StagingBucketPolicy:
Expand Down Expand Up @@ -611,7 +615,7 @@ Resources:
Type: String
Name:
Fn::Sub: /cdk-bootstrap/${Qualifier}/version
Value: "23"
Value: "25"
Outputs:
BucketName:
Description: The name of the S3 bucket owned by the CDK toolkit stack
Expand Down
2 changes: 1 addition & 1 deletion src/AWS.Deploy.Orchestration/Data/AWSResourceQueryer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ public async Task<List<PlatformSummary>> GetElasticBeanstalkPlatformArns(string?
if (string.IsNullOrEmpty(version.PlatformCategory) || string.IsNullOrEmpty(version.PlatformBranchLifecycleState))
continue;

if (!version.PlatformBranchLifecycleState.Equals("Supported"))
if (!(version.PlatformBranchLifecycleState.Equals("Supported") || version.PlatformBranchLifecycleState.Equals("Deprecated")))
continue;

platformVersions.Add(version);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<PackageIcon>icon.png</PackageIcon>
<PackageProjectUrl>https://github.com/aws/aws-dotnet-deploy</PackageProjectUrl>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>1.27.0</Version>
<Version>1.28.0</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
<PackageProjectUrl>https://github.com/aws/aws-dotnet-deploy</PackageProjectUrl>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\public.snk</AssemblyOriginatorKeyFile>
<Version>1.27.0</Version>
<Version>1.28.0</Version>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AWSSDK.Core" Version="3.7.303.20" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.22" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="6.0.36" />
<!-- We are pining Newtonsoft.Json to 13.0.1 to maintain compatibility with the VS Toolkit.
https://devblogs.microsoft.com/visualstudio/using-newtonsoft-json-in-a-visual-studio-extension/-->
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
Expand Down
25 changes: 25 additions & 0 deletions test/AWS.Deploy.CLI.UnitTests/AWSCredentialsFactoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

using Amazon.Runtime;
using Xunit;

namespace AWS.Deploy.CLI.UnitTests
{
public class AWSCredentialsFactoryTests
{
[Fact]
public void Create_ReturnsAWSCredentialsInstance()
{
// Arrange
var factory = new AWSCredentialsFactory();

// Act
var result = factory.Create();

// Assert
Assert.NotNull(result);
Assert.IsAssignableFrom<AWSCredentials>(result);
}
}
}
Loading

0 comments on commit 5ed05e5

Please sign in to comment.