Skip to content

Commit

Permalink
Fixes issue #3479 where S3ForcePathStyle is unable to be read from a …
Browse files Browse the repository at this point in the history
…credential profile
  • Loading branch information
peterrsongg committed Nov 5, 2024
1 parent ad13fd4 commit b808075
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 5 deletions.
18 changes: 18 additions & 0 deletions generator/.DevConfigs/666f52b5-8ab6-4817-b54c-f42d2d41bb46.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"core": {
"changeLogMessages": [
"Add S3ForcePathStyle as a config option in for credential profiles."
],
"type": "patch",
"updateMinimum": true
},
"services": [
{
"serviceName": "S3",
"type": "patch",
"changeLogMessages": [
"Fixes [issue 3479](https://github.com/aws/aws-sdk-net/issues/3479) where ForcePathStyle is unable to be read from the config file"
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ internal Dictionary<string, Dictionary<string, string>> NestedProperties
/// If true, the use of multi-region access points is disabled.
/// </summary>
public bool? S3DisableMultiRegionAccessPoints { get; set; }

/// <summary>
/// When true, S3 requests will always use path style addressing.
/// </summary>
public bool? S3ForcePathStyle { get; set; }

/// <summary>
/// The Sts Regional Endpoints Value as either legacy or regional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class SharedCredentialsFile : ICredentialProfileStore
private const string RequestMinCompressionSizeBytesField = "request_min_compression_size_bytes";
private const string ClientAppIdField = "sdk_ua_app_id";
private const string AccountIdEndpointModeField = "account_id_endpoint_mode";
private const string S3ForcePathStyleField = "s3_force_path_style";
private readonly Logger _logger = Logger.GetLogger(typeof(SharedCredentialsFile));

private static readonly HashSet<string> ReservedPropertyNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
Expand Down Expand Up @@ -104,7 +105,8 @@ public class SharedCredentialsFile : ICredentialProfileStore
DisableRequestCompressionField,
RequestMinCompressionSizeBytesField,
ClientAppIdField,
AccountIdEndpointModeField
AccountIdEndpointModeField,
S3ForcePathStyleField
};

/// <summary>
Expand Down Expand Up @@ -443,9 +445,13 @@ private void RegisterProfileInternal(CredentialProfile profile)

if (profile.ClientAppId != null)
reservedProperties[ClientAppIdField] = profile.ClientAppId;

if (profile.AccountIdEndpointMode != null)
reservedProperties[AccountIdEndpointModeField] = profile.AccountIdEndpointMode.ToString().ToLowerInvariant();

if (profile.S3ForcePathStyle != null)
reservedProperties[S3ForcePathStyleField] = profile.S3ForcePathStyle.ToString().ToLowerInvariant();

var profileDictionary = PropertyMapping.CombineProfileParts(
profile.Options, ReservedPropertyNames, reservedProperties, profile.Properties);

Expand Down Expand Up @@ -966,6 +972,21 @@ private bool TryGetProfile(string profileName, bool doRefresh, bool isSsoSession

#endif
}

string s3ForcePathStyleString;
bool? s3ForcePathStyle = null;
if (reservedProperties.TryGetValue(S3ForcePathStyleField, out s3ForcePathStyleString))
{
bool s3ForcePathStyleOut;
if (!bool.TryParse(s3ForcePathStyleString, out s3ForcePathStyleOut))
{
Logger.GetLogger(GetType()).InfoFormat("Invalid value {0} for {1} in profile {2}. A boolean true/false is expected.", s3ForcePathStyleString, S3ForcePathStyleField, profileName);
profile = null;
return false;
}
s3ForcePathStyle = s3ForcePathStyleOut;
}

profile = new CredentialProfile(profileName, profileOptions)
{
UniqueKey = toolkitArtifactGuid,
Expand All @@ -992,7 +1013,8 @@ private bool TryGetProfile(string profileName, bool doRefresh, bool isSsoSession
DisableRequestCompression = disableRequestCompression,
RequestMinCompressionSizeBytes = requestMinCompressionSizeBytes,
ClientAppId = clientAppId,
AccountIdEndpointMode = accountIdEndpointMode
AccountIdEndpointMode = accountIdEndpointMode,
S3ForcePathStyle = s3ForcePathStyle
};

if (!IsSupportedProfileType(profile.ProfileType))
Expand Down
33 changes: 30 additions & 3 deletions sdk/src/Services/S3/Custom/AmazonS3Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public partial class AmazonS3Config : ClientConfig
private const string AwsS3UsEast1RegionalEndpointsEnvironmentVariable = "AWS_S3_US_EAST_1_REGIONAL_ENDPOINT";
private const string DisableMRAPEnvName = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS";

private bool forcePathStyle = false;
private bool? _forcePathStyle;
private bool useAccelerateEndpoint = false;
private S3UsEast1RegionalEndpointValue? s3UsEast1RegionalEndpointValue;
private readonly string legacyUSEast1GlobalRegionSystemName = RegionEndpoint.USEast1.SystemName;
Expand All @@ -61,13 +61,40 @@ public IS3ExpressCredentialProvider S3ExpressCredentialProvider
set { s3ExpressCredentialProvider = value; }
}

private object _forcePathStyleLock = new object();
/// <summary>
/// When true, requests will always use path style addressing.
/// </summary>
public bool ForcePathStyle
{
get { return forcePathStyle; }
set { forcePathStyle = value; }
get
{
if (_forcePathStyle.HasValue)
{
return _forcePathStyle.GetValueOrDefault();
}

ResolveCredentialProfile();

lock (_forcePathStyleLock)
{
if (_forcePathStyle.HasValue)
{
return _forcePathStyle.Value;
}

_forcePathStyle = _profile?.S3ForcePathStyle;
return _forcePathStyle.GetValueOrDefault();
}
}

set
{
lock (_forcePathStyleLock)
{
_forcePathStyle = value;
}
}
}

/// <summary>
Expand Down
81 changes: 81 additions & 0 deletions sdk/test/Services/S3/UnitTests/Custom/S3ForcePathStyleTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Amazon.S3;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using AWSSDK_DotNet.CommonTest.Utils;
using Amazon.Runtime.CredentialManagement;

namespace AWSSDK.UnitTests
{
[TestClass]
public class S3ForcePathStyleTests
{
private static readonly string ProfileText =
@"[enable_force_path_style]
region = us-west-2
aws_access_key_id = default_aws_access_key_id
aws_secret_access_key = default_aws_secret_access_key
s3_force_path_style = true
[disable_force_path_style]
region = us-west-2
aws_access_key_id = other_aws_access_key_id
aws_secret_access_key = other_aws_secret_access_key
s3_force_path_style = false";

private const string AWSProfileVariable = "AWS_PROFILE";
private string _beginningAWSProfileEnvironmentValue;
private string _tempCredentialsFilePath;

[TestInitialize]
public void Initialize()
{
// Save off current environment variable value to restore later
_beginningAWSProfileEnvironmentValue = Environment.GetEnvironmentVariable(AWSProfileVariable);

// Then clear the current value so every test is starting from a clean slate
Environment.SetEnvironmentVariable(AWSProfileVariable, "");

// set credentials file and use it to load CredentialProfileStoreChain
_tempCredentialsFilePath = Path.GetTempFileName();
File.WriteAllText(_tempCredentialsFilePath, ProfileText);
ReflectionHelpers.Invoke(typeof(AmazonS3Config), "credentialProfileChain", new CredentialProfileStoreChain(_tempCredentialsFilePath));
ReflectionHelpers.Invoke(typeof(AmazonS3Config), "_triedToResolveProfile", false);
}

[TestCleanup]
public void RestoreOriginalSettings()
{
Environment.SetEnvironmentVariable(AWSProfileVariable, _beginningAWSProfileEnvironmentValue);
File.Delete(_tempCredentialsFilePath);
}

[TestMethod]
[TestCategory("S3")]
public void CredentialProfileEnable_ShouldApplyToS3Config()
{
Environment.SetEnvironmentVariable(AWSProfileVariable, "enable_force_path_style");
var config = new AmazonS3Config();
Assert.IsTrue(config.ForcePathStyle);
}

[TestMethod]
[TestCategory("S3")]
public void UnsetForcePathStyleShouldDefaultToFalse()
{
var config = new AmazonS3Config();
Assert.IsFalse(config.ForcePathStyle);
}

[TestMethod]
[TestCategory("S3")]
public void ConfigShouldOverrideProfile()
{
Environment.SetEnvironmentVariable(AWSProfileVariable, "enable_force_path_style");
var config = new AmazonS3Config
{
ForcePathStyle = false
};
Assert.IsFalse(config.ForcePathStyle);
}
}
}

0 comments on commit b808075

Please sign in to comment.