Stopped trying to edit HTTPClient.Request
Instead construct signed request from url, method, headers and body Added helper functions to HTTPClient.Request extension
This commit is contained in:
parent
0747cc22e5
commit
70277f6976
|
@ -2,17 +2,19 @@
|
|||
// credentials.swift
|
||||
// aws-sign
|
||||
//
|
||||
// Created by Adam Fowler on 2019/08/29.
|
||||
// Created by Adam Fowler on 29/08/2019.
|
||||
//
|
||||
import Foundation
|
||||
import INIParser
|
||||
|
||||
/// Protocol for providing credential details for accessing AWS services
|
||||
public protocol CredentialProvider {
|
||||
var accessKeyId: String {get}
|
||||
var secretAccessKey: String {get}
|
||||
var sessionToken: String? {get}
|
||||
}
|
||||
|
||||
/// basic version of CredentialProvider where you supply the credentials
|
||||
public struct Credential : CredentialProvider {
|
||||
public let accessKeyId: String
|
||||
public let secretAccessKey: String
|
||||
|
@ -25,6 +27,7 @@ public struct Credential : CredentialProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/// environment variable version of credential provider that uses system environment variables to get credential details
|
||||
public struct EnvironmentCredential: CredentialProvider {
|
||||
public let accessKeyId: String
|
||||
public let secretAccessKey: String
|
||||
|
|
|
@ -2,47 +2,13 @@
|
|||
// hash.swift
|
||||
// AsyncHTTPClient
|
||||
//
|
||||
// Created by Adam Fowler on 29/08/2019.
|
||||
// Created by Adam Fowler on 2019/08/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
//
|
||||
// Hash.swift
|
||||
// AWSSDKSwift
|
||||
//
|
||||
// Created by Yuki Takei on 2017/03/13.
|
||||
//
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if canImport(CAWSSignOpenSSL)
|
||||
|
||||
import CAWSSignOpenSSL
|
||||
|
||||
public func sha256(_ string: String) -> [UInt8] {
|
||||
var bytes = Array(string.utf8)
|
||||
return sha256(&bytes)
|
||||
}
|
||||
|
||||
public func sha256(_ bytes: inout [UInt8]) -> [UInt8] {
|
||||
var hash = [UInt8](repeating: 0, count: Int(SHA256_DIGEST_LENGTH))
|
||||
SHA256(&bytes, bytes.count, &hash)
|
||||
return hash
|
||||
}
|
||||
|
||||
public func sha256(_ data: Data) -> [UInt8] {
|
||||
return data.withUnsafeBytes { ptr in
|
||||
var hash = [UInt8](repeating: 0, count: Int(SHA256_DIGEST_LENGTH))
|
||||
if let bytes = ptr.baseAddress?.assumingMemoryBound(to: UInt8.self) {
|
||||
SHA256(bytes, data.count, &hash)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
}
|
||||
|
||||
#elseif canImport(CommonCrypto)
|
||||
// Currently only works if CommonCrypto exists. Will look into doing something for Linux later
|
||||
#if canImport(CommonCrypto)
|
||||
|
||||
import CommonCrypto
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// request.swift
|
||||
// AWSSigner
|
||||
//
|
||||
// Created by Adam Fowler on 2019/08/30.
|
||||
//
|
||||
|
||||
import AsyncHTTPClient
|
||||
import Foundation
|
||||
import NIO
|
||||
import NIOHTTP1
|
||||
|
||||
public extension HTTPClient.Request {
|
||||
/// return signed HTTPClient request with signature in the headers
|
||||
static func awsHeaderSignedRequest(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: AWSSigner.BodyData? = nil, date: Date = Date(), signer: AWSSigner) throws -> HTTPClient.Request {
|
||||
let signedHeaders = signer.signHeaders(url: url, method: method, headers: headers, body: body, date: date)
|
||||
return try HTTPClient.Request(url: url, method: method, headers: signedHeaders, body: body?.body)
|
||||
}
|
||||
|
||||
/// return signed HTTPClient request with signature in the URL
|
||||
static func awsURLSignedRequest(url: URL, method: HTTPMethod = .GET, body: AWSSigner.BodyData? = nil, date: Date = Date(), expires: Int = 86400, signer: AWSSigner) throws -> HTTPClient.Request {
|
||||
let signedURL = signer.signURL(url: url, method: method, body: body, date: date, expires: expires)
|
||||
return try HTTPClient.Request(url: signedURL, method: method, body: body?.body)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,106 +6,85 @@
|
|||
// Amazon Web Services V4 Signer
|
||||
// AWS documentation about signing requests is here https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html
|
||||
//
|
||||
|
||||
import AsyncHTTPClient
|
||||
import Foundation
|
||||
import NIO
|
||||
import AsyncHTTPClient
|
||||
import NIOHTTP1
|
||||
|
||||
/// Amazon Web Services V4 Signer
|
||||
public class AWSSigner {
|
||||
static let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||
|
||||
/// security credentials for accessing AWS services
|
||||
let credentials: CredentialProvider
|
||||
let service: String
|
||||
/// service signing name. In general this is the same as the service name
|
||||
let name: String
|
||||
/// AWS region you are working in
|
||||
let region: String
|
||||
|
||||
/// Initialise the Signer class with AWS credentials
|
||||
public init(credentials: CredentialProvider, service: String, region: String) {
|
||||
public init(credentials: CredentialProvider, name: String, region: String) {
|
||||
self.credentials = credentials
|
||||
self.service = service
|
||||
self.name = name
|
||||
self.region = region
|
||||
}
|
||||
|
||||
/// sign a HTTP Request and place in "Authorization" header
|
||||
public func signInHeader(request: HTTPClient.Request) -> HTTPClient.Request {
|
||||
/// Enum for holding your body data
|
||||
public enum BodyData {
|
||||
case string(String)
|
||||
case data(Data)
|
||||
case byteBuffer(ByteBuffer)
|
||||
|
||||
var request = request
|
||||
// add date, host, sha256 and if available security token headers
|
||||
request.headers.add(name: "X-Amz-Date", value: AWSSigner.timestamp(Date()))
|
||||
request.headers.add(name: "host", value: request.url.host ?? "")
|
||||
request.headers.add(name: "x-amz-content-sha256", value: AWSSigner.hashedPayload(request.body))
|
||||
if let sessionToken = credentials.sessionToken {
|
||||
request.headers.add(name: "x-amz-security-token", value: sessionToken)
|
||||
var body : HTTPClient.Body {
|
||||
switch self {
|
||||
case .string(let string):
|
||||
return .string(string)
|
||||
case .data(let data):
|
||||
return .data(data)
|
||||
case .byteBuffer(let byteBuffer):
|
||||
return .byteBuffer(byteBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Generate signed headers, for a HTTP request
|
||||
public func signHeaders(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: BodyData? = nil, date: Date = Date()) -> HTTPHeaders {
|
||||
var headers = headers
|
||||
// add date, host, sha256 and if available security token headers
|
||||
headers.add(name: "X-Amz-Date", value: AWSSigner.timestamp(date))
|
||||
headers.add(name: "host", value: url.host ?? "")
|
||||
headers.add(name: "x-amz-content-sha256", value: AWSSigner.hashedPayload(body))
|
||||
if let sessionToken = credentials.sessionToken {
|
||||
headers.add(name: "x-amz-security-token", value: sessionToken)
|
||||
}
|
||||
|
||||
// construct signing data. Do this after adding the headers as it uses data from the headers
|
||||
let signingData = SigningData(request: request, signer: self)
|
||||
let signingData = AWSSigner.SigningData(url: url, method: method, headers: headers, body: body, date: date, signer: self)
|
||||
|
||||
// construct authorization string
|
||||
let authorization = "AWS4-HMAC-SHA256 " +
|
||||
"Credential=\(credentials.accessKeyId)/\(signingData.date)/\(region)/\(service)/aws4_request, " +
|
||||
"Credential=\(credentials.accessKeyId)/\(signingData.date)/\(region)/\(name)/aws4_request, " +
|
||||
"SignedHeaders=\(signingData.signedHeaders), " +
|
||||
"Signature=\(signature(signingData: signingData))"
|
||||
|
||||
// add Authorization header
|
||||
request.headers.add(name: "Authorization", value: authorization)
|
||||
return request
|
||||
headers.add(name: "Authorization", value: authorization)
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
/// structure used to store data used throughout the signing process
|
||||
struct SigningData {
|
||||
let request : HTTPClient.Request
|
||||
let hashedPayload : String
|
||||
let datetime : String
|
||||
let headersToSign: [String: String]
|
||||
let signedHeaders : String
|
||||
var unsignedURL : URL
|
||||
|
||||
var date : String { return String(datetime.prefix(8))}
|
||||
|
||||
init(request: HTTPClient.Request, signer: AWSSigner) {
|
||||
self.request = request
|
||||
self.datetime = request.headers["x-amz-date"].first ?? AWSSigner.timestamp(Date())
|
||||
self.hashedPayload = request.headers["x-amz-content-sha256"].first ?? AWSSigner.hashedPayload(request.body)
|
||||
self.unsignedURL = request.url
|
||||
|
||||
let headersNotToSign: Set<String> = [
|
||||
"Authorization"
|
||||
]
|
||||
var headersToSign : [String: String] = [:]
|
||||
for header in request.headers {
|
||||
if headersNotToSign.contains(header.name) {
|
||||
continue
|
||||
}
|
||||
headersToSign[header.name] = header.value
|
||||
}
|
||||
self.headersToSign = headersToSign
|
||||
self.signedHeaders = headersToSign.map { return "\($0.key.lowercased())" }
|
||||
.sorted()
|
||||
.joined(separator: ";")
|
||||
}
|
||||
}
|
||||
|
||||
/// return a request with a signed URL
|
||||
public func signURL(request: HTTPClient.Request, expires: Int = 86400) throws -> HTTPClient.Request {
|
||||
|
||||
var request = request
|
||||
// add date, host headers. If the service is s3 then add a sha256 of "UNSIGNED-PAYLOAD"
|
||||
request.headers.add(name: "X-Amz-Date", value: AWSSigner.timestamp(Date()))
|
||||
request.headers.add(name: "host", value: request.url.host ?? "")
|
||||
if service == "s3" {
|
||||
request.headers.add(name: "x-amz-content-sha256", value:"UNSIGNED-PAYLOAD")
|
||||
}
|
||||
|
||||
/// Generate a signed URL, for a HTTP request
|
||||
public func signURL(url: URL, method: HTTPMethod = .GET, body: BodyData? = nil, date: Date = Date(), expires: Int = 86400) -> URL {
|
||||
let headers = HTTPHeaders([("host", url.host ?? "")])
|
||||
// Create signing data
|
||||
var signingData = SigningData(request: request, signer: self)
|
||||
var signingData = AWSSigner.SigningData(url: url, method: method, headers: headers, body: body, date: date, signer: self)
|
||||
|
||||
// Construct query string. Start with original query strings and append all the signing info.
|
||||
var query = request.url.query ?? ""
|
||||
var query = url.query ?? ""
|
||||
if query.count > 0 {
|
||||
query += "&"
|
||||
}
|
||||
query += "X-Amz-Algorithm=AWS4-HMAC-SHA256"
|
||||
query += "&X-Amz-Credential=\(credentials.accessKeyId)/\(signingData.date)/\(region)/\(service)/aws4_request"
|
||||
query += "&X-Amz-Credential=\(credentials.accessKeyId)/\(signingData.date)/\(region)/\(name)/aws4_request"
|
||||
query += "&X-Amz-Date=\(signingData.datetime)"
|
||||
query += "&X-Amz-Expires=\(expires)"
|
||||
query += "&X-Amz-SignedHeaders=\(signingData.signedHeaders)"
|
||||
|
@ -118,20 +97,63 @@ public class AWSSigner {
|
|||
.joined(separator: "&")
|
||||
.addingPercentEncoding(withAllowedCharacters: AWSSigner.queryAllowedCharacters)!
|
||||
|
||||
// update unsignURL in the signingData so when the canonical request is constructed it includes all the signing query items
|
||||
signingData.unsignedURL = URL(string: request.url.absoluteString.split(separator: "?")[0]+"?"+query)! // NEED TO DEAL WITH SITUATION WHERE THIS FAILS
|
||||
// update unsignedURL in the signingData so when the canonical request is constructed it includes all the signing query items
|
||||
signingData.unsignedURL = URL(string: url.absoluteString.split(separator: "?")[0]+"?"+query)! // NEED TO DEAL WITH SITUATION WHERE THIS FAILS
|
||||
query += "&X-Amz-Signature=\(signature(signingData: signingData))"
|
||||
|
||||
|
||||
// Add signature to query items and build a new Request
|
||||
let signedURL = URL(string: request.url.absoluteString.split(separator: "?")[0]+"?"+query)!
|
||||
return try HTTPClient.Request(url: signedURL, method: request.method, headers: request.headers, body: request.body)
|
||||
let signedURL = URL(string: url.absoluteString.split(separator: "?")[0]+"?"+query)!
|
||||
return signedURL
|
||||
}
|
||||
|
||||
/// structure used to store data used throughout the signing process
|
||||
struct SigningData {
|
||||
let url : URL
|
||||
let method : HTTPMethod
|
||||
let hashedPayload : String
|
||||
let datetime : String
|
||||
let headersToSign: [String: String]
|
||||
let signedHeaders : String
|
||||
var unsignedURL : URL
|
||||
|
||||
var date : String { return String(datetime.prefix(8))}
|
||||
|
||||
init(url: URL, method: HTTPMethod = .GET, headers: HTTPHeaders = HTTPHeaders(), body: BodyData? = nil, date: Date = Date(), signer: AWSSigner) {
|
||||
self.url = url
|
||||
self.method = method
|
||||
self.datetime = headers["x-amz-date"].first ?? AWSSigner.timestamp(date)
|
||||
self.unsignedURL = self.url
|
||||
|
||||
if let hash = headers["x-amz-content-sha256"].first {
|
||||
self.hashedPayload = hash
|
||||
} else if signer.name == "s3" {
|
||||
self.hashedPayload = "UNSIGNED-PAYLOAD"
|
||||
} else {
|
||||
self.hashedPayload = AWSSigner.hashedPayload(body)
|
||||
}
|
||||
|
||||
let headersNotToSign: Set<String> = [
|
||||
"Authorization"
|
||||
]
|
||||
var headersToSign : [String: String] = [:]
|
||||
for header in headers {
|
||||
if headersNotToSign.contains(header.name) {
|
||||
continue
|
||||
}
|
||||
headersToSign[header.name] = header.value
|
||||
}
|
||||
self.headersToSign = headersToSign
|
||||
self.signedHeaders = headersToSign.map { return "\($0.key.lowercased())" }
|
||||
.sorted()
|
||||
.joined(separator: ";")
|
||||
}
|
||||
}
|
||||
|
||||
// Calculating signature as in https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
|
||||
func signature(signingData: SigningData) -> String {
|
||||
let kDate = hmac(string:signingData.date, key:Array("AWS4\(credentials.secretAccessKey)".utf8))
|
||||
let kRegion = hmac(string: region, key: kDate)
|
||||
let kService = hmac(string: service, key: kRegion)
|
||||
let kService = hmac(string: name, key: kRegion)
|
||||
let kSigning = hmac(string: "aws4_request", key: kService)
|
||||
let kSignature = hmac(string: stringToSign(signingData: signingData), key: kSigning)
|
||||
return AWSSigner.hexEncoded(kSignature)
|
||||
|
@ -141,7 +163,7 @@ public class AWSSigner {
|
|||
func stringToSign(signingData: SigningData) -> String {
|
||||
let stringToSign = "AWS4-HMAC-SHA256\n" +
|
||||
"\(signingData.datetime)\n" +
|
||||
"\(signingData.date)/\(region)/\(service)/aws4_request\n" +
|
||||
"\(signingData.date)/\(region)/\(name)/aws4_request\n" +
|
||||
AWSSigner.hexEncoded(sha256(canonicalRequest(signingData: signingData)))
|
||||
return stringToSign
|
||||
}
|
||||
|
@ -151,7 +173,7 @@ public class AWSSigner {
|
|||
let canonicalHeaders = signingData.headersToSign.map { return "\($0.key.lowercased()):\($0.value)" }
|
||||
.sorted()
|
||||
.joined(separator: "\n") // REMEMBER TO TRIM THE VALUE
|
||||
let canonicalRequest = "\(signingData.request.method.rawValue)\n" +
|
||||
let canonicalRequest = "\(signingData.method.rawValue)\n" +
|
||||
"\(signingData.unsignedURL.path)\n" +
|
||||
"\(signingData.unsignedURL.query ?? "")\n" +
|
||||
"\(canonicalHeaders)\n\n" +
|
||||
|
@ -161,15 +183,27 @@ public class AWSSigner {
|
|||
}
|
||||
|
||||
/// Create a SHA256 hash of the Requests body
|
||||
static func hashedPayload(_ payload: HTTPClient.Body?) -> String {
|
||||
static func hashedPayload(_ payload: BodyData?) -> String {
|
||||
guard let payload = payload else { return AWSSigner.hexEncoded(sha256([UInt8]())) }
|
||||
var hash : [UInt8] = []
|
||||
_ = payload.stream(HTTPClient.Body.StreamWriter { (data) -> EventLoopFuture<Void> in
|
||||
guard case .byteBuffer(let buffer) = data else {return AWSSigner.eventLoopGroup.next().makeSucceededFuture(Void())}
|
||||
hash = sha256(Array(buffer.readableBytesView))
|
||||
return AWSSigner.eventLoopGroup.next().makeSucceededFuture(Void())
|
||||
})
|
||||
return AWSSigner.hexEncoded(hash)
|
||||
let hash : [UInt8]?
|
||||
switch payload {
|
||||
case .string(let string):
|
||||
hash = sha256(string)
|
||||
case .data(let data):
|
||||
hash = data.withContiguousStorageIfAvailable { bytes in
|
||||
return sha256(bytes)
|
||||
}
|
||||
case .byteBuffer(let byteBuffer):
|
||||
let byteBufferView = byteBuffer.readableBytesView
|
||||
hash = byteBufferView.withContiguousStorageIfAvailable { bytes in
|
||||
return sha256(bytes)
|
||||
}
|
||||
}
|
||||
if let hash = hash {
|
||||
return AWSSigner.hexEncoded(hash)
|
||||
} else {
|
||||
return AWSSigner.hexEncoded(sha256([UInt8]()))
|
||||
}
|
||||
}
|
||||
|
||||
/// return a hexEncoded string buffer from an array of bytes
|
||||
|
@ -186,5 +220,5 @@ public class AWSSigner {
|
|||
return formatter.string(from: date)
|
||||
}
|
||||
|
||||
static let queryAllowedCharacters = CharacterSet(charactersIn:"/;+").inverted
|
||||
static let queryAllowedCharacters = CharacterSet(charactersIn:"/;").inverted
|
||||
}
|
||||
|
|
|
@ -3,69 +3,33 @@ import AsyncHTTPClient
|
|||
@testable import AWSSigner
|
||||
|
||||
final class aws_signTests: XCTestCase {
|
||||
let credentials : CredentialProvider = (SharedCredential() ?? EnvironmentCredential()) ?? Credential(accessKeyId: "", secretAccessKey: "")
|
||||
let credentials : CredentialProvider = Credential(accessKeyId: "MYACCESSKEY", secretAccessKey: "MYSECRETACCESSKEY")
|
||||
|
||||
func testSignS3Headers() {
|
||||
do {
|
||||
let client = HTTPClient(eventLoopGroupProvider: .createNew)
|
||||
let request = try HTTPClient.Request(url: "https://s3.us-east-1.amazonaws.com/test-bucket", method: .PUT, headers: [:])
|
||||
let signedRequest = try AWSSigner(credentials: credentials, service:"s3", region:"us-east-1").signURL(request: request)
|
||||
let response = try client.execute(request: signedRequest).wait()
|
||||
print("Status code \(response.status.code)")
|
||||
XCTAssertTrue(200..<300 ~= response.status.code || response.status.code == 409)
|
||||
if let body = response.body {
|
||||
let bodyString = body.getString(at: 0, length: body.readableBytes)
|
||||
print(bodyString ?? "")
|
||||
}
|
||||
|
||||
try client.syncShutdown()
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
func testSignGetHeaders() {
|
||||
let signer = AWSSigner(credentials: credentials, name: "glacier", region:"us-east-1")
|
||||
let headers = signer.signHeaders(url: URL(string:"https://glacier.us-east-1.amazonaws.com/-/vaults")!, method: .GET, headers: ["x-amz-glacier-version":"2012-06-01"], date: Date(timeIntervalSinceReferenceDate: 2000000))
|
||||
XCTAssertEqual(headers["Authorization"].first, "AWS4-HMAC-SHA256 Credential=MYACCESSKEY/20010124/us-east-1/glacier/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-glacier-version, Signature=acfa9b03fca6b098d7b88bfd9bbdb4687f5b34e944a9c6ed9f4814c1b0b06d62")
|
||||
print(headers["Authorization"])
|
||||
}
|
||||
|
||||
func testSignSNSHeaders() {
|
||||
do {
|
||||
let client = HTTPClient(eventLoopGroupProvider: .createNew)
|
||||
let request = try HTTPClient.Request(url: "https://sns.eu-west-1.amazonaws.com/", method: .POST, headers: ["Content-Type": "application/x-www-form-urlencoded; charset=utf-8"], body: .string("Action=ListTopics&Version=2010-03-31"))
|
||||
let signedRequest = AWSSigner(credentials: credentials, service:"sns", region:"eu-west-1").signInHeader(request: request)
|
||||
let response = try client.execute(request: signedRequest).wait()
|
||||
print("Status code \(response.status.code)")
|
||||
XCTAssertTrue(200..<300 ~= response.status.code)
|
||||
if let body = response.body {
|
||||
let bodyString = body.getString(at: 0, length: body.readableBytes)
|
||||
print(bodyString ?? "")
|
||||
}
|
||||
|
||||
try client.syncShutdown()
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
func testSignPutHeaders() {
|
||||
let signer = AWSSigner(credentials: credentials, name: "sns", region:"eu-west-1")
|
||||
let headers = signer.signHeaders(url: URL(string: "https://sns.eu-west-1.amazonaws.com/")!, method: .POST, headers: ["Content-Type": "application/x-www-form-urlencoded; charset=utf-8"], body: .string("Action=ListTopics&Version=2010-03-31"), date: Date(timeIntervalSinceReferenceDate: 200))
|
||||
XCTAssertEqual(headers["Authorization"].first, "AWS4-HMAC-SHA256 Credential=MYACCESSKEY/20010101/eu-west-1/sns/aws4_request, SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date, Signature=1d29943055a8ad094239e8de06082100f2426ebbb2c6a5bbcbb04c63e6a3f274")
|
||||
}
|
||||
|
||||
func testSignS3URL() {
|
||||
do {
|
||||
let client = HTTPClient(eventLoopGroupProvider: .createNew)
|
||||
let request = try HTTPClient.Request(url: "https://s3.eu-west-1.amazonaws.com/", method: .GET, headers: [:])
|
||||
let signedRequest = try AWSSigner(credentials: credentials, service:"s3", region:"eu-west-1").signURL(request: request)
|
||||
let response = try client.execute(request: signedRequest).wait()
|
||||
print("Status code \(response.status.code)")
|
||||
XCTAssertTrue(200..<300 ~= response.status.code)
|
||||
if let body = response.body {
|
||||
let bodyString = body.getString(at: 0, length: body.readableBytes)
|
||||
print(bodyString ?? "")
|
||||
} else {
|
||||
XCTFail("Empty body")
|
||||
}
|
||||
|
||||
try client.syncShutdown()
|
||||
} catch {
|
||||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
func testSignS3GetURL() {
|
||||
let signer = AWSSigner(credentials: credentials, name: "s3", region:"us-east-1")
|
||||
let url = signer.signURL(url: URL(string: "https://s3.us-east-1.amazonaws.com/")!, method: .GET, date:Date(timeIntervalSinceReferenceDate: 100000))
|
||||
XCTAssertEqual(url.absoluteString, "https://s3.us-east-1.amazonaws.com/?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MYACCESSKEY%2F20010102%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20010102T034640Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=27957103c8bfdff3560372b1d85976ed29c944f34295eca2d4fdac7fc02c375a")
|
||||
}
|
||||
|
||||
func testSignS3PutURL() {
|
||||
let signer = AWSSigner(credentials: credentials, name: "s3", region:"eu-west-1")
|
||||
let url = signer.signURL(url: URL(string: "https://test-bucket.s3.amazonaws.com/test-put.txt")!, method: .PUT, body: .string("Testing signed URLs"), date:Date(timeIntervalSinceReferenceDate: 100000))
|
||||
XCTAssertEqual(url.absoluteString, "https://test-bucket.s3.amazonaws.com/test-put.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=MYACCESSKEY%2F20010102%2Feu-west-1%2Fs3%2Faws4_request&X-Amz-Date=20010102T034640Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=13d665549a6ea5eb6a1615ede83440eaed3e0ee25c964e62d188c896d916d96f")
|
||||
}
|
||||
static var allTests = [
|
||||
("testSignS3URL", testSignS3URL),
|
||||
("testSignSNSHeaders", testSignSNSHeaders),
|
||||
("testSignS3Headers", testSignS3Headers),
|
||||
("testSignS3GetURL", testSignS3GetURL),
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue