AWS AWSSimpleQueueService documentation change
Summary
Added Swift SDK code example demonstrating SNS-SQS integration with FIFO topics, message filtering, deduplication, and queue policy configuration
Security assessment
The changes demonstrate normal SNS-SQS integration patterns including queue policy setup (security through resource policies) which is a standard security practice, but there's no evidence of addressing a specific vulnerability or security incident. The policy implementation shown is part of normal service configuration.
Diff
diff --git a/AWSSimpleQueueService/latest/SQSDeveloperGuide/example_sqs_Scenario_TopicsAndQueues_section.md b/AWSSimpleQueueService/latest/SQSDeveloperGuide/example_sqs_Scenario_TopicsAndQueues_section.md index 73381e073..9bd397438 100644 --- a//AWSSimpleQueueService/latest/SQSDeveloperGuide/example_sqs_Scenario_TopicsAndQueues_section.md +++ b//AWSSimpleQueueService/latest/SQSDeveloperGuide/example_sqs_Scenario_TopicsAndQueues_section.md @@ -4066,0 +4067,734 @@ There's more on GitHub. Find the complete example and learn how to set up and ru +Swift + + +**SDK for Swift** + + +###### Note + +There's more on GitHub. Find the complete example and learn how to set up and run in the [AWS Code Examples Repository](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/swift/example_code/sqs/scenario#code-examples). + + + import ArgumentParser + import AWSClientRuntime + import AWSSNS + import AWSSQS + import Foundation + + struct ExampleCommand: ParsableCommand { + @Option(help: "Name of the Amazon Region to use") + var region = "us-east-1" + + static var configuration = CommandConfiguration( + commandName: "queue-scenario", + abstract: """ + This example interactively demonstrates how to use Amazon Simple + Notification Service (Amazon SNS) and Amazon Simple Queue Service + (Amazon SQS) together to publish and receive messages using queues. + """, + discussion: """ + Supports filtering using a "tone" attribute. + """ + ) + + /// Prompt for an input string. Only non-empty strings are allowed. + /// + /// - Parameter prompt: The prompt to display. + /// + /// - Returns: The string input by the user. + func stringRequest(prompt: String) -> String { + var str: String? + + while str == nil { + print(prompt, terminator: "") + str = readLine() + + if str != nil && str?.count == 0 { + str = nil + } + } + + return str! + } + + /// Ask a yes/no question. + /// + /// - Parameter prompt: A prompt string to print. + /// + /// - Returns: `true` if the user answered "Y", otherwise `false`. + func yesNoRequest(prompt: String) -> Bool { + while true { + let answer = stringRequest(prompt: prompt).lowercased() + if answer == "y" || answer == "n" { + return answer == "y" + } + } + } + + /// Display a menu of options then request a selection. + /// + /// - Parameters: + /// - prompt: A prompt string to display before the menu. + /// - options: An array of strings giving the menu options. + /// + /// - Returns: The index number of the selected option or 0 if no item was + /// selected. + func menuRequest(prompt: String, options: [String]) -> Int { + let numOptions = options.count + + if numOptions == 0 { + return 0 + } + + print(prompt) + + for (index, value) in options.enumerated() { + print("(\(index)) \(value)") + } + + repeat { + print("Enter your selection (0 - \(numOptions-1)): ", terminator: "") + if let answer = readLine() { + guard let answer = Int(answer) else { + print("Please enter the number matching your selection.") + continue + } + + if answer >= 0 && answer < numOptions { + return answer + } else { + print("Please enter the number matching your selection.") + } + } + } while true + } + + /// Ask the user too press RETURN. Accepts any input but ignores it. + /// + /// - Parameter prompt: The text prompt to display. + func returnRequest(prompt: String) { + print(prompt, terminator: "") + _ = readLine() + } + + var attrValues = [ + "<none>", + "cheerful", + "funny", + "serious", + "sincere" + ] + + /// Ask the user to choose one of the attribute values to use as a filter. + /// + /// - Parameters: + /// - message: A message to display before the menu of values. + /// - attrValues: An array of strings giving the values to choose from. + /// + /// - Returns: The string corresponding to the selected option. + func askForFilter(message: String, attrValues: [String]) -> String? { + print(message) + for (index, value) in attrValues.enumerated() { + print(" [\(index)] \(value)") + } + + var answer: Int? + repeat { + answer = Int(stringRequest(prompt: "Select an value for the 'tone' attribute or 0 to end: ")) + } while answer == nil || answer! < 0 || answer! > attrValues.count + 1 + + if answer == 0 { + return nil + } + return attrValues[answer!] + } + + /// Prompts the user for filter terms and constructs the attribute + /// record that specifies them. + /// + /// - Returns: A mapping of "FilterPolicy" to a JSON string representing + /// the user-defined filter. + func buildFilterAttributes() -> [String:String] { + var attr: [String:String] = [:] + var filterString = "" + + var first = true + + while let ans = askForFilter(message: "Choose a value to apply to the 'tone' attribute.", + attrValues: attrValues) { + if !first { + filterString += "," + } + first = false + + filterString += "\"\(ans)\"" + } + + let filterJSON = "{ \"tone\": [\(filterString)]}" + attr["FilterPolicy"] = filterJSON + + return attr + } + /// Create a queue, returning its URL string. + /// + /// - Parameters: + /// - prompt: A prompt to ask for the queue name. + /// - isFIFO: Whether or not to create a FIFO queue. + /// + /// - Returns: The URL of the queue. + func createQueue(prompt: String, sqsClient: SQSClient, isFIFO: Bool) async throws -> String? { + repeat { + var queueName = stringRequest(prompt: prompt) + var attributes: [String: String] = [:] + + if isFIFO { + queueName += ".fifo" + attributes["FifoQueue"] = "true" + } + + do { + let output = try await sqsClient.createQueue( + input: CreateQueueInput( + attributes: attributes, + queueName: queueName + ) + )