diff --git a/Sources/Core/AWSClientRuntime/Auth/CredentialsProviders/SSOCredentialsProvider.swift b/Sources/Core/AWSClientRuntime/Auth/CredentialsProviders/SSOCredentialsProvider.swift new file mode 100644 index 00000000000..9cb30f10cc5 --- /dev/null +++ b/Sources/Core/AWSClientRuntime/Auth/CredentialsProviders/SSOCredentialsProvider.swift @@ -0,0 +1,36 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import AwsCommonRuntimeKit +import ClientRuntime + +/// A credentials provider that sources credentials using GetRoleCredentialsRequest to the AWS Single Sign-On Service to maintain short-lived sessions. +/// [Details link](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html) +public struct SSOCredentialsProvider: CredentialsSourcedByCRT { + let crtCredentialsProvider: CRTCredentialsProvider + + /// - Parameters: + /// - profileName: The profile name to use. If not provided it will be resolved internally via the `AWS_PROFILE` environment variable or defaulted to `default` if not configured. + /// - configFilePath: The path to the configuration file to use. If not provided it will be resolved internally via the `AWS_CONFIG_FILE` environment variable or defaulted to `~/.aws/config` if not configured. + /// - credentialsFilePath: The path to the shared credentials file to use. If not provided it will be resolved internally via the `AWS_SHARED_CREDENTIALS_FILE` environment variable or defaulted `~/.aws/credentials` if not configured. + public init( + profileName: String? = nil, + configFilePath: String? = nil, + credentialsFilePath: String? = nil + ) throws { + let fileBasedConfig = try CRTFileBasedConfiguration( + configFilePath: configFilePath, + credentialsFilePath: credentialsFilePath + ) + self.crtCredentialsProvider = try CRTCredentialsProvider(source: .sso( + bootstrap: SDKDefaultIO.shared.clientBootstrap, + tlsContext: SDKDefaultIO.shared.tlsContext, + fileBasedConfiguration: fileBasedConfig, + profileFileNameOverride: profileName + )) + } +} diff --git a/Tests/Core/AWSClientRuntimeTests/Auth/CredentialsProvidersTests/SSOCredentialsProviderTests.swift b/Tests/Core/AWSClientRuntimeTests/Auth/CredentialsProvidersTests/SSOCredentialsProviderTests.swift new file mode 100644 index 00000000000..2ea22a7ac13 --- /dev/null +++ b/Tests/Core/AWSClientRuntimeTests/Auth/CredentialsProvidersTests/SSOCredentialsProviderTests.swift @@ -0,0 +1,47 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import ClientRuntime +import Foundation +import XCTest + +@_spi(FileBasedConfig) @testable import AWSClientRuntime + +class SSOCredentialsProviderTests: XCTestCase { + let configPath = Bundle.module.path(forResource: "sso_tests", ofType: nil)! + let credentialsPath = Bundle.module.path(forResource: "credentials", ofType: nil)! + + func testCreateCredentialsProviderSSONonexistentProfile() async throws { + XCTAssertThrowsError(try SSOCredentialsProvider( + profileName: "PROFILE_NOT_IN_SSO_TESTS_CONFIG_FILE", + configFilePath: configPath, + credentialsFilePath: credentialsPath + ) + ) + } + + func testCreateCredentialsProviderSSOLegacyProfile() async throws { + _ = try SSOCredentialsProvider( + profileName: "user", + configFilePath: configPath, + credentialsFilePath: credentialsPath + ) + // SUCCESS: creation didn't throw error + } + + func testCreateCredentialsProviderSSOTokenProviderProfile() async throws { + _ = try SSOCredentialsProvider( + profileName: "dev", + configFilePath: configPath, + credentialsFilePath: credentialsPath + ) + // SUCCESS: creation didn't throw error + } + + // TODO: add integration tests that automatically test that SSO crednetials provider correctly exchanges SSO token for temporary AWS credentails. + // Manual integration testing confirmed SSOCredentialsProvider works as of 081723. +} diff --git a/Tests/Core/AWSClientRuntimeTests/Resources/sso_tests b/Tests/Core/AWSClientRuntimeTests/Resources/sso_tests new file mode 100644 index 00000000000..b2b43c6bd43 --- /dev/null +++ b/Tests/Core/AWSClientRuntimeTests/Resources/sso_tests @@ -0,0 +1,17 @@ +[profile dev] +sso_session = my-sso +sso_account_id = 111122223333 +sso_role_name = SampleRole + +[sso-session my-sso] +sso_region = us-east-1 +sso_start_url = https://my-sso-portal.awsapps.com/start +sso_registration_scopes = sso:account:access + +[profile user] +aws_access_key_id = example_access_key_id +aws_secret_access_key = example_secret_access_key +sso_start_url = https://d-test.awsapps.com/start +sso_region = us-west-2 +sso_account_id = 12345 +sso_role_name = roleName