From 6955280bf04297a351548f4989a585af1a7621cc Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Tue, 12 Sep 2023 16:37:13 -0700 Subject: [PATCH 01/10] wip --- .../Resources/sso-config | 8 ++ .../Resources/sso-credentials | 2 + .../SSOCredentialsProviderTests.swift | 96 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config create mode 100644 IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials create mode 100644 IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config new file mode 100644 index 00000000000..285eb3105c2 --- /dev/null +++ b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config @@ -0,0 +1,8 @@ +[default] +sso_session = my-sso +sso_account_id = 111122223333 +sso_role_name = + +[sso-session my-sso] +sso_region = us-east-1 +sso_start_url = https://my-sso-portal.awsapps.com/start diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials new file mode 100644 index 00000000000..e6ed8338510 --- /dev/null +++ b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials @@ -0,0 +1,2 @@ + +# intentionally empty to force credentials to be fetched from SSO diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift new file mode 100644 index 00000000000..e5c2e083496 --- /dev/null +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -0,0 +1,96 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +import Foundation +import XCTest +import AWSS3 +import AWSClientRuntime +import AWSSSO + +/* Prerequisites to run the SSO credentials provider integration test(s): + * + * 1. Enable AWS Organization for the AWS account used for integration test if it hasn't been already. + * 2. Create a permission set (for S3::listBuckets) in IAM Identity Center. + * 3. Create a user in IAM Identity Center, and retrieve username, password, and SSO start URL (these are needed for step 4, aws sso configure). + * 4. Give the created user access to your AWS account with the created permission set. + * 5. Configure SSO config. + * 6. Create SSO token using AWS CLI (aws sso login --profile ). + * 7. Run the test. + * + * Steps 2, 3, 4 will be taken care of by the test's setUp(), using AWS credentials fetched by default credentials provider chain. + * + * In effect, you'll need to: + * - Do step 1 manually + * - Run the test, and have setUp() handle steps 2, 3, 4 then fail (due to no valid SSO token) + * - Do step 5 & 6 manually + * - Run the test + * + * Only step 6 has to be re-done more than once, as SSO token may have expired before you run the test again. + */ +class SSOCredentialsProviderTests : XCTestCase { + var client: S3Client! + + override func setUp() async throws { + createPermissionSet() + let userData = createUser() + giveAccountAccessToUserUsingPermissionSet() + + setUpClient() + } + + // This test calls listBuckets() and forces S3Client to use SSOCredentialsProvider + func test_listBuckets() async throws { + _ = try await client.listBuckets(input: ListBucketsInput()) + } + + override func tearDown() async throws { + // No action required. + } + + /* HELPER METHODS */ + private func createPermissionSet() async throws { + + } + + private func createUser() async throws -> SSOUserData { + + } + + private func giveAccountAccessToUserUsingPermissionSet() { + + } + + private func configureSSOConfig(userData: SSOUserData) { + + } + + private func ssoLogin() { + + } + + private func setUpClient() async throws { + // Setup SSOCredentialsProvider + let SSOCredentialsProvider = try SSOCredentialsProvider( + configFilePath: Bundle.module.path(forResource: "sso-config", ofType: nil)!, + credentialsFilePath: Bundle.module.path(forResource: "sso-credentials", ofType: nil)! + ) + + // Setup S3ClientConfiguration to use SSOCredentialsProvider + let testConfig = try await S3Client.S3ClientConfiguration() + testConfig.credentialsProvider = SSOCredentialsProvider + + // Initialize our S3 client with the specified configuration + client = S3Client(config: testConfig) + } + + /* HELPER DATA STRUCT */ + private struct SSOUserData { + val username: String + val password: String + val startUrl: String + } +} From a51690b9e709c5e1fbd224ab50e0ab94906277a5 Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Thu, 14 Sep 2023 17:05:27 -0700 Subject: [PATCH 02/10] wip --- .../SSOCredentialsProviderTests.swift | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index e5c2e083496..e1a28ff101c 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -9,11 +9,11 @@ import Foundation import XCTest import AWSS3 import AWSClientRuntime -import AWSSSO +import AWSSSOAdmin /* Prerequisites to run the SSO credentials provider integration test(s): * - * 1. Enable AWS Organization for the AWS account used for integration test if it hasn't been already. + * 1. Enable IAM Identity Center AWS Organization for the AWS account used for integration test if it hasn't been already. * 2. Create a permission set (for S3::listBuckets) in IAM Identity Center. * 3. Create a user in IAM Identity Center, and retrieve username, password, and SSO start URL (these are needed for step 4, aws sso configure). * 4. Give the created user access to your AWS account with the created permission set. @@ -21,25 +21,34 @@ import AWSSSO * 6. Create SSO token using AWS CLI (aws sso login --profile ). * 7. Run the test. * - * Steps 2, 3, 4 will be taken care of by the test's setUp(), using AWS credentials fetched by default credentials provider chain. - * - * In effect, you'll need to: - * - Do step 1 manually - * - Run the test, and have setUp() handle steps 2, 3, 4 then fail (due to no valid SSO token) - * - Do step 5 & 6 manually - * - Run the test - * - * Only step 6 has to be re-done more than once, as SSO token may have expired before you run the test again. + * Only step 1 has to be done manually in the AWS account console you're using to run this integration test. */ class SSOCredentialsProviderTests : XCTestCase { var client: S3Client! + var ssoClient: SSOAdminClient! + + private var username: String = "" + private var password: String = "" + private var startUrl: String = "" + + private var iamIdentityCenterInstanceArn: String = "" + private var permissionSetArn: String = "" + private var userArn: String = "" + override func setUp() async throws { - createPermissionSet() - let userData = createUser() - giveAccountAccessToUserUsingPermissionSet() + // Use default credentials provider chain + ssoClient = try await SSOClient() + try await createPermissionSet() + try await createUser() + try await giveAccountAccessToUserUsingPermissionSet() + + // Use AWS CLI for these + try await configureSSOConfig() + try await ssoLoginAndCreateToken() - setUpClient() + // This client uses SSO credentials provider to call S3::listBuckets operation + try await setUpClient() } // This test calls listBuckets() and forces S3Client to use SSOCredentialsProvider @@ -53,22 +62,26 @@ class SSOCredentialsProviderTests : XCTestCase { /* HELPER METHODS */ private func createPermissionSet() async throws { + if let response = try await ssoClient.listInstances(input: ListInstancesInput()) as! ListInstancesOutputResponse, response.instances != nil { + iamIdentityCenterInstanceArn = response.instances + + } } - private func createUser() async throws -> SSOUserData { + private func createUser() async throws { } - private func giveAccountAccessToUserUsingPermissionSet() { + private func giveAccountAccessToUserUsingPermissionSet() async throws { } - private func configureSSOConfig(userData: SSOUserData) { + private func configureSSOConfig() async throws { } - private func ssoLogin() { + private func ssoLoginAndCreateToken() async throws { } @@ -86,11 +99,4 @@ class SSOCredentialsProviderTests : XCTestCase { // Initialize our S3 client with the specified configuration client = S3Client(config: testConfig) } - - /* HELPER DATA STRUCT */ - private struct SSOUserData { - val username: String - val password: String - val startUrl: String - } } From a5d395ecd0e67abc933df54aa73abbd95bfe3d57 Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Sun, 17 Sep 2023 21:45:27 -0700 Subject: [PATCH 03/10] Add permission set generation. --- .../Resources/sso-config | 8 -- .../Resources/sso-credentials | 2 - .../SSOCredentialsProviderTests.swift | 89 ++++++++++--------- 3 files changed, 47 insertions(+), 52 deletions(-) delete mode 100644 IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config delete mode 100644 IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config deleted file mode 100644 index 285eb3105c2..00000000000 --- a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-config +++ /dev/null @@ -1,8 +0,0 @@ -[default] -sso_session = my-sso -sso_account_id = 111122223333 -sso_role_name = - -[sso-session my-sso] -sso_region = us-east-1 -sso_start_url = https://my-sso-portal.awsapps.com/start diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials b/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials deleted file mode 100644 index e6ed8338510..00000000000 --- a/IntegrationTests/Services/AWSS3IntegrationTests/Resources/sso-credentials +++ /dev/null @@ -1,2 +0,0 @@ - -# intentionally empty to force credentials to be fetched from SSO diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index e1a28ff101c..2641789b760 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -13,45 +13,43 @@ import AWSSSOAdmin /* Prerequisites to run the SSO credentials provider integration test(s): * - * 1. Enable IAM Identity Center AWS Organization for the AWS account used for integration test if it hasn't been already. - * 2. Create a permission set (for S3::listBuckets) in IAM Identity Center. - * 3. Create a user in IAM Identity Center, and retrieve username, password, and SSO start URL (these are needed for step 4, aws sso configure). + * [Manual] + * 1. Enable IAM Identity Center AWS Organization for the AWS account used to run integration test if it hasn't been already. + * + * [Automatic] + * 2. Create a read-only permission set in IAM Identity Center called "SSOCredProvIntegTestPermSet". + + * [Manual] + * 3. Create a user in IAM Identity Center. * 4. Give the created user access to your AWS account with the created permission set. - * 5. Configure SSO config. + * 5. Retrieve username, password, and SSO start URL of the IAM Identity Store user. Configure SSO config using these values (aws sso configure). * 6. Create SSO token using AWS CLI (aws sso login --profile ). * 7. Run the test. * - * Only step 1 has to be done manually in the AWS account console you're using to run this integration test. + * Note: Enabling AWS organization and creating IAM identity store have no exposed API as of 9/17/2023 for programmatic activation / creation. + * + * Step 1, 3, 4, 5 have to be done only once per account. */ class SSOCredentialsProviderTests : XCTestCase { var client: S3Client! var ssoClient: SSOAdminClient! - private var username: String = "" - private var password: String = "" - private var startUrl: String = "" - private var iamIdentityCenterInstanceArn: String = "" + private let permissionSetName = "SSOCredProvIntegTestPermSet" private var permissionSetArn: String = "" - private var userArn: String = "" + private let awsReadOnlyPolicy = "arn:aws:iam::aws:policy/ReadOnlyAccess" override func setUp() async throws { - // Use default credentials provider chain + // Use default credentials provider chain for setup ssoClient = try await SSOClient() - try await createPermissionSet() - try await createUser() - try await giveAccountAccessToUserUsingPermissionSet() + try await createPermissionSetIfNeeded() - // Use AWS CLI for these - try await configureSSOConfig() - try await ssoLoginAndCreateToken() - - // This client uses SSO credentials provider to call S3::listBuckets operation + // Create a S3 client that uses SSO credentials provider try await setUpClient() } - // This test calls listBuckets() and forces S3Client to use SSOCredentialsProvider + // The test calls listBuckets() and forces S3Client to use SSOCredentialsProvider func test_listBuckets() async throws { _ = try await client.listBuckets(input: ListBucketsInput()) } @@ -61,36 +59,43 @@ class SSOCredentialsProviderTests : XCTestCase { } /* HELPER METHODS */ - private func createPermissionSet() async throws { - if let response = try await ssoClient.listInstances(input: ListInstancesInput()) as! ListInstancesOutputResponse, response.instances != nil { - iamIdentityCenterInstanceArn = response.instances - + private func createPermissionSetIfNeeded() async throws { + // Get IAM identity center instanceArn + if let response = try await ssoClient.listInstances(input: ListInstancesInput()) as? ListInstancesOutputResponse { + iamIdentityCenterInstanceArn = response.instances![0].instanceArn } - } - - private func createUser() async throws { - - } - - private func giveAccountAccessToUserUsingPermissionSet() async throws { - - } - - private func configureSSOConfig() async throws { + // Check if permission set for this integ test is already present. Save its arn and return if it already exists. + let output = try await ssoClient.listPermissionSets(input: ListPermissionSetsInput(instanceArn: iamIdentityCenterInstanceArn)) as? ListPermissionSetsOutputResponse + guard let output = output, sets = output.permissionSets else { + throw Error("Failed to retrieve list of pre-existing permission sets from IAM Identity Center.") + } + if sets.contains(permissionSetName) { + // Set permission set instanceArn + let idx = sets.firstIndex(where: $0 == permissionSetName) + permissionSetArn = sets[idx] + return + } - } - - private func ssoLoginAndCreateToken() async throws { + // Otherwise, create permission set and save its ARN + if let response = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( + description: "Permission set for testing SSO credentials provider.", + instanceArn: iamIdentityCenterInstanceArn, + name: permissionSetName + )) as? CreatePermissionSetOutputResponse { + permissionSetArn = response.permissionSet!.permissionSetArn! + } + // Attach ReadOnly AWS-managed policy to the created permission set + let _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( + instanceArn: iamIdentityCenterInstanceArn, + managedPolicyArn: awsReadOnlyPolicy, + permissionSetArn: permissionSetArn)) } private func setUpClient() async throws { // Setup SSOCredentialsProvider - let SSOCredentialsProvider = try SSOCredentialsProvider( - configFilePath: Bundle.module.path(forResource: "sso-config", ofType: nil)!, - credentialsFilePath: Bundle.module.path(forResource: "sso-credentials", ofType: nil)! - ) + let SSOCredentialsProvider = try SSOCredentialsProvider() // Setup S3ClientConfiguration to use SSOCredentialsProvider let testConfig = try await S3Client.S3ClientConfiguration() From 004c5e1b07eb959f589bbc1a3060941529bff02d Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Mon, 18 Sep 2023 14:26:56 -0700 Subject: [PATCH 04/10] Add integration test dependency. --- .../Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift index 7dd2fd2a910..d91be6473b3 100644 --- a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift +++ b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift @@ -115,6 +115,8 @@ func addIntegrationTestTarget(_ name: String) { "README.md", "Resources/ECSIntegTestApp/" ] + case "AWSS3": + additionalDependencies = ["AWSSSOAdmin"] default: break } From c3a1004aeca8d0734862fa3086debda5fad54a8f Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Mon, 18 Sep 2023 20:06:04 -0700 Subject: [PATCH 05/10] Make permission set creation work. --- .../SSOCredentialsProviderTests.swift | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index 2641789b760..a6db3f9564e 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -18,7 +18,7 @@ import AWSSSOAdmin * * [Automatic] * 2. Create a read-only permission set in IAM Identity Center called "SSOCredProvIntegTestPermSet". - + * * [Manual] * 3. Create a user in IAM Identity Center. * 4. Give the created user access to your AWS account with the created permission set. @@ -33,6 +33,8 @@ import AWSSSOAdmin class SSOCredentialsProviderTests : XCTestCase { var client: S3Client! var ssoClient: SSOAdminClient! + // Change this region string to the region where AWS SSO instance is in. + let region = "us-west-2" private var iamIdentityCenterInstanceArn: String = "" private let permissionSetName = "SSOCredProvIntegTestPermSet" @@ -42,7 +44,7 @@ class SSOCredentialsProviderTests : XCTestCase { override func setUp() async throws { // Use default credentials provider chain for setup - ssoClient = try await SSOClient() + ssoClient = try SSOAdminClient(region: "us-west-2") try await createPermissionSetIfNeeded() // Create a S3 client that uses SSO credentials provider @@ -61,36 +63,31 @@ class SSOCredentialsProviderTests : XCTestCase { /* HELPER METHODS */ private func createPermissionSetIfNeeded() async throws { // Get IAM identity center instanceArn - if let response = try await ssoClient.listInstances(input: ListInstancesInput()) as? ListInstancesOutputResponse { - iamIdentityCenterInstanceArn = response.instances![0].instanceArn - } + let listInstancesOutput = try await ssoClient.listInstances(input: ListInstancesInput()) + iamIdentityCenterInstanceArn = listInstancesOutput.instances![0].instanceArn! - // Check if permission set for this integ test is already present. Save its arn and return if it already exists. - let output = try await ssoClient.listPermissionSets(input: ListPermissionSetsInput(instanceArn: iamIdentityCenterInstanceArn)) as? ListPermissionSetsOutputResponse - guard let output = output, sets = output.permissionSets else { - throw Error("Failed to retrieve list of pre-existing permission sets from IAM Identity Center.") - } - if sets.contains(permissionSetName) { - // Set permission set instanceArn - let idx = sets.firstIndex(where: $0 == permissionSetName) - permissionSetArn = sets[idx] - return - } - - // Otherwise, create permission set and save its ARN - if let response = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( + do { + // Create permission set and save its ARN + let createPermissionSetOutput = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( description: "Permission set for testing SSO credentials provider.", instanceArn: iamIdentityCenterInstanceArn, name: permissionSetName - )) as? CreatePermissionSetOutputResponse { - permissionSetArn = response.permissionSet!.permissionSetArn! + )) + permissionSetArn = createPermissionSetOutput.permissionSet!.permissionSetArn! + + + // Attach ReadOnly AWS-managed policy to the created permission set + let _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( + instanceArn: iamIdentityCenterInstanceArn, + managedPolicyArn: awsReadOnlyPolicy, + permissionSetArn: permissionSetArn)) + } catch let error as AWSSSOAdmin.ConflictException { + if error.message == "PermissionSet with name \(permissionSetName) already exists." { + return + } else { + throw error + } } - - // Attach ReadOnly AWS-managed policy to the created permission set - let _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( - instanceArn: iamIdentityCenterInstanceArn, - managedPolicyArn: awsReadOnlyPolicy, - permissionSetArn: permissionSetArn)) } private func setUpClient() async throws { @@ -100,6 +97,7 @@ class SSOCredentialsProviderTests : XCTestCase { // Setup S3ClientConfiguration to use SSOCredentialsProvider let testConfig = try await S3Client.S3ClientConfiguration() testConfig.credentialsProvider = SSOCredentialsProvider + testConfig.region = region // Initialize our S3 client with the specified configuration client = S3Client(config: testConfig) From 1866c849dceb86820924e1026a5495bd69646f7b Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Wed, 20 Sep 2023 13:49:34 -0700 Subject: [PATCH 06/10] Resolve PR comments from Josh. --- .../SSOCredentialsProviderTests.swift | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index a6db3f9564e..7935a90c04b 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -43,6 +43,7 @@ class SSOCredentialsProviderTests : XCTestCase { override func setUp() async throws { + try await super.setUp() // Use default credentials provider chain for setup ssoClient = try SSOAdminClient(region: "us-west-2") try await createPermissionSetIfNeeded() @@ -56,10 +57,6 @@ class SSOCredentialsProviderTests : XCTestCase { _ = try await client.listBuckets(input: ListBucketsInput()) } - override func tearDown() async throws { - // No action required. - } - /* HELPER METHODS */ private func createPermissionSetIfNeeded() async throws { // Get IAM identity center instanceArn @@ -82,7 +79,7 @@ class SSOCredentialsProviderTests : XCTestCase { managedPolicyArn: awsReadOnlyPolicy, permissionSetArn: permissionSetArn)) } catch let error as AWSSSOAdmin.ConflictException { - if error.message == "PermissionSet with name \(permissionSetName) already exists." { + if let message = error.message, message.contains("\(permissionSetName) already exists") { return } else { throw error From 18d4ebb4f84a2bfea4ea3a8b58d20042b6bdda45 Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Wed, 20 Sep 2023 14:19:39 -0700 Subject: [PATCH 07/10] Resolve PR comments from David. --- .../SSOCredentialsProviderTests.swift | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index 7935a90c04b..4af75f4d306 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -9,6 +9,7 @@ import Foundation import XCTest import AWSS3 import AWSClientRuntime +import ClientRuntime import AWSSSOAdmin /* Prerequisites to run the SSO credentials provider integration test(s): @@ -61,24 +62,17 @@ class SSOCredentialsProviderTests : XCTestCase { private func createPermissionSetIfNeeded() async throws { // Get IAM identity center instanceArn let listInstancesOutput = try await ssoClient.listInstances(input: ListInstancesInput()) - iamIdentityCenterInstanceArn = listInstancesOutput.instances![0].instanceArn! + guard let iamCenterInstances = listInstancesOutput.instances, let iamCenterArn = iamCenterInstances[0].instanceArn else { + throw ClientError.dataNotFound("No IAM Identity Center instance found for the account." + + "Ensure that AWS organization is enabled for the account you're using to run the integration test.") + } + iamIdentityCenterInstanceArn = iamCenterArn do { - // Create permission set and save its ARN - let createPermissionSetOutput = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( - description: "Permission set for testing SSO credentials provider.", - instanceArn: iamIdentityCenterInstanceArn, - name: permissionSetName - )) - permissionSetArn = createPermissionSetOutput.permissionSet!.permissionSetArn! - - - // Attach ReadOnly AWS-managed policy to the created permission set - let _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( - instanceArn: iamIdentityCenterInstanceArn, - managedPolicyArn: awsReadOnlyPolicy, - permissionSetArn: permissionSetArn)) + // Create permission set and attach AWS managed read-only policy + try await createPermissionSet() } catch let error as AWSSSOAdmin.ConflictException { + // Catch error if permission set has already been created from previous run of this integ test if let message = error.message, message.contains("\(permissionSetName) already exists") { return } else { @@ -87,6 +81,26 @@ class SSOCredentialsProviderTests : XCTestCase { } } + private func createPermissionSet() async throws { + // Create permission set and save its ARN + let createPermissionSetOutput = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( + description: "Permission set for testing SSO credentials provider.", + instanceArn: iamIdentityCenterInstanceArn, + name: permissionSetName + )) + + guard let permSet = createPermissionSetOutput.permissionSet, let permSetArn = permSet.permissionSetArn else { + throw ClientError.dataNotFound("Permission set arn could not be retrieved after creation.") + } + permissionSetArn = permSetArn + + // Attach ReadOnly AWS-managed policy to the created permission set + _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( + instanceArn: iamIdentityCenterInstanceArn, + managedPolicyArn: awsReadOnlyPolicy, + permissionSetArn: permissionSetArn)) + } + private func setUpClient() async throws { // Setup SSOCredentialsProvider let SSOCredentialsProvider = try SSOCredentialsProvider() From ab802086de06ddabd6876714455bdca311840a4f Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Wed, 20 Sep 2023 15:19:35 -0700 Subject: [PATCH 08/10] Refactor to smaller funcitons. --- .../SSOCredentialsProviderTests.swift | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index 4af75f4d306..be5f952983a 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -61,24 +61,27 @@ class SSOCredentialsProviderTests : XCTestCase { /* HELPER METHODS */ private func createPermissionSetIfNeeded() async throws { // Get IAM identity center instanceArn - let listInstancesOutput = try await ssoClient.listInstances(input: ListInstancesInput()) - guard let iamCenterInstances = listInstancesOutput.instances, let iamCenterArn = iamCenterInstances[0].instanceArn else { - throw ClientError.dataNotFound("No IAM Identity Center instance found for the account." - + "Ensure that AWS organization is enabled for the account you're using to run the integration test.") - } - iamIdentityCenterInstanceArn = iamCenterArn + try await getIamIdentityCenterArn() do { - // Create permission set and attach AWS managed read-only policy + // Create permission set with read-only policy try await createPermissionSet() } catch let error as AWSSSOAdmin.ConflictException { // Catch error if permission set has already been created from previous run of this integ test if let message = error.message, message.contains("\(permissionSetName) already exists") { return - } else { - throw error } + throw error + } + } + + private func getIamIdentityCenterArn() async throws { + // Get IAM identity center instanceArn + let listInstancesOutput = try await ssoClient.listInstances(input: ListInstancesInput()) + guard let iamCenterInstances = listInstancesOutput.instances, let iamCenterArn = iamCenterInstances[0].instanceArn else { + throw ClientError.dataNotFound("No IAM Identity Center instance found. Check AWS organization is enabled for the account.") } + iamIdentityCenterInstanceArn = iamCenterArn } private func createPermissionSet() async throws { @@ -87,13 +90,18 @@ class SSOCredentialsProviderTests : XCTestCase { description: "Permission set for testing SSO credentials provider.", instanceArn: iamIdentityCenterInstanceArn, name: permissionSetName + )) - guard let permSet = createPermissionSetOutput.permissionSet, let permSetArn = permSet.permissionSetArn else { throw ClientError.dataNotFound("Permission set arn could not be retrieved after creation.") } permissionSetArn = permSetArn + // Attach policy to permissino set just created + try await attachReadOnlyPolicyToPermSet() + } + + private func attachReadOnlyPolicyToPermSet() async throws { // Attach ReadOnly AWS-managed policy to the created permission set _ = try await ssoClient.attachManagedPolicyToPermissionSet(input: AttachManagedPolicyToPermissionSetInput( instanceArn: iamIdentityCenterInstanceArn, From 67178f19b7fbb2f65a618a159b66136fb9c5b8e2 Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Wed, 20 Sep 2023 15:36:55 -0700 Subject: [PATCH 09/10] Resolve separation of concerns. --- .../SSOCredentialsProviderTests.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index be5f952983a..7e0c121900b 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -64,8 +64,10 @@ class SSOCredentialsProviderTests : XCTestCase { try await getIamIdentityCenterArn() do { - // Create permission set with read-only policy + // Create permission set try await createPermissionSet() + // Attach policy to permissino set just created + try await attachReadOnlyPolicyToPermSet() } catch let error as AWSSSOAdmin.ConflictException { // Catch error if permission set has already been created from previous run of this integ test if let message = error.message, message.contains("\(permissionSetName) already exists") { @@ -96,9 +98,6 @@ class SSOCredentialsProviderTests : XCTestCase { throw ClientError.dataNotFound("Permission set arn could not be retrieved after creation.") } permissionSetArn = permSetArn - - // Attach policy to permissino set just created - try await attachReadOnlyPolicyToPermSet() } private func attachReadOnlyPolicyToPermSet() async throws { From c03be5e49ebca1a66e28a4d569368bf33f363c21 Mon Sep 17 00:00:00 2001 From: Sichan Yoo Date: Wed, 20 Sep 2023 15:47:12 -0700 Subject: [PATCH 10/10] Refactor for return value. --- .../SSOCredentialsProviderTests.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift index 7e0c121900b..6d853dc0a1e 100644 --- a/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift +++ b/IntegrationTests/Services/AWSS3IntegrationTests/SSOCredentialsProviderTests.swift @@ -38,10 +38,10 @@ class SSOCredentialsProviderTests : XCTestCase { let region = "us-west-2" private var iamIdentityCenterInstanceArn: String = "" - private let permissionSetName = "SSOCredProvIntegTestPermSet" private var permissionSetArn: String = "" - private let awsReadOnlyPolicy = "arn:aws:iam::aws:policy/ReadOnlyAccess" + private let permissionSetName = "SSOCredProvIntegTestPermSet" + private let awsReadOnlyPolicy = "arn:aws:iam::aws:policy/ReadOnlyAccess" override func setUp() async throws { try await super.setUp() @@ -61,11 +61,11 @@ class SSOCredentialsProviderTests : XCTestCase { /* HELPER METHODS */ private func createPermissionSetIfNeeded() async throws { // Get IAM identity center instanceArn - try await getIamIdentityCenterArn() + iamIdentityCenterInstanceArn = try await getIamIdentityCenterArn() do { // Create permission set - try await createPermissionSet() + permissionSetArn = try await createPermissionSet() // Attach policy to permissino set just created try await attachReadOnlyPolicyToPermSet() } catch let error as AWSSSOAdmin.ConflictException { @@ -77,16 +77,16 @@ class SSOCredentialsProviderTests : XCTestCase { } } - private func getIamIdentityCenterArn() async throws { + private func getIamIdentityCenterArn() async throws -> String { // Get IAM identity center instanceArn let listInstancesOutput = try await ssoClient.listInstances(input: ListInstancesInput()) guard let iamCenterInstances = listInstancesOutput.instances, let iamCenterArn = iamCenterInstances[0].instanceArn else { throw ClientError.dataNotFound("No IAM Identity Center instance found. Check AWS organization is enabled for the account.") } - iamIdentityCenterInstanceArn = iamCenterArn + return iamCenterArn } - private func createPermissionSet() async throws { + private func createPermissionSet() async throws -> String { // Create permission set and save its ARN let createPermissionSetOutput = try await ssoClient.createPermissionSet(input: CreatePermissionSetInput( description: "Permission set for testing SSO credentials provider.", @@ -97,7 +97,7 @@ class SSOCredentialsProviderTests : XCTestCase { guard let permSet = createPermissionSetOutput.permissionSet, let permSetArn = permSet.permissionSetArn else { throw ClientError.dataNotFound("Permission set arn could not be retrieved after creation.") } - permissionSetArn = permSetArn + return permSetArn } private func attachReadOnlyPolicyToPermSet() async throws {