Skip to content

Commit 0783719

Browse files
authored
Swift AssumeRole: Add region command line option (#7035)
Add region command line option
1 parent b1fc966 commit 0783719

File tree

2 files changed

+154
-149
lines changed

2 files changed

+154
-149
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
/// An `Error` type used to return errors from the
5+
/// `assumeRole(identityResolver: roleArn:)` function.
6+
enum AssumeRoleExampleError: Error {
7+
/// An error indicating that the STS `AssumeRole` request failed.
8+
case assumeRoleFailed
9+
/// An error indicating that the returned credentials were missing
10+
/// required information.
11+
case incompleteCredentials
12+
/// An error indicating that no credentials were returned by `AssumeRole`.
13+
case missingCredentials
14+
15+
/// Return a human-readable explanation of the error.
16+
var errorDescription: String? {
17+
switch self {
18+
case .assumeRoleFailed:
19+
return "Unable to assume the specified role."
20+
case .incompleteCredentials:
21+
return "AWS STS returned incomplete credentials."
22+
case .missingCredentials:
23+
return "AWS STS did not return any credentials for the specified role."
24+
}
25+
}
26+
}

swift/example_code/sts/AssumeRole/Sources/entry.swift

+128-149
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ import SmithyIdentity
1616

1717
struct ExampleCommand: ParsableCommand {
1818
@Option(help: "AWS access key ID")
19-
var accessKey: String? = nil
19+
var accessKey: String?
2020
@Option(help: "AWS secret access key")
21-
var secretKey: String? = nil
21+
var secretKey: String?
2222
@Option(help: "Session token")
23-
var sessionToken: String? = nil
23+
var sessionToken: String?
24+
@Option(help: "Amazon S3 Region to use")
25+
var region: String = "us-east-1"
2426
@Argument(help: "ARN of the role to assume")
2527
var roleArn: String
2628

@@ -39,8 +41,7 @@ struct ExampleCommand: ParsableCommand {
3941
"""
4042
)
4143

42-
/// Called by ``main()`` to do the actual running of the AWS
43-
/// example.
44+
/// Called by ``main()`` to run the main example code.
4445
// snippet-start:[swift.sts.AssumeRole.command.runasync]
4546
func runAsync() async throws {
4647
// If credentials are specified, create a credential identity
@@ -99,169 +100,147 @@ struct ExampleCommand: ParsableCommand {
99100
}
100101
}
101102
// snippet-end:[swift.sts.AssumeRole.command.runasync]
102-
}
103-
104-
/// An `Error` type used to return errors from the
105-
/// `assumeRole(identityResolver: roleArn:)` function.
106-
enum AssumeRoleExampleError: Error {
107-
/// An error indicating that the STS `AssumeRole` request failed.
108-
case assumeRoleFailed
109-
/// An error indicating that the returned credentials were missing
110-
/// required information.
111-
case incompleteCredentials
112-
/// An error indicating that no credentials were returned by `AssumeRole`.
113-
case missingCredentials
114-
115-
/// Return a human-readable explanation of the error.
116-
var errorDescription: String? {
117-
switch self {
118-
case .assumeRoleFailed:
119-
return "Unable to assume the specified role."
120-
case .incompleteCredentials:
121-
return "AWS STS returned incomplete credentials."
122-
case .missingCredentials:
123-
return "AWS STS did not return any credentials for the specified role."
124-
}
125-
}
126-
}
127-
128-
// snippet-start:[swift.sts.AssumeRole.assumeRole-function]
129-
/// Assume the specified role. If any kind of credential identity resolver is
130-
/// specified, that identity is adopted before assuming the role.
131-
///
132-
/// - Parameters:
133-
/// - identityResolver: Any kind of `AWSCredentialIdentityResolver`. If
134-
/// provided, this identity is adopted before attempting to assume the
135-
/// specified role.
136-
/// - roleArn: The ARN of the AWS role to assume.
137-
///
138-
/// - Throws: Re-throws STS errors. Also can throw any
139-
/// `AssumeRoleExampleError`.
140-
/// - Returns: An `AWSCredentialIdentity` containing the temporary credentials
141-
/// assigned.
142-
func assumeRole(identityResolver: (any AWSCredentialIdentityResolver)?,
143-
roleArn: String) async throws -> AWSCredentialIdentity {
144-
let stsConfiguration = try await STSClient.STSClientConfiguration(
145-
awsCredentialIdentityResolver: identityResolver
146-
)
147-
let stsClient = STSClient(config: stsConfiguration)
148103

149-
// Assume the role and return the assigned credentials.
150-
151-
// snippet-start: [swift.sts.sts.AssumeRole]
152-
let input = AssumeRoleInput(
153-
roleArn: roleArn,
154-
roleSessionName: "AssumeRole-Example"
155-
)
104+
// snippet-start:[swift.sts.AssumeRole.assumeRole-function]
105+
/// Assume the specified role. If any kind of credential identity resolver is
106+
/// specified, that identity is adopted before assuming the role.
107+
///
108+
/// - Parameters:
109+
/// - identityResolver: Any kind of `AWSCredentialIdentityResolver`. If
110+
/// provided, this identity is adopted before attempting to assume the
111+
/// specified role.
112+
/// - roleArn: The ARN of the AWS role to assume.
113+
///
114+
/// - Throws: Re-throws STS errors. Also can throw any
115+
/// `AssumeRoleExampleError`.
116+
/// - Returns: An `AWSCredentialIdentity` containing the temporary credentials
117+
/// assigned.
118+
func assumeRole(identityResolver: (any AWSCredentialIdentityResolver)?,
119+
roleArn: String) async throws -> AWSCredentialIdentity {
120+
let stsConfiguration = try await STSClient.STSClientConfiguration(
121+
awsCredentialIdentityResolver: identityResolver,
122+
region: region
123+
)
124+
let stsClient = STSClient(config: stsConfiguration)
156125

157-
let output = try await stsClient.assumeRole(input: input)
126+
// Assume the role and return the assigned credentials.
158127

159-
guard let credentials = output.credentials else {
160-
throw AssumeRoleExampleError.missingCredentials
161-
}
128+
// snippet-start: [swift.sts.sts.AssumeRole]
129+
let input = AssumeRoleInput(
130+
roleArn: roleArn,
131+
roleSessionName: "AssumeRole-Example"
132+
)
162133

163-
guard let accessKey = credentials.accessKeyId,
164-
let secretKey = credentials.secretAccessKey,
165-
let sessionToken = credentials.sessionToken else {
166-
throw AssumeRoleExampleError.incompleteCredentials
167-
}
168-
// snippet-end: [swift.sts.sts.AssumeRole]
134+
let output = try await stsClient.assumeRole(input: input)
169135

170-
// Return an `AWSCredentialIdentity` object with the temporary
171-
// credentials.
136+
guard let credentials = output.credentials else {
137+
throw AssumeRoleExampleError.missingCredentials
138+
}
172139

173-
let awsCredentials = AWSCredentialIdentity(
174-
accessKey: accessKey,
175-
secret: secretKey,
176-
sessionToken: sessionToken
177-
)
178-
return awsCredentials
179-
}
180-
// snippet-end:[swift.sts.AssumeRole.assumeRole-function]
140+
guard let accessKey = credentials.accessKeyId,
141+
let secretKey = credentials.secretAccessKey,
142+
let sessionToken = credentials.sessionToken else {
143+
throw AssumeRoleExampleError.incompleteCredentials
144+
}
145+
// snippet-end: [swift.sts.sts.AssumeRole]
181146

182-
/// Return an array containing the names of all available buckets using
183-
/// the specified credential identity resolver to authenticate.
184-
///
185-
/// - Parameter identityResolver: Any type of `AWSCredentialIdentityResolver`,
186-
/// used to authenticate and authorize the user for access to the bucket
187-
/// names.
188-
///
189-
/// - Throws: Re-throws errors from `ListBucketsPaginated`.
190-
///
191-
/// - Returns: An array of strings listing the buckets.
192-
func getBucketNames(identityResolver: (any AWSCredentialIdentityResolver)?)
193-
async throws -> [String] {
194-
do {
195-
// Get an S3Client with which to access Amazon S3.
196-
// snippet-start:[swift.sts.AssumeRole.use-resolver]
197-
let configuration = try await S3Client.S3ClientConfiguration(
198-
awsCredentialIdentityResolver: identityResolver
199-
)
200-
let client = S3Client(config: configuration)
147+
// Return an `AWSCredentialIdentity` object with the temporary
148+
// credentials.
201149

202-
// Use "Paginated" to get all the buckets. This lets the SDK handle
203-
// the 'continuationToken' in "ListBucketsOutput".
204-
let pages = client.listBucketsPaginated(
205-
input: ListBucketsInput( maxBuckets: 10)
150+
let awsCredentials = AWSCredentialIdentity(
151+
accessKey: accessKey,
152+
secret: secretKey,
153+
sessionToken: sessionToken
206154
)
207-
// snippet-end:[swift.sts.AssumeRole.use-resolver]
208-
209-
// Get the bucket names.
210-
var bucketNames: [String] = []
211-
155+
return awsCredentials
156+
}
157+
// snippet-end:[swift.sts.AssumeRole.assumeRole-function]
158+
159+
/// Return an array containing the names of all available buckets using
160+
/// the specified credential identity resolver to authenticate.
161+
///
162+
/// - Parameter identityResolver: Any type of `AWSCredentialIdentityResolver`,
163+
/// used to authenticate and authorize the user for access to the bucket
164+
/// names.
165+
///
166+
/// - Throws: Re-throws errors from `ListBucketsPaginated`.
167+
///
168+
/// - Returns: An array of strings listing the buckets.
169+
func getBucketNames(identityResolver: (any AWSCredentialIdentityResolver)?)
170+
async throws -> [String] {
212171
do {
213-
for try await page in pages {
214-
guard let buckets = page.buckets else {
215-
print("Error: page is empty.")
216-
continue
217-
}
172+
// Get an S3Client with which to access Amazon S3.
173+
// snippet-start:[swift.sts.AssumeRole.use-resolver]
174+
let s3Configuration = try await S3Client.S3ClientConfiguration(
175+
awsCredentialIdentityResolver: identityResolver,
176+
region: region
177+
)
178+
let client = S3Client(config: s3Configuration)
179+
180+
// Use "Paginated" to get all the buckets. This lets the SDK handle
181+
// the 'continuationToken' in "ListBucketsOutput".
182+
let pages = client.listBucketsPaginated(
183+
input: ListBucketsInput( maxBuckets: 10)
184+
)
185+
// snippet-end:[swift.sts.AssumeRole.use-resolver]
186+
187+
// Get the bucket names.
188+
var bucketNames: [String] = []
218189

219-
for bucket in buckets {
220-
bucketNames.append(bucket.name ?? "<unknown>")
190+
do {
191+
for try await page in pages {
192+
guard let buckets = page.buckets else {
193+
print("Error: page is empty.")
194+
continue
195+
}
196+
197+
for bucket in buckets {
198+
bucketNames.append(bucket.name ?? "<unknown>")
199+
}
221200
}
222-
}
223201

224-
return bucketNames
225-
} catch {
226-
print("ERROR: listBuckets:", dump(error))
227-
throw error
202+
return bucketNames
203+
} catch {
204+
print("ERROR: listBuckets:", dump(error))
205+
throw error
206+
}
228207
}
229208
}
230-
}
231209

232-
/// Create a credential identity resolver using access key and secret access
233-
/// key.
234-
///
235-
/// - Parameters:
236-
/// - accessKey: A string containing the AWS access key ID.
237-
/// - secretKey: A string containing the AWS secret access key.
238-
/// - sessionToken: An optional string containing the session token.
239-
/// - Throws: Re-throws errors from AWSSDKIdentity.
240-
/// - Returns: A `StaticAWSCredentialIdentityResolver` that can be used when
241-
/// configuring service clients.
242-
func getIdentityResolver(accessKey: String?, secretKey: String?,
243-
sessionToken: String?)
244-
throws -> StaticAWSCredentialIdentityResolver? {
245-
246-
if accessKey == nil || secretKey == nil {
247-
return nil
248-
}
210+
/// Create a credential identity resolver using access key and secret access
211+
/// key.
212+
///
213+
/// - Parameters:
214+
/// - accessKey: A string containing the AWS access key ID.
215+
/// - secretKey: A string containing the AWS secret access key.
216+
/// - sessionToken: An optional string containing the session token.
217+
/// - Throws: Re-throws errors from AWSSDKIdentity.
218+
/// - Returns: A `StaticAWSCredentialIdentityResolver` that can be used when
219+
/// configuring service clients.
220+
func getIdentityResolver(accessKey: String?, secretKey: String?,
221+
sessionToken: String?)
222+
throws -> StaticAWSCredentialIdentityResolver? {
223+
224+
if accessKey == nil || secretKey == nil {
225+
return nil
226+
}
249227

250-
guard let accessKey = accessKey,
251-
let secretKey = secretKey else {
252-
return nil
253-
}
228+
guard let accessKey = accessKey,
229+
let secretKey = secretKey else {
230+
return nil
231+
}
254232

255-
// snippet-start:[swift.sts.AssumeRole.create-static-resolver]
256-
let credentials = AWSCredentialIdentity(
257-
accessKey: accessKey,
258-
secret: secretKey,
259-
sessionToken: sessionToken
260-
)
233+
// snippet-start:[swift.sts.AssumeRole.create-static-resolver]
234+
let credentials = AWSCredentialIdentity(
235+
accessKey: accessKey,
236+
secret: secretKey,
237+
sessionToken: sessionToken
238+
)
261239

262-
let identityResolver = try StaticAWSCredentialIdentityResolver(credentials)
263-
// snippet-end:[swift.sts.AssumeRole.create-static-resolver]
264-
return identityResolver
240+
let identityResolver = try StaticAWSCredentialIdentityResolver(credentials)
241+
// snippet-end:[swift.sts.AssumeRole.create-static-resolver]
242+
return identityResolver
243+
}
265244
}
266245

267246
/// The program's asynchronous entry point.

0 commit comments

Comments
 (0)