Skip to content

Add mTLS client certificate information to APIGatwayV2Request #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Sources/AWSLambdaEvents/APIGateway+V2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ public struct APIGatewayV2Request: Codable {
public let lambda: LambdaAuthorizerContext?
}

public struct Authentication: Codable {
public struct ClientCert: Codable {
public struct Validity: Codable {
public let notBefore: String
public let notAfter: String
}

public let clientCertPem: String
public let subjectDN: String
public let issuerDN: String
public let serialNumber: String
public let validity: Validity
}

public let clientCert: ClientCert?
}

public let accountId: String
public let apiId: String
public let domainName: String
Expand All @@ -65,6 +82,7 @@ public struct APIGatewayV2Request: Codable {

public let http: HTTP
public let authorizer: Authorizer?
public let authentication: Authentication?

/// The request time in format: 23/Apr/2020:11:08:18 +0000
public let time: String
Expand Down Expand Up @@ -136,5 +154,8 @@ extension APIGatewayV2Request.Context.Authorizer: Sendable {}
extension APIGatewayV2Request.Context.Authorizer.JWT: Sendable {}
extension APIGatewayV2Request.Context.Authorizer.IAM: Sendable {}
extension APIGatewayV2Request.Context.Authorizer.IAM.CognitoIdentity: Sendable {}
extension APIGatewayV2Request.Context.Authentication: Sendable {}
extension APIGatewayV2Request.Context.Authentication.ClientCert: Sendable {}
extension APIGatewayV2Request.Context.Authentication.ClientCert.Validity: Sendable {}
extension APIGatewayV2Response: Sendable {}
#endif
85 changes: 85 additions & 0 deletions Tests/AWSLambdaEventsTests/APIGateway+V2Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,78 @@ class APIGatewayV2Tests: XCTestCase {
}
"""

static let fullExamplePayload = """
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
"cookies": [
"cookie1",
"cookie2"
],
"headers": {
"header1": "value1",
"header2": "value1,value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authentication": {
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"authorizer": {
"jwt": {
"claims": {
"claim1": "value1",
"claim2": "value2"
},
"scopes": [
"scope1",
"scope2"
]
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "192.0.2.1",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"body": "Hello from Lambda",
"pathParameters": {
"parameter1": "value1"
},
"isBase64Encoded": false,
"stageVariables": {
"stageVariable1": "value1",
"stageVariable2": "value2"
}
}
"""

// MARK: - Request -

// MARK: Decoding
Expand All @@ -90,4 +162,17 @@ class APIGatewayV2Tests: XCTestCase {

XCTAssertNil(req?.body)
}

func testDecodingRequestClientCert() throws {
let data = APIGatewayV2Tests.fullExamplePayload.data(using: .utf8)!
let request = try JSONDecoder().decode(APIGatewayV2Request.self, from: data)
let clientCert = request.context.authentication?.clientCert

XCTAssertEqual(clientCert?.clientCertPem, "CERT_CONTENT")
XCTAssertEqual(clientCert?.subjectDN, "www.example.com")
XCTAssertEqual(clientCert?.issuerDN, "Example issuer")
XCTAssertEqual(clientCert?.serialNumber, "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1")
XCTAssertEqual(clientCert?.validity.notBefore, "May 28 12:30:02 2019 GMT")
XCTAssertEqual(clientCert?.validity.notAfter, "Aug 5 09:36:04 2021 GMT")
}
}