/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Amazon.Runtime.CredentialManagement;
using Amazon.Runtime.Internal.Util;
using Amazon.Util.Internal;
namespace Amazon.Runtime.Internal
{
///
/// This class gets the CSM configuration if set.
/// The priority goes
/// 1. App.config / instantiate on the AWSConfigs class
/// 2. Environment variable
/// 3. Shared Profile
///
public class CSMFallbackConfigChain
{
private readonly ILogger LOGGER = Logger.GetLogger(typeof(CSMFallbackConfigChain));
private static CredentialProfileStoreChain credentialProfileChain = new CredentialProfileStoreChain(AWSConfigs.AWSProfilesLocation);
public delegate void ConfigurationSource();
public List AllGenerators { get; set; }
internal bool IsConfigSet { get; set; }
public string ConfigSource { get; set; }
public CSMConfiguration CSMConfiguration { get; internal set; }
public CSMFallbackConfigChain()
{
CSMConfiguration = new CSMConfiguration();
AllGenerators = new List
{
() => new AppConfigCSMConfigs(this),
() => new EnvironmentVariableCSMConfigs(this),
() => new ProfileCSMConfigs(credentialProfileChain, this)
};
}
public CSMConfiguration GetCSMConfig()
{
foreach (var generator in AllGenerators)
{
try
{
generator();
if (IsConfigSet)
{
break;
}
}
catch(Exception e)
{
LOGGER.Error(e, "Error looking for CSM configuration");
}
}
return CSMConfiguration;
}
}
///
/// Determine CSM configs from shared profile file.
///
public class ProfileCSMConfigs
{
private const string CSM_ENABLED = "csm_enabled";
private const string CSM_CLIENTID = "csm_clientid";
private const string CSM_HOST = "csm_host";
private const string CSM_PORT = "csm_port";
private const string CSM_PROFILE_ERROR_MSG = "CSM configurations not found using profile store.";
private string ProfileName { get; set; }
public ProfileCSMConfigs(CSMFallbackConfigChain cSMFallbackConfigChain, string profileName, IDictionary profileProperties)
{
ProfileName = profileName;
Setup(cSMFallbackConfigChain, profileProperties);
}
public ProfileCSMConfigs(ICredentialProfileSource source, CSMFallbackConfigChain cSMFallbackConfigChain)
{
ProfileName = FallbackCredentialsFactory.GetProfileName();
CredentialProfile profile;
if (!source.TryGetProfile(ProfileName, out profile))
{
return;
}
Setup(cSMFallbackConfigChain, profile.Properties);
}
private void Setup(CSMFallbackConfigChain cSMFallbackConfigChain, IDictionary profileProperties)
{
var logger = Logger.GetLogger(typeof(ProfileCSMConfigs));
var csmConfiguration = cSMFallbackConfigChain.CSMConfiguration;
string csm_enabled;
if (!profileProperties.TryGetValue(CSM_ENABLED, out csm_enabled))
{
return;
}
cSMFallbackConfigChain.IsConfigSet = true;
cSMFallbackConfigChain.ConfigSource = "shared profile";
bool enabled;
if (bool.TryParse(csm_enabled, out enabled))
{
csmConfiguration.Enabled = enabled;
}
else
{
throw new AmazonClientException("Unexpected profile variable value type " + CSM_ENABLED + ". Set a valid boolean value.");
}
if (csmConfiguration.Enabled)
{
string clientId;
if (profileProperties.TryGetValue(CSM_CLIENTID, out clientId))
{
csmConfiguration.ClientId = clientId;
}
string csm_port;
if (profileProperties.TryGetValue(CSM_PORT, out csm_port))
{
int port;
if (int.TryParse(csm_port, out port))
{
csmConfiguration.Port = port;
}
else
{
throw new AmazonClientException("Unexpected profile variable value type " + CSM_PORT + ". Set a valid integer value.");
}
}
string csm_host;
if (profileProperties.TryGetValue(CSM_HOST, out csm_host))
{
if (!string.IsNullOrEmpty(csm_host))
{
csmConfiguration.Host = csm_host;
}
}
}
logger.InfoFormat(string.Format(CultureInfo.InvariantCulture,
"CSM configurations found using profile store for the profile = {0}: values are CSM enabled = {1}, host = {2}, port = {3}, clientid = {4}",
ProfileName, csmConfiguration.Enabled, csmConfiguration.Host, csmConfiguration.Port, csmConfiguration.ClientId));
}
}
///
/// Determine CSM configs from environment variables.
///
public class EnvironmentVariableCSMConfigs
{
private const string CSM_ENABLED = "AWS_CSM_ENABLED";
private const string CSM_CLIENTID = "AWS_CSM_CLIENT_ID";
private const string CSM_HOST = "AWS_CSM_HOST";
private const string CSM_PORT = "AWS_CSM_PORT";
private IEnvironmentVariableRetriever environmentRetriever { get; set; } = EnvironmentVariableSource.Instance.EnvironmentVariableRetriever;
public EnvironmentVariableCSMConfigs(IEnvironmentVariableRetriever environmentRetriever, CSMFallbackConfigChain cSMFallbackConfigChain)
{
this.environmentRetriever = environmentRetriever;
SetupConfiguration(cSMFallbackConfigChain);
}
public EnvironmentVariableCSMConfigs(CSMFallbackConfigChain cSMFallbackConfigChain)
{
SetupConfiguration(cSMFallbackConfigChain);
}
private void SetupConfiguration(CSMFallbackConfigChain cSMFallbackConfigChain)
{
var csmConfiguration = cSMFallbackConfigChain.CSMConfiguration;
var logger = Logger.GetLogger(typeof(EnvironmentVariableCSMConfigs));
var enabled = environmentRetriever.GetEnvironmentVariable(CSM_ENABLED);
if (string.IsNullOrEmpty(enabled))
{
return;
}
cSMFallbackConfigChain.IsConfigSet = true;
cSMFallbackConfigChain.ConfigSource = "environment variable";
bool csm_enabled;
if (bool.TryParse(enabled, out csm_enabled))
{
csmConfiguration.Enabled = csm_enabled;
}
else
{
throw new AmazonClientException("Unexpected environment variable value type " + CSM_ENABLED + ". Set a valid boolean value.");
}
if (csmConfiguration.Enabled)
{
csmConfiguration.ClientId = environmentRetriever.GetEnvironmentVariable(CSM_CLIENTID) ?? csmConfiguration.ClientId;
string portValue = environmentRetriever.GetEnvironmentVariable(CSM_PORT);
if (!string.IsNullOrEmpty(portValue))
{
int port;
if (int.TryParse(portValue, out port))
{
csmConfiguration.Port = port;
}
else
{
throw new AmazonClientException("Unexpected environment variable value type " + CSM_PORT + ". Set a valid integer value.");
}
}
string hostValue = environmentRetriever.GetEnvironmentVariable(CSM_HOST);
if(!string.IsNullOrEmpty(hostValue))
{
csmConfiguration.Host = hostValue;
}
}
logger.InfoFormat(string.Format(CultureInfo.InvariantCulture,
"CSM configurations found using environment variable. values are CSM enabled = {0}, host = {1}, port = {2}, clientid = {3}",
csmConfiguration.Enabled, csmConfiguration.Host, csmConfiguration.Port, csmConfiguration.ClientId));
}
}
///
/// Determine CSM configs from AWSConfigs class.
///
public class AppConfigCSMConfigs
{
public AppConfigCSMConfigs(CSMFallbackConfigChain cSMFallbackConfigChain)
{
var csmConfiguration = cSMFallbackConfigChain.CSMConfiguration;
var logger = Logger.GetLogger(typeof(AppConfigCSMConfigs));
if(!AWSConfigs.CSMConfig.CSMEnabled.HasValue)
{
return;
}
cSMFallbackConfigChain.IsConfigSet = true;
if (!AWSConfigs.CSMConfig.CSMEnabled.GetValueOrDefault())
{
return;
}
cSMFallbackConfigChain.ConfigSource = "app config";
csmConfiguration.Enabled = AWSConfigs.CSMConfig.CSMEnabled.GetValueOrDefault();
if (csmConfiguration.Enabled)
{
if (!string.IsNullOrEmpty(AWSConfigs.CSMConfig.CSMClientId))
{
csmConfiguration.ClientId = AWSConfigs.CSMConfig.CSMClientId;
}
csmConfiguration.Host = AWSConfigs.CSMConfig.CSMHost;
csmConfiguration.Port = AWSConfigs.CSMConfig.CSMPort;
logger.InfoFormat(string.Format(CultureInfo.InvariantCulture,
"CSM configurations found using application configuration file. values are CSM enabled = {0}, host = {1}, port = {2}, clientid = {3}",
csmConfiguration.Enabled, csmConfiguration.Host, csmConfiguration.Port, csmConfiguration.ClientId));
}
}
}
}