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

Fixes issue #3479 where S3ForcePathStyle is unable to be read from a config file #3544

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 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);
}
}
}