Skip to content

Commit 0ebee71

Browse files
committed
allow for the hash character in configuration values
1 parent d2a68f1 commit 0ebee71

File tree

2 files changed

+128
-7
lines changed

2 files changed

+128
-7
lines changed

src/aws-cpp-sdk-core/source/config/AWSConfigFileProfileConfigLoader.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
*/
55

66
#include <aws/core/config/AWSProfileConfigLoader.h>
7+
#include <aws/core/utils/memory/stl/AWSArray.h>
78
#include <aws/core/utils/memory/stl/AWSSet.h>
89
#include <aws/core/utils/memory/stl/AWSStreamFwd.h>
910
#include <aws/core/utils/StringUtils.h>
1011
#include <aws/core/utils/logging/LogMacros.h>
1112
#include <fstream>
1213

14+
namespace {
15+
Aws::Array<const char*, 2> COMMENT_START_SEQ{" #", " ;"};
16+
Aws::Array<const char, 2> COMMENT_CHARS{'#', ';'};
17+
}
18+
1319
namespace Aws
1420
{
1521
namespace Config
@@ -46,8 +52,6 @@ namespace Aws
4652
static const size_t IDENTIFIER_ALLOWED_CHARACTERS_SZ = sizeof(IDENTIFIER_ALLOWED_CHARACTERS) - 1;
4753
const char WHITESPACE_CHARACTERS[] = "\t ";
4854
static const size_t WHITESPACE_CHARACTERS_SZ = sizeof(WHITESPACE_CHARACTERS) - 1;
49-
const char COMMENT_START[] = "#;";
50-
static const size_t COMMENT_START_SZ = sizeof(COMMENT_START) - 1;
5155

5256
struct ProfilePropertyAccessFunctions
5357
{
@@ -125,7 +129,7 @@ namespace Aws
125129
rawLine.pop_back(); // Remove carriage return character ('\r')
126130
}
127131

128-
Aws::String line = rawLine.substr(0, rawLine.find_first_of(COMMENT_START)); // ignore comments
132+
const Aws::String line{StripCommentFromLine(rawLine)};
129133
if (line.empty() || line.length() < ASSUME_EMPTY_LEN || line.find_first_not_of(WHITESPACE_CHARACTERS) == Aws::String::npos)
130134
{
131135
continue;
@@ -384,8 +388,7 @@ namespace Aws
384388
}
385389
pos++;
386390
pos = line.find_first_not_of(WHITESPACE_CHARACTERS, pos);
387-
if(pos != Aws::String::npos &&
388-
std::find(COMMENT_START, COMMENT_START + COMMENT_START_SZ, line[pos]) == COMMENT_START + COMMENT_START_SZ)
391+
if(pos != Aws::String::npos && std::find(COMMENT_CHARS.begin(), COMMENT_CHARS.end(), line[pos]) == COMMENT_CHARS.end())
389392
{
390393
AWS_LOGSTREAM_ERROR(PARSER_TAG, "Found unexpected characters after closing bracket of Section Identifier " << line);
391394
break;
@@ -532,6 +535,26 @@ namespace Aws
532535
}
533536
}
534537

538+
/**
539+
* Returns a configuration file line with inline comments removed.
540+
*
541+
* @param line a raw line read in from configuration.
542+
* @return the raw line with any commented out sections removed.
543+
*/
544+
static Aws::String StripCommentFromLine(const Aws::String& line) {
545+
// entire line is commented if the first char is comment, otherwise we want whitespace + comment delimitation
546+
if (line.empty() || std::any_of(COMMENT_CHARS.begin(), COMMENT_CHARS.end(),
547+
[&line](const char firstChar) -> bool { return firstChar == line.front(); })) {
548+
return {};
549+
}
550+
551+
size_t commentLocation = Aws::String::npos;
552+
for (const auto* const commentChar : COMMENT_START_SEQ) {
553+
commentLocation = std::min(commentLocation, line.find(commentChar));
554+
}
555+
return {line.substr(0, commentLocation)};
556+
}
557+
535558
Aws::Map<String, Profile> m_foundProfiles;
536559
Aws::Map<String, Profile::SsoSession> m_foundSsoSessions;
537560
};

tests/aws-cpp-sdk-core-tests/aws/config/AWSConfigFileProfileConfigLoaderTest.cpp

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,13 @@ R"(
348348
;another comment
349349
[ default ]
350350
source_profile = base)" "\t" R"(
351-
credential_process = echo '{ "Version": 1, "AccessKeyId": "ASIARTESTID", "SecretAccessKey": "TESTSECRETKEY", "SessionToken": "TESTSESSIONTOKEN", "Expiration": "2022-05-02T18:36:00+00:00" }'#COMMENT
351+
credential_process = echo '{ "Version": 1, "AccessKeyId": "ASIARTESTID", "SecretAccessKey": "TESTSECRETKEY", "SessionToken": "TESTSESSIONTOKEN", "Expiration": "2022-05-02T18:36:00+00:00" }' #COMMENT
352352
; Comment to be ignored
353353
)"
354354
R"( )" // to avoid blank space removals by an IDE.
355355
R"(
356356
[ profile )" "\t\t\t" R"( base ]
357-
region = us-east-1#sa-east-3
357+
region = us-east-1 #sa-east-3
358358
#region = commented-out region
359359
)";
360360

@@ -484,3 +484,101 @@ aws_secret_access_key = correct_secret)";
484484
ASSERT_EQ("correct_secret", profiles.at(complicatedProfileName).GetCredentials().GetAWSSecretKey());
485485
}
486486
}
487+
488+
TEST_F(AWSConfigFileProfileConfigLoaderTest, TestSsoStartUrlWithHash) {
489+
TempFile configFile(std::ios_base::out | std::ios_base::trunc);
490+
ASSERT_TRUE(configFile.good());
491+
492+
configFile << R"([profile gustave])" << "\n"
493+
<< R"(sso_account_id = 333333333333)" << "\n"
494+
<< R"(sso_role_name = PictoAccess)" << "\n"
495+
<< R"(sso_start_url = https://lumiere.com/for-those-who-come-after#)" << "\n"
496+
<< R"(sso_region = eu-west-3)" << "\n"
497+
<< R"(sso_registration_scopes = sso:account:access)" << "\n"
498+
<< R"(region = eu-west-3)" << "\n"
499+
<< R"(output = json)" << "\n";
500+
501+
configFile.flush();
502+
503+
AWSConfigFileProfileConfigLoader loader(configFile.GetFileName(), true);
504+
ASSERT_TRUE(loader.Load());
505+
const auto& loadedProfiles = loader.GetProfiles();
506+
ASSERT_TRUE(loadedProfiles.size() == 1);
507+
const auto& profile = loadedProfiles.find("gustave");
508+
ASSERT_TRUE(profile != loadedProfiles.end());
509+
ASSERT_STREQ("https://lumiere.com/for-those-who-come-after#", profile->second.GetSsoStartUrl().c_str());
510+
}
511+
512+
TEST_F(AWSConfigFileProfileConfigLoaderTest, TestSsoStartUrlWithComment) {
513+
TempFile configFile(std::ios_base::out | std::ios_base::trunc);
514+
ASSERT_TRUE(configFile.good());
515+
516+
configFile << R"([profile lune])" << "\n"
517+
<< R"(sso_account_id = 333333333333)" << "\n"
518+
<< R"(sso_role_name = PictoAccess)" << "\n"
519+
<< R"(sso_start_url = https://lumiere.com/for-those-who-come-after # stained)" << "\n"
520+
<< R"(sso_region = eu-west-3)" << "\n"
521+
<< R"(sso_registration_scopes = sso:account:access)" << "\n"
522+
<< R"(region = eu-west-3)" << "\n"
523+
<< R"(output = json)" << "\n";
524+
525+
configFile.flush();
526+
527+
AWSConfigFileProfileConfigLoader loader(configFile.GetFileName(), true);
528+
ASSERT_TRUE(loader.Load());
529+
const auto& loadedProfiles = loader.GetProfiles();
530+
ASSERT_TRUE(loadedProfiles.size() == 1);
531+
const auto& profile = loadedProfiles.find("lune");
532+
ASSERT_TRUE(profile != loadedProfiles.end());
533+
ASSERT_STREQ("https://lumiere.com/for-those-who-come-after", profile->second.GetSsoStartUrl().c_str());
534+
}
535+
536+
TEST_F(AWSConfigFileProfileConfigLoaderTest, TestSsoStartUrlLineCommnent) {
537+
TempFile configFile(std::ios_base::out | std::ios_base::trunc);
538+
ASSERT_TRUE(configFile.good());
539+
540+
configFile << R"([profile maelle])" << "\n"
541+
<< R"(sso_account_id = 333333333333)" << "\n"
542+
<< R"(sso_role_name = PictoAccess)" << "\n"
543+
<< R"(sso_start_url = https://lumiere.com/for-those-who-come-after # stendahl pre nerf)" << "\n"
544+
<< R"(#sso_start_url = https://lumiere.com/verso)" << "\n"
545+
<< R"(sso_region = eu-west-3)" << "\n"
546+
<< R"(sso_registration_scopes = sso:account:access)" << "\n"
547+
<< R"(region = eu-west-3)" << "\n"
548+
<< R"(output = json)" << "\n";
549+
550+
configFile.flush();
551+
552+
AWSConfigFileProfileConfigLoader loader(configFile.GetFileName(), true);
553+
ASSERT_TRUE(loader.Load());
554+
const auto& loadedProfiles = loader.GetProfiles();
555+
ASSERT_TRUE(loadedProfiles.size() == 1);
556+
const auto& profile = loadedProfiles.find("maelle");
557+
ASSERT_TRUE(profile != loadedProfiles.end());
558+
ASSERT_STREQ("https://lumiere.com/for-those-who-come-after", profile->second.GetSsoStartUrl().c_str());
559+
}
560+
561+
TEST_F(AWSConfigFileProfileConfigLoaderTest, TestSsoStartUrlShouldHandleMultipleCommentsCorrectly) {
562+
TempFile configFile(std::ios_base::out | std::ios_base::trunc);
563+
ASSERT_TRUE(configFile.good());
564+
565+
configFile << R"([profile maelle])" << "\n"
566+
<< R"(sso_account_id = 333333333333)" << "\n"
567+
<< R"(sso_role_name = PictoAccess)" << "\n"
568+
<< R"(sso_start_url = https://lumiere.com/for-those-who-come-after#when-one-falls-we-continue ; painted power # stendahl pre nerf)" << "\n"
569+
<< R"(;#sso_start_url = https://lumiere.com/verso)" << "\n"
570+
<< R"(sso_region = eu-west-3)" << "\n"
571+
<< R"(sso_registration_scopes = sso:account:access)" << "\n"
572+
<< R"(region = eu-west-3)" << "\n"
573+
<< R"(output = json)" << "\n";
574+
575+
configFile.flush();
576+
577+
AWSConfigFileProfileConfigLoader loader(configFile.GetFileName(), true);
578+
ASSERT_TRUE(loader.Load());
579+
const auto& loadedProfiles = loader.GetProfiles();
580+
ASSERT_TRUE(loadedProfiles.size() == 1);
581+
const auto& profile = loadedProfiles.find("maelle");
582+
ASSERT_TRUE(profile != loadedProfiles.end());
583+
ASSERT_STREQ("https://lumiere.com/for-those-who-come-after#when-one-falls-we-continue", profile->second.GetSsoStartUrl().c_str());
584+
}

0 commit comments

Comments
 (0)