Skip to content
This repository was archived by the owner on Apr 5, 2020. It is now read-only.

Commit 1f1e301

Browse files
authored
Merge pull request #4 from Yasumoto/master
Adds ability to provide temporary credential token when using EC2 instances. Update swift version.
2 parents aad80ea + ae76cb5 commit 1f1e301

File tree

5 files changed

+40
-21
lines changed

5 files changed

+40
-21
lines changed

.swift-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.0
1+
3.0.2

Package.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,5 @@ let package = Package(
77
.Package(url: "https://github.com/vapor/crypto.git",
88
majorVersion: 1),
99
.Package(url: "https://github.com/vapor/core.git", majorVersion: 1)
10-
11-
12-
]
10+
]
1311
)
14-

Sources/S3SignerAWS.swift

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Core
66
public class S3SignerAWS {
77
private let accessKey: String
88
private let secretKey: String
9+
private let securityToken : String? // Used to validate temporary credentials, such as those from an EC2 Instance's IAM role
910
private let _region: Region
1011
private let dateFormatter: DateFormatter
1112

@@ -14,14 +15,22 @@ public class S3SignerAWS {
1415
return self._region
1516
}
1617
}
17-
18-
required public init(accessKey: String, secretKey: String, region: Region) {
18+
19+
/// Initializes a signer which works for either permanent credentials or temporary secrets
20+
///
21+
/// - Parameters:
22+
/// - accessKey: Main token to identify the credential
23+
/// - secretKey: Password to validate access
24+
/// - region: Which AWS region to sign against
25+
/// - securityToken: Optional token used only with temporary credentials
26+
public init(accessKey: String, secretKey: String, region: Region, securityToken: String? = nil) {
1927
self.accessKey = accessKey
2028
self.secretKey = secretKey
2129
self._region = region
30+
self.securityToken = securityToken
2231
self.dateFormatter = DateFormatter()
2332
}
24-
33+
2534
public func authHeaderV4(httpMethod: HTTPMethod, urlString: String, pathPercentEncoding: CharacterSet = CharacterSet.urlPathAllowed, queryPercentEncoding: CharacterSet = CharacterSet.urlQueryAllowed, headers: [String: String], payload: Payload, mimeType: String? = nil) throws -> [String:String] {
2635

2736
guard let url = URL(string: urlString) else { throw S3SignerError.badURL }
@@ -34,7 +43,7 @@ public class S3SignerAWS {
3443

3544
if httpMethod == .put {
3645
if payload.isBytes {
37-
let MD5Digest = try Hash.make(.md5, payload.bytes).base64String
46+
let MD5Digest = try Hash.make(.md5, payload.bytes).base64Encoded.string
3847
updatedHeaders["content-md5"] = MD5Digest
3948
}
4049
}
@@ -79,7 +88,7 @@ public class S3SignerAWS {
7988
guard let stringToSign = ["GET", "", "", "\(expirationTime)", path(url: url)].joined(separator: "\n").data(using: String.Encoding.utf8) else { throw S3SignerError.unableToEncodeStringToSign }
8089

8190
let stringToSignBytes = try stringToSign.makeBytes()
82-
let signature = try HMAC.make(.sha1, stringToSignBytes, key: secretKey.bytes).base64String.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
91+
let signature = try HMAC.make(.sha1, stringToSignBytes, key: secretKey.bytes).base64Encoded.string.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
8392
guard let sig = signature else { throw S3SignerError.unableToEncodeSignature }
8493

8594
let finalURLString = "\(urlString)?AWSAccessKeyId=\(accessKey)&Signature=\(sig)&Expires=\(expirationTime)"
@@ -113,6 +122,10 @@ public class S3SignerAWS {
113122
if bodyDigest != "UNSIGNED-PAYLOAD" {
114123
headersCopy["x-amz-content-sha256"] = bodyDigest
115124
}
125+
// According to http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html#RequestWithSTS
126+
if let token = securityToken {
127+
headersCopy["X-Amz-Security-Token"] = token
128+
}
116129
return headersCopy
117130
}
118131

File renamed without changes.

S3SignerAWSTests/S3SignerAWSTests.swift renamed to Tests/S3SignerAWSTests/S3SignerAWSTests.swift

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ class S3SignerAWSTests: XCTestCase {
2121
let accessKey = "AKIAIOSFODNN7EXAMPLE"
2222
let testSecretKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
2323

24-
var signer: S3SignerAWS = S3SignerAWS(accessKey: accessKey, secretKey: testSecretKey, region: Region.usStandard_usEast1)
24+
var signer: S3SignerAWS {
25+
get {
26+
return S3SignerAWS(accessKey: accessKey, secretKey: testSecretKey, region: Region.usEast1_Virginia)
27+
}
28+
}
2529

2630
let shortDate = "20130524"
2731
let longDate = "20130524T000000Z"
@@ -247,16 +251,21 @@ class S3SignerAWSTests: XCTestCase {
247251
// }
248252
// }
249253
// }
250-
//
251-
//
252-
//
253-
//
254-
// func testPerformanceExample() {
255-
// // This is an example of a performance test case.
256-
// self.measure {
257-
// }
258-
// }
259-
//
254+
255+
func testAuthHeaderV4ConfigCredentials() throws {
256+
let configFileCredentials = try signer.authHeaderV4(httpMethod: .get, urlString: "http://fake-url.com", headers: [:], payload: .none)
257+
XCTAssert(configFileCredentials["x-amz-content-sha256"] == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
258+
XCTAssert(configFileCredentials["host"] == "fake-url.com")
259+
XCTAssert(configFileCredentials["X-Amz-Security-Token"] == nil)
260+
}
261+
262+
func testAuthHeaderV4IAMCredentials() throws {
263+
let iamSigner = S3SignerAWS(accessKey: accessKey, secretKey: testSecretKey, region: Region.usEast1_Virginia, securityToken: "verySecure")
264+
let iamBasedCredentials = try iamSigner.authHeaderV4(httpMethod: .get, urlString: "http://fake-url.com", headers: [:], payload: .none)
265+
XCTAssert(iamBasedCredentials["x-amz-content-sha256"] == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
266+
XCTAssert(iamBasedCredentials["host"] == "fake-url.com")
267+
XCTAssert(iamBasedCredentials["X-Amz-Security-Token"] == "verySecure")
268+
}
260269
}
261270

262271

0 commit comments

Comments
 (0)