1 | /* |
2 | * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"). |
5 | * You may not use this file except in compliance with the License. |
6 | * A copy of the License is located at |
7 | * |
8 | * http://aws.amazon.com/apache2.0 |
9 | * |
10 | * or in the "license" file accompanying this file. This file is distributed |
11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
12 | * express or implied. See the License for the specific language governing |
13 | * permissions and limitations under the License. |
14 | */ |
15 | |
16 | #include <aws/core/config/AWSProfileConfigLoader.h> |
17 | #include <aws/core/internal/AWSHttpResourceClient.h> |
18 | #include <aws/core/auth/AWSCredentialsProvider.h> |
19 | #include <aws/core/utils/memory/stl/AWSList.h> |
20 | #include <aws/core/utils/memory/stl/AWSStreamFwd.h> |
21 | #include <aws/core/utils/StringUtils.h> |
22 | #include <aws/core/utils/logging/LogMacros.h> |
23 | #include <aws/core/utils/json/JsonSerializer.h> |
24 | #include <fstream> |
25 | |
26 | namespace Aws |
27 | { |
28 | namespace Config |
29 | { |
30 | using namespace Aws::Utils; |
31 | using namespace Aws::Auth; |
32 | |
33 | static const char* const CONFIG_LOADER_TAG = "Aws::Config::AWSProfileConfigLoader" ; |
34 | #ifdef _MSC_VER |
35 | // VS2015 compiler's bug, warning s_CoreErrorsMapper: symbol will be dynamically initialized (implementation limitation) |
36 | AWS_SUPPRESS_WARNING(4592, |
37 | static Aws::UniquePtr<ConfigAndCredentialsCacheManager> s_configManager(nullptr); |
38 | ) |
39 | #else |
40 | static Aws::UniquePtr<ConfigAndCredentialsCacheManager> s_configManager(nullptr); |
41 | #endif |
42 | |
43 | static const char CONFIG_CREDENTIALS_CACHE_MANAGER_TAG[] = "ConfigAndCredentialsCacheManager" ; |
44 | |
45 | bool AWSProfileConfigLoader::Load() |
46 | { |
47 | if(LoadInternal()) |
48 | { |
49 | AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully reloaded configuration." ); |
50 | m_lastLoadTime = DateTime::Now(); |
51 | AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "reloaded config at " |
52 | << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); |
53 | return true; |
54 | } |
55 | |
56 | AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Failed to reload configuration." ); |
57 | return false; |
58 | } |
59 | |
60 | bool AWSProfileConfigLoader::PersistProfiles(const Aws::Map<Aws::String, Profile>& profiles) |
61 | { |
62 | if(PersistInternal(profiles)) |
63 | { |
64 | AWS_LOGSTREAM_INFO(CONFIG_LOADER_TAG, "Successfully persisted configuration." ); |
65 | m_profiles = profiles; |
66 | m_lastLoadTime = DateTime::Now(); |
67 | AWS_LOGSTREAM_TRACE(CONFIG_LOADER_TAG, "persisted config at " |
68 | << m_lastLoadTime.ToGmtString(DateFormat::ISO_8601)); |
69 | return true; |
70 | } |
71 | |
72 | AWS_LOGSTREAM_WARN(CONFIG_LOADER_TAG, "Failed to persist configuration." ); |
73 | return false; |
74 | } |
75 | |
76 | static const char REGION_KEY[] = "region" ; |
77 | static const char ACCESS_KEY_ID_KEY[] = "aws_access_key_id" ; |
78 | static const char SECRET_KEY_KEY[] = "aws_secret_access_key" ; |
79 | static const char SESSION_TOKEN_KEY[] = "aws_session_token" ; |
80 | static const char ROLE_ARN_KEY[] = "role_arn" ; |
81 | static const char EXTERNAL_ID_KEY[] = "external_id" ; |
82 | static const char CREDENTIAL_PROCESS_COMMAND[] = "credential_process" ; |
83 | static const char SOURCE_PROFILE_KEY[] = "source_profile" ; |
84 | static const char PROFILE_PREFIX[] = "profile " ; |
85 | static const char EQ = '='; |
86 | static const char LEFT_BRACKET = '['; |
87 | static const char RIGHT_BRACKET = ']'; |
88 | static const char PARSER_TAG[] = "Aws::Config::ConfigFileProfileFSM" ; |
89 | |
90 | class ConfigFileProfileFSM |
91 | { |
92 | public: |
93 | ConfigFileProfileFSM() : m_parserState(START) {} |
94 | |
95 | const Aws::Map<String, Profile>& GetProfiles() const { return m_foundProfiles; } |
96 | |
97 | void ParseStream(Aws::IStream& stream) |
98 | { |
99 | static const size_t ASSUME_EMPTY_LEN = 3; |
100 | |
101 | Aws::String line; |
102 | while(std::getline(stream, line) && m_parserState != FAILURE) |
103 | { |
104 | if (line.empty() || line.length() < ASSUME_EMPTY_LEN) |
105 | { |
106 | continue; |
107 | } |
108 | |
109 | auto openPos = line.find(LEFT_BRACKET); |
110 | auto closePos = line.find(RIGHT_BRACKET); |
111 | |
112 | switch(m_parserState) |
113 | { |
114 | |
115 | case START: |
116 | if(openPos != std::string::npos && closePos != std::string::npos) |
117 | { |
118 | FlushProfileAndReset(line, openPos, closePos); |
119 | m_parserState = PROFILE_FOUND; |
120 | } |
121 | break; |
122 | |
123 | //fallthrough here is intentional to reduce duplicate logic |
124 | case PROFILE_KEY_VALUE_FOUND: |
125 | if(openPos != std::string::npos && closePos != std::string::npos) |
126 | { |
127 | m_parserState = PROFILE_FOUND; |
128 | FlushProfileAndReset(line, openPos, closePos); |
129 | break; |
130 | } |
131 | // fall through |
132 | case PROFILE_FOUND: |
133 | { |
134 | auto equalsPos = line.find(EQ); |
135 | if (equalsPos != std::string::npos) |
136 | { |
137 | auto key = line.substr(0, equalsPos); |
138 | auto value = line.substr(equalsPos + 1); |
139 | m_profileKeyValuePairs[StringUtils::Trim(key.c_str())] = |
140 | StringUtils::Trim(value.c_str()); |
141 | m_parserState = PROFILE_KEY_VALUE_FOUND; |
142 | } |
143 | |
144 | break; |
145 | } |
146 | default: |
147 | m_parserState = FAILURE; |
148 | break; |
149 | } |
150 | } |
151 | |
152 | FlushProfileAndReset(line, std::string::npos, std::string::npos); |
153 | } |
154 | |
155 | private: |
156 | |
157 | void FlushProfileAndReset(Aws::String& line, size_t openPos, size_t closePos) |
158 | { |
159 | if(!m_currentWorkingProfile.empty() && !m_profileKeyValuePairs.empty()) |
160 | { |
161 | Profile profile; |
162 | profile.SetName(m_currentWorkingProfile); |
163 | |
164 | auto regionIter = m_profileKeyValuePairs.find(REGION_KEY); |
165 | if (regionIter != m_profileKeyValuePairs.end()) |
166 | { |
167 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found region " << regionIter->second); |
168 | profile.SetRegion(regionIter->second); |
169 | } |
170 | |
171 | auto accessKeyIdIter = m_profileKeyValuePairs.find(ACCESS_KEY_ID_KEY); |
172 | Aws::String accessKey, secretKey, sessionToken; |
173 | if (accessKeyIdIter != m_profileKeyValuePairs.end()) |
174 | { |
175 | accessKey = accessKeyIdIter->second; |
176 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found access key " << accessKey); |
177 | |
178 | auto secretAccessKeyIter = m_profileKeyValuePairs.find(SECRET_KEY_KEY); |
179 | auto sessionTokenIter = m_profileKeyValuePairs.find(SESSION_TOKEN_KEY); |
180 | if (secretAccessKeyIter != m_profileKeyValuePairs.end()) |
181 | { |
182 | secretKey = secretAccessKeyIter->second; |
183 | } |
184 | else |
185 | { |
186 | AWS_LOGSTREAM_ERROR(PARSER_TAG, "No secret access key found even though an access key was specified. This will cause all signed AWS calls to fail." ); |
187 | } |
188 | |
189 | if (sessionTokenIter != m_profileKeyValuePairs.end()) |
190 | { |
191 | sessionToken = sessionTokenIter->second; |
192 | } |
193 | |
194 | profile.SetCredentials(Aws::Auth::AWSCredentials(accessKey, secretKey, sessionToken)); |
195 | } |
196 | |
197 | auto assumeRoleArnIter = m_profileKeyValuePairs.find(ROLE_ARN_KEY); |
198 | if (assumeRoleArnIter != m_profileKeyValuePairs.end()) |
199 | { |
200 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found role arn " << assumeRoleArnIter->second); |
201 | profile.SetRoleArn(assumeRoleArnIter->second); |
202 | } |
203 | |
204 | auto externalIdIter = m_profileKeyValuePairs.find(EXTERNAL_ID_KEY); |
205 | if (externalIdIter != m_profileKeyValuePairs.end()) |
206 | { |
207 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found external id " << externalIdIter->second); |
208 | profile.SetExternalId(externalIdIter->second); |
209 | } |
210 | |
211 | auto sourceProfileIter = m_profileKeyValuePairs.find(SOURCE_PROFILE_KEY); |
212 | if (sourceProfileIter != m_profileKeyValuePairs.end()) |
213 | { |
214 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found source profile " << sourceProfileIter->second); |
215 | profile.SetSourceProfile(sourceProfileIter->second); |
216 | } |
217 | |
218 | auto credentialProcessIter = m_profileKeyValuePairs.find(CREDENTIAL_PROCESS_COMMAND); |
219 | if (credentialProcessIter != m_profileKeyValuePairs.end()) |
220 | { |
221 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found credential process " << credentialProcessIter->second); |
222 | profile.SetCredentialProcess(credentialProcessIter->second); |
223 | } |
224 | profile.SetAllKeyValPairs(m_profileKeyValuePairs); |
225 | |
226 | m_foundProfiles[profile.GetName()] = std::move(profile); |
227 | m_currentWorkingProfile.clear(); |
228 | m_profileKeyValuePairs.clear(); |
229 | } |
230 | |
231 | if(!line.empty() && openPos != std::string::npos && closePos != std::string::npos) |
232 | { |
233 | m_currentWorkingProfile = StringUtils::Trim(line.substr(openPos + 1, closePos - openPos - 1).c_str()); |
234 | StringUtils::Replace(m_currentWorkingProfile, PROFILE_PREFIX, "" ); |
235 | AWS_LOGSTREAM_DEBUG(PARSER_TAG, "found profile " << m_currentWorkingProfile); |
236 | } |
237 | } |
238 | |
239 | enum State |
240 | { |
241 | START = 0, |
242 | PROFILE_FOUND, |
243 | PROFILE_KEY_VALUE_FOUND, |
244 | FAILURE |
245 | }; |
246 | |
247 | Aws::String m_currentWorkingProfile; |
248 | Aws::Map<String, String> m_profileKeyValuePairs; |
249 | State m_parserState; |
250 | Aws::Map<String, Profile> m_foundProfiles; |
251 | }; |
252 | |
253 | static const char* const CONFIG_FILE_LOADER = "Aws::Config::AWSConfigFileProfileConfigLoader" ; |
254 | |
255 | AWSConfigFileProfileConfigLoader::AWSConfigFileProfileConfigLoader(const Aws::String& fileName, bool useProfilePrefix) : |
256 | m_fileName(fileName), m_useProfilePrefix(useProfilePrefix) |
257 | { |
258 | AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Initializing config loader against fileName " |
259 | << fileName << " and using profilePrefix = " << useProfilePrefix); |
260 | } |
261 | |
262 | bool AWSConfigFileProfileConfigLoader::LoadInternal() |
263 | { |
264 | m_profiles.clear(); |
265 | |
266 | Aws::IFStream inputFile(m_fileName.c_str()); |
267 | if(inputFile) |
268 | { |
269 | ConfigFileProfileFSM parser; |
270 | parser.ParseStream(inputFile); |
271 | m_profiles = parser.GetProfiles(); |
272 | return m_profiles.size() > 0; |
273 | } |
274 | |
275 | AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for reading." ); |
276 | |
277 | return false; |
278 | } |
279 | |
280 | bool AWSConfigFileProfileConfigLoader::PersistInternal(const Aws::Map<Aws::String, Profile>& profiles) |
281 | { |
282 | Aws::OFStream outputFile(m_fileName.c_str(), std::ios_base::out | std::ios_base::trunc); |
283 | if(outputFile) |
284 | { |
285 | for(auto& profile : profiles) |
286 | { |
287 | Aws::String prefix = m_useProfilePrefix ? PROFILE_PREFIX : "" ; |
288 | |
289 | AWS_LOGSTREAM_DEBUG(CONFIG_FILE_LOADER, "Writing profile " << profile.first << " to disk." ); |
290 | |
291 | outputFile << LEFT_BRACKET << prefix << profile.second.GetName() << RIGHT_BRACKET << std::endl; |
292 | const Aws::Auth::AWSCredentials& credentials = profile.second.GetCredentials(); |
293 | outputFile << ACCESS_KEY_ID_KEY << EQ << credentials.GetAWSAccessKeyId() << std::endl; |
294 | outputFile << SECRET_KEY_KEY << EQ << credentials.GetAWSSecretKey() << std::endl; |
295 | |
296 | if(!credentials.GetSessionToken().empty()) |
297 | { |
298 | outputFile << SESSION_TOKEN_KEY << EQ << credentials.GetSessionToken() << std::endl; |
299 | } |
300 | |
301 | if(!profile.second.GetRegion().empty()) |
302 | { |
303 | outputFile << REGION_KEY << EQ << profile.second.GetRegion() << std::endl; |
304 | } |
305 | |
306 | if(!profile.second.GetRoleArn().empty()) |
307 | { |
308 | outputFile << ROLE_ARN_KEY << EQ << profile.second.GetRoleArn() << std::endl; |
309 | } |
310 | |
311 | if(!profile.second.GetSourceProfile().empty()) |
312 | { |
313 | outputFile << SOURCE_PROFILE_KEY << EQ << profile.second.GetSourceProfile() << std::endl; |
314 | } |
315 | |
316 | outputFile << std::endl; |
317 | } |
318 | |
319 | AWS_LOGSTREAM_INFO(CONFIG_FILE_LOADER, "Profiles written to config file " << m_fileName); |
320 | |
321 | return true; |
322 | } |
323 | |
324 | AWS_LOGSTREAM_WARN(CONFIG_FILE_LOADER, "Unable to open config file " << m_fileName << " for writing." ); |
325 | |
326 | return false; |
327 | } |
328 | |
329 | static const char* const EC2_INSTANCE_PROFILE_LOG_TAG = "Aws::Config::EC2InstanceProfileConfigLoader" ; |
330 | |
331 | EC2InstanceProfileConfigLoader::EC2InstanceProfileConfigLoader(const std::shared_ptr<Aws::Internal::EC2MetadataClient>& client) |
332 | : m_ec2metadataClient(client == nullptr ? Aws::MakeShared<Aws::Internal::EC2MetadataClient>(EC2_INSTANCE_PROFILE_LOG_TAG) : client) |
333 | { |
334 | } |
335 | |
336 | bool EC2InstanceProfileConfigLoader::LoadInternal() |
337 | { |
338 | auto credentialsStr = m_ec2metadataClient->GetDefaultCredentialsSecurely(); |
339 | if(credentialsStr.empty()) return false; |
340 | |
341 | Json::JsonValue credentialsDoc(credentialsStr); |
342 | if (!credentialsDoc.WasParseSuccessful()) |
343 | { |
344 | AWS_LOGSTREAM_ERROR(EC2_INSTANCE_PROFILE_LOG_TAG, |
345 | "Failed to parse output from EC2MetadataService." ); |
346 | return false; |
347 | } |
348 | const char* accessKeyId = "AccessKeyId" ; |
349 | const char* secretAccessKey = "SecretAccessKey" ; |
350 | Aws::String accessKey, secretKey, token; |
351 | |
352 | auto credentialsView = credentialsDoc.View(); |
353 | accessKey = credentialsView.GetString(accessKeyId); |
354 | AWS_LOGSTREAM_INFO(EC2_INSTANCE_PROFILE_LOG_TAG, |
355 | "Successfully pulled credentials from metadata service with access key " << accessKey); |
356 | |
357 | secretKey = credentialsView.GetString(secretAccessKey); |
358 | token = credentialsView.GetString("Token" ); |
359 | |
360 | auto region = m_ec2metadataClient->GetCurrentRegion(); |
361 | |
362 | Profile profile; |
363 | profile.SetCredentials(AWSCredentials(accessKey, secretKey, token)); |
364 | profile.SetRegion(region); |
365 | profile.SetName(INSTANCE_PROFILE_KEY); |
366 | |
367 | m_profiles[INSTANCE_PROFILE_KEY] = profile; |
368 | |
369 | return true; |
370 | } |
371 | |
372 | ConfigAndCredentialsCacheManager::ConfigAndCredentialsCacheManager() : |
373 | m_credentialsFileLoader(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()), |
374 | m_configFileLoader(Aws::Auth::GetConfigProfileFilename(), true/*use profile prefix*/) |
375 | { |
376 | ReloadCredentialsFile(); |
377 | ReloadConfigFile(); |
378 | } |
379 | |
380 | void ConfigAndCredentialsCacheManager::ReloadConfigFile() |
381 | { |
382 | Aws::Utils::Threading::WriterLockGuard guard(m_configLock); |
383 | m_configFileLoader.SetFileName(Aws::Auth::GetConfigProfileFilename()); |
384 | m_configFileLoader.Load(); |
385 | } |
386 | |
387 | void ConfigAndCredentialsCacheManager::ReloadCredentialsFile() |
388 | { |
389 | Aws::Utils::Threading::WriterLockGuard guard(m_credentialsLock); |
390 | m_credentialsFileLoader.SetFileName(Aws::Auth::ProfileConfigFileAWSCredentialsProvider::GetCredentialsProfileFilename()); |
391 | m_credentialsFileLoader.Load(); |
392 | } |
393 | |
394 | bool ConfigAndCredentialsCacheManager::HasConfigProfile(const Aws::String& profileName) const |
395 | { |
396 | Aws::Utils::Threading::ReaderLockGuard guard(m_configLock); |
397 | return (m_configFileLoader.GetProfiles().count(profileName) == 1); |
398 | } |
399 | |
400 | Aws::Config::Profile ConfigAndCredentialsCacheManager::GetConfigProfile(const Aws::String& profileName) const |
401 | { |
402 | Aws::Utils::Threading::ReaderLockGuard guard(m_configLock); |
403 | const auto& profiles = m_configFileLoader.GetProfiles(); |
404 | const auto &iter = profiles.find(profileName); |
405 | if (iter == profiles.end()) |
406 | { |
407 | return {}; |
408 | } |
409 | return iter->second; |
410 | } |
411 | |
412 | Aws::Map<Aws::String, Aws::Config::Profile> ConfigAndCredentialsCacheManager::GetConfigProfiles() const |
413 | { |
414 | Aws::Utils::Threading::ReaderLockGuard guard(m_configLock); |
415 | return m_configFileLoader.GetProfiles(); |
416 | } |
417 | |
418 | Aws::String ConfigAndCredentialsCacheManager::GetConfig(const Aws::String& profileName, const Aws::String& key) const |
419 | { |
420 | Aws::Utils::Threading::ReaderLockGuard guard(m_configLock); |
421 | const auto& profiles = m_configFileLoader.GetProfiles(); |
422 | const auto &iter = profiles.find(profileName); |
423 | if (iter == profiles.end()) |
424 | { |
425 | return {}; |
426 | } |
427 | return iter->second.GetValue(key); |
428 | } |
429 | |
430 | bool ConfigAndCredentialsCacheManager::HasCredentialsProfile(const Aws::String& profileName) const |
431 | { |
432 | Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock); |
433 | return (m_credentialsFileLoader.GetProfiles().count(profileName) == 1); |
434 | } |
435 | |
436 | Aws::Config::Profile ConfigAndCredentialsCacheManager::GetCredentialsProfile(const Aws::String& profileName) const |
437 | { |
438 | Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock); |
439 | const auto &profiles = m_credentialsFileLoader.GetProfiles(); |
440 | const auto &iter = profiles.find(profileName); |
441 | if (iter == profiles.end()) |
442 | { |
443 | return {}; |
444 | } |
445 | return iter->second; |
446 | } |
447 | |
448 | Aws::Auth::AWSCredentials ConfigAndCredentialsCacheManager::GetCredentials(const Aws::String& profileName) const |
449 | { |
450 | Aws::Utils::Threading::ReaderLockGuard guard(m_credentialsLock); |
451 | const auto& profiles = m_credentialsFileLoader.GetProfiles(); |
452 | const auto &iter = profiles.find(profileName); |
453 | if (iter == profiles.end()) |
454 | { |
455 | return {}; |
456 | } |
457 | return iter->second.GetCredentials(); |
458 | } |
459 | |
460 | void InitConfigAndCredentialsCacheManager() |
461 | { |
462 | if (s_configManager) |
463 | { |
464 | return; |
465 | } |
466 | s_configManager = Aws::MakeUnique<ConfigAndCredentialsCacheManager>(CONFIG_CREDENTIALS_CACHE_MANAGER_TAG); |
467 | } |
468 | |
469 | void CleanupConfigAndCredentialsCacheManager() |
470 | { |
471 | if (!s_configManager) |
472 | { |
473 | return; |
474 | } |
475 | s_configManager = nullptr; |
476 | } |
477 | |
478 | void ReloadCachedConfigFile() |
479 | { |
480 | assert(s_configManager); |
481 | s_configManager->ReloadConfigFile(); |
482 | } |
483 | |
484 | void ReloadCachedCredentialsFile() |
485 | { |
486 | assert(s_configManager); |
487 | s_configManager->ReloadCredentialsFile(); |
488 | } |
489 | |
490 | bool HasCachedConfigProfile(const Aws::String& profileName) |
491 | { |
492 | assert(s_configManager); |
493 | return s_configManager->HasConfigProfile(profileName); |
494 | } |
495 | |
496 | Aws::Config::Profile GetCachedConfigProfile(const Aws::String& profileName) |
497 | { |
498 | assert(s_configManager); |
499 | return s_configManager->GetConfigProfile(profileName); |
500 | } |
501 | |
502 | Aws::Map<Aws::String, Aws::Config::Profile> GetCachedConfigProfiles() |
503 | { |
504 | assert(s_configManager); |
505 | return s_configManager->GetConfigProfiles(); |
506 | } |
507 | |
508 | Aws::String GetCachedConfigValue(const Aws::String &profileName, const Aws::String &key) |
509 | { |
510 | assert(s_configManager); |
511 | return s_configManager->GetConfig(profileName, key); |
512 | } |
513 | |
514 | Aws::String GetCachedConfigValue(const Aws::String &key) |
515 | { |
516 | assert(s_configManager); |
517 | return s_configManager->GetConfig(Aws::Auth::GetConfigProfileName(), key); |
518 | } |
519 | |
520 | bool HasCachedCredentialsProfile(const Aws::String& profileName) |
521 | { |
522 | assert(s_configManager); |
523 | return s_configManager->HasCredentialsProfile(profileName); |
524 | } |
525 | |
526 | Aws::Config::Profile GetCachedCredentialsProfile(const Aws::String &profileName) |
527 | { |
528 | assert(s_configManager); |
529 | return s_configManager->GetCredentialsProfile(profileName); |
530 | } |
531 | |
532 | Aws::Auth::AWSCredentials GetCachedCredentials(const Aws::String &profileName) |
533 | { |
534 | assert(s_configManager); |
535 | return s_configManager->GetCredentials(profileName); |
536 | } |
537 | } // Config namespace |
538 | } // Aws namespace |
539 | |