Skip to content

Commit 0064b1b

Browse files
sbSteveKxiazhvera
andauthored
MQTT and TLS Implementation (#287)
MQTT5 bindings and support iOS and tvOS dispatch queue and SecItem support Co-authored-by: Vera Xia <[email protected]>
1 parent 74d970d commit 0064b1b

30 files changed

+5169
-50
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Builder
2+
3+
class CrtCiPrepXCodebuild(Builder.Action):
4+
def run(self, env):
5+
env.shell.setenv("TEST_RUNNER_AWS_TESTING_STS_ROLE_ARN", env.shell.get_secret("aws-c-auth-testing/sts-role-arn"))
6+
actions = [
7+
Builder.SetupCrossCICrtEnvironment(use_xcodebuild=True)
8+
]
9+
return Builder.Script(actions, name='crt-ci-prep-xcodebuild')

.github/workflows/ci.yml

+7-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ on:
66
- 'main'
77

88
env:
9-
BUILDER_VERSION: v0.9.73
9+
BUILDER_VERSION: v0.9.77
1010
BUILDER_SOURCE: releases
1111
BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
1212
PACKAGE_NAME: aws-crt-swift
@@ -80,7 +80,7 @@ jobs:
8080
strategy:
8181
fail-fast: false
8282
matrix:
83-
# This matrix runs tests on iOS, tvOS & watchOS, on oldest & newest supported Xcodes
83+
# This matrix runs tests on iOS and tvOS on oldest & newest supported Xcodes
8484
runner:
8585
- macos-13 # x64
8686
- macos-14
@@ -90,9 +90,7 @@ jobs:
9090
[{ os: ios, destination: 'iOS Simulator,OS=16.1,name=iPhone 14'},
9191
{ os: ios, destination: 'iOS Simulator,OS=17.2,name=iPhone 15'},
9292
{ os: tvos, destination: 'tvOS Simulator,OS=16.1,name=Apple TV 4K (3rd generation) (at 1080p)'},
93-
{ os: tvos, destination: 'tvOS Simulator,OS=17.2,name=Apple TV 4K (3rd generation) (at 1080p)'},
94-
{ os: watchos, destination: 'watchOS Simulator,OS=10.2,name=Apple Watch SE (40mm) (2nd generation)'},
95-
{ os: watchos, destination: 'watchOS Simulator,OS=9.1,name=Apple Watch Series 5 (40mm)'}]
93+
{ os: tvos, destination: 'tvOS Simulator,OS=17.2,name=Apple TV 4K (3rd generation) (at 1080p)'}]
9694
xcode:
9795
- Xcode_14.1
9896
- Xcode_15.2
@@ -102,6 +100,10 @@ jobs:
102100
xcode: Xcode_15.2
103101
- runner: macos-13
104102
xcode: Xcode_15.2
103+
- runner: macos-13-xlarge
104+
target: { os: ios, destination: 'iOS Simulator,OS=16.1,name=iPhone 14'}
105+
- runner: macos-13
106+
target: { os: ios, destination: 'iOS Simulator,OS=16.1,name=iPhone 14'}
105107
# Don't run new macOS with old Xcode
106108
- runner: macos-14-large
107109
xcode: Xcode_14.1
@@ -117,10 +119,6 @@ jobs:
117119
xcode: Xcode_14.1
118120
- target: { os: ios, destination: 'iOS Simulator,OS=17.2,name=iPhone 15'}
119121
xcode: Xcode_14.1
120-
- target: { os: watchos, destination: 'watchOS Simulator,OS=10.2,name=Apple Watch SE (40mm) (2nd generation)'}
121-
xcode: Xcode_14.1
122-
- target: { os: watchos, destination: 'watchOS Simulator,OS=9.1,name=Apple Watch Series 5 (40mm)'}
123-
xcode: Xcode_15.2
124122
steps:
125123
- uses: aws-actions/configure-aws-credentials@v4
126124
with:

.gitignore

+20
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,23 @@ cmake-build-debug
77
.DS_Store
88
.swiftpm
99
.vscode
10+
11+
# Ignore XCode project local user data
12+
### Xcode ###
13+
## User settings
14+
**/xcuserdata/
15+
16+
## Xcode 8 and earlier
17+
*.xcscmblueprint
18+
*.xccheckout
19+
20+
### Xcode Patch ###
21+
*.xcodeproj/*
22+
!*.xcodeproj/project.pbxproj
23+
!*.xcodeproj/xcshareddata/
24+
!*.xcodeproj/project.xcworkspace/
25+
!*.xcworkspace/contents.xcworkspacedata
26+
/*.gcno
27+
**/xcshareddata/WorkspaceSettings.xcsettings
28+
29+
# End of https://www.toptal.com/developers/gitignore/api/xcode

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@
2828
[submodule "aws-common-runtime/aws-c-event-stream"]
2929
path = aws-common-runtime/aws-c-event-stream
3030
url = https://github.com/awslabs/aws-c-event-stream
31+
[submodule "aws-common-runtime/aws-c-mqtt"]
32+
path = aws-common-runtime/aws-c-mqtt
33+
url = https://github.com/awslabs/aws-c-mqtt.git

.swiftlint.yml

+6-13
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ analyzer_rules:
77

88
disabled_rules:
99
- trailing_whitespace
10-
- todo
11-
- identifier_name
1210
- compiler_protocol_init
1311
- function_parameter_count
1412
- multiple_closures_with_trailing_closure
@@ -17,37 +15,32 @@ disabled_rules:
1715
- syntactic_sugar
1816
- unused_capture_list
1917
- blanket_disable_command
18+
- identifier_name
2019
- trailing_comma
2120

2221
opt_in_rules:
23-
- empty_count
2422
- vertical_parameter_alignment_on_call
23+
- empty_count
2524

2625
# configurable rules can be customized from this configuration file
2726
force_cast: warning
27+
opening_brace: error
2828
closing_brace: error
2929
colon:
3030
severity: error
3131
comma: error
32-
empty_count: warning
3332
empty_enum_arguments: error
3433
function_body_length:
3534
warning: 100
3635
error: 150
37-
identifier_name:
38-
excluded:
39-
- id
40-
- of
41-
- or
4236
line_length:
43-
warning: 120
37+
warning: 140
4438
error: 160
4539
ignores_comments: true
46-
opening_brace: error
4740
return_arrow_whitespace: error
4841
statement_position:
4942
severity: error
50-
todo: warning
5143
trailing_semicolon: error
5244
vertical_parameter_alignment: error
53-
vertical_parameter_alignment_on_call: true
45+
vertical_parameter_alignment_on_call:
46+
severity: error

Package.swift

+37-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ let cSettings: [CSetting] = [
2222
.define("AWS_APPSTORE_SAFE"),
2323
]
2424

25+
/// Store any defines that will be used by Swift Tests in swiftTestSettings
26+
var swiftTestSettings: [SwiftSetting] = []
27+
2528
//////////////////////////////////////////////////////////////////////
2629
/// Configure C targets.
2730
/// Note: We can not use unsafe flags because SwiftPM makes the target ineligible for use by other packages.
@@ -113,7 +116,6 @@ packageTargets.append(.target(
113116
.define("S2N_BUILD_RELEASE"),
114117
.define("_FORTIFY_SOURCE", to: "2"),
115118
.define("POSIX_C_SOURCE", to: "200809L"),
116-
117119
]
118120
))
119121
#endif
@@ -137,16 +139,25 @@ awsCIoPlatformExcludes.append("source/linux")
137139
awsCIoPlatformExcludes.append("source/s2n")
138140
awsCIoPlatformExcludes.append("source/darwin")
139141
cSettingsIO.append(.define("AWS_ENABLE_IO_COMPLETION_PORTS"))
142+
swiftTestSettings.append(.define("AWS_ENABLE_IO_COMPLETION_PORTS"))
140143
#elseif os(Linux)
141144
awsCIoPlatformExcludes.append("source/windows")
142145
awsCIoPlatformExcludes.append("source/bsd")
143146
awsCIoPlatformExcludes.append("source/darwin")
144147
cSettingsIO.append(.define("AWS_ENABLE_EPOLL"))
148+
swiftTestSettings.append(.define("AWS_ENABLE_EPOLL"))
145149
#else // macOS, iOS, watchOS, tvOS
146150
awsCIoPlatformExcludes.append("source/windows")
147151
awsCIoPlatformExcludes.append("source/linux")
148152
awsCIoPlatformExcludes.append("source/s2n")
149-
cSettingsIO.append(.define("AWS_ENABLE_KQUEUE"))
153+
cSettingsIO.append(.define("__APPLE__"))
154+
cSettingsIO.append(.define("AWS_ENABLE_DISPATCH_QUEUE", .when(platforms: [.iOS, .tvOS, .macOS])))
155+
cSettingsIO.append(.define("AWS_USE_SECITEM", .when(platforms: [.iOS, .tvOS])))
156+
cSettingsIO.append(.define("AWS_ENABLE_KQUEUE", .when(platforms: [.macOS])))
157+
swiftTestSettings.append(.define("__APPLE__"))
158+
swiftTestSettings.append(.define("AWS_ENABLE_DISPATCH_QUEUE", .when(platforms: [.iOS, .tvOS, .macOS])))
159+
swiftTestSettings.append(.define("AWS_USE_SECITEM", .when(platforms: [.iOS, .tvOS])))
160+
swiftTestSettings.append(.define("AWS_ENABLE_KQUEUE", .when(platforms: [.macOS])))
150161
#endif
151162

152163
//////////////////////////////////////////////////////////////////////
@@ -204,6 +215,15 @@ let awsCEventStreamExcludes = [
204215
"CODE_OF_CONDUCT.md",
205216
"clang-tidy/run-clang-tidy.sh"] + excludesFromAll
206217

218+
//////////////////////////////////////////////////////////////////////
219+
/// aws-c-mqtt
220+
//////////////////////////////////////////////////////////////////////
221+
222+
let awsCMqttExcludes = [
223+
"bin",
224+
"CODE_OF_CONDUCT.md"
225+
] + excludesFromAll
226+
207227
packageTargets.append(contentsOf: [
208228
.target(
209229
name: "AwsCPlatformConfig",
@@ -274,6 +294,16 @@ packageTargets.append(contentsOf: [
274294
exclude: awsCEventStreamExcludes,
275295
cSettings: cSettings
276296
),
297+
.target(
298+
name: "AwsCMqtt",
299+
dependencies: ["AwsCHttp", "AwsCCal", "AwsCIo", "AwsCCommon"],
300+
path: "aws-common-runtime/aws-c-mqtt",
301+
exclude: awsCMqttExcludes,
302+
cSettings: cSettings
303+
),
304+
.systemLibrary(
305+
name: "LibNative"
306+
),
277307
.target(
278308
name: "AwsCommonRuntimeKit",
279309
dependencies: [ "AwsCAuth",
@@ -283,7 +313,9 @@ packageTargets.append(contentsOf: [
283313
"AwsCIo",
284314
"AwsCCommon",
285315
"AwsCChecksums",
286-
"AwsCEventStream"],
316+
"AwsCEventStream",
317+
"AwsCMqtt",
318+
"LibNative"],
287319
path: "Source/AwsCommonRuntimeKit",
288320
resources: [
289321
.copy("PrivacyInfo.xcprivacy")
@@ -295,7 +327,8 @@ packageTargets.append(contentsOf: [
295327
path: "Test/AwsCommonRuntimeKitTests",
296328
resources: [
297329
.process("Resources")
298-
]
330+
],
331+
swiftSettings: swiftTestSettings
299332
),
300333
.executableTarget(
301334
name: "Elasticurl",

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# AwsCommonRuntimeKit
2-
The AWS CRT for Swift is currently in developer preview and is intended strictly for feedback purposes only.
2+
The AWS CRT for Swift is currently in developer preview and is intended strictly for feedback purposes only.
33
Do not use this for production workloads.
44

55
## Building
@@ -29,4 +29,4 @@ Required Reading:
2929
Useful Videos:
3030
- [Safely manage pointers in Swift](https://developer.apple.com/videos/play/wwdc2020/10167/)
3131
- [Unsafe Swift](https://developer.apple.com/videos/play/wwdc2020/10648)
32-
- [Swift and C Interoperability](https://youtu.be/0kim9mxBOA8)
32+
- [Swift and C Interoperability](https://youtu.be/0kim9mxBOA8)

Source/AwsCommonRuntimeKit/CommonRuntimeKit.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import AwsCEventStream
22
import AwsCAuth
3+
import AwsCMqtt
4+
import LibNative
35

46
/**
57
* Initializes the library.
@@ -12,6 +14,8 @@ public struct CommonRuntimeKit {
1214
public static func initialize() {
1315
aws_auth_library_init(allocator.rawValue)
1416
aws_event_stream_library_init(allocator.rawValue)
17+
aws_mqtt_library_init(allocator.rawValue)
18+
aws_register_error_info(&s_crt_swift_error_list)
1519
}
1620

1721
/**
@@ -20,8 +24,11 @@ public struct CommonRuntimeKit {
2024
* Warning: It will hang if you are still holding references to any CRT objects such as HostResolver.
2125
*/
2226
public static func cleanUp() {
23-
aws_auth_library_clean_up()
27+
aws_unregister_error_info(&s_crt_swift_error_list)
28+
aws_mqtt_library_clean_up()
2429
aws_event_stream_library_clean_up()
30+
aws_auth_library_clean_up()
31+
2532
}
2633

2734
private init() {}

Source/AwsCommonRuntimeKit/auth/credentials/CredentialsProvider.swift

+84
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@ public protocol CredentialsProviding {
1010
func getCredentials() async throws -> Credentials
1111
}
1212

13+
/// A pair defining an identity provider and a valid login token sourced from it.
14+
public struct CognitoLoginPair: CStruct {
15+
public var IdentityProviderName: String
16+
public var IdentityProviderToken: String
17+
18+
public init(identityProviderName: String,
19+
identityProviderToken: String) {
20+
self.IdentityProviderName = identityProviderName
21+
self.IdentityProviderToken = identityProviderToken
22+
}
23+
24+
typealias RawType = aws_cognito_identity_provider_token_pair
25+
func withCStruct<Result>(_ body: (aws_cognito_identity_provider_token_pair) -> Result) -> Result {
26+
var token_pair = aws_cognito_identity_provider_token_pair()
27+
28+
return withByteCursorFromStrings(IdentityProviderName,
29+
IdentityProviderToken) { identityProviderNameCursor, IdentityProviderTokenCursor in
30+
token_pair.identity_provider_name = identityProviderNameCursor
31+
token_pair.identity_provider_token = IdentityProviderTokenCursor
32+
return body(token_pair)
33+
}
34+
}
35+
}
36+
1337
public class CredentialsProvider: CredentialsProviding {
1438

1539
let rawValue: UnsafeMutablePointer<aws_credentials_provider>
@@ -294,6 +318,7 @@ extension CredentialsProvider.Source {
294318
/// - Throws: CommonRuntimeError.crtError
295319
public static func `defaultChain`(bootstrap: ClientBootstrap,
296320
fileBasedConfiguration: FileBasedConfiguration,
321+
tlsContext: TLSContext? = nil,
297322
shutdownCallback: ShutdownCallback? = nil) -> Self {
298323
Self {
299324
let shutdownCallbackCore = ShutdownCallbackCore(shutdownCallback)
@@ -302,6 +327,7 @@ extension CredentialsProvider.Source {
302327
chainDefaultOptions.bootstrap = bootstrap.rawValue
303328
chainDefaultOptions.profile_collection_cached = fileBasedConfiguration.rawValue
304329
chainDefaultOptions.shutdown_options = shutdownCallbackCore.getRetainedCredentialProviderShutdownOptions()
330+
chainDefaultOptions.tls_ctx = tlsContext?.rawValue
305331

306332
guard let provider = aws_credentials_provider_new_chain_default(allocator.rawValue,
307333
&chainDefaultOptions)
@@ -567,6 +593,64 @@ extension CredentialsProvider.Source {
567593
return provider
568594
}
569595
}
596+
597+
/// Credential Provider that sources credentials from Cognito Identity service
598+
/// - Parameters:
599+
/// - bootstrap: Connection bootstrap to use for any network connections made while sourcing credentials
600+
/// - tlsContext: TLS configuration for secure socket connections.
601+
/// - endpoint: Cognito service regional endpoint to source credentials from.
602+
/// - identity: Cognito identity to fetch credentials relative to.
603+
/// - logins: (Optional) set of identity provider token pairs to allow for authenticated identity access.
604+
/// - customRoleArn: (Optional) ARN of the role to be assumed when multiple roles were received in the token from the identity provider.
605+
/// - proxyOptions: (Optional) Http proxy configuration for the http request that fetches credentials
606+
/// - shutdownCallback: (Optional) shutdown callback
607+
/// - Returns: `CredentialsProvider`
608+
/// - Throws: CommonRuntimeError.crtError
609+
public static func `cognito`(bootstrap: ClientBootstrap,
610+
tlsContext: TLSContext,
611+
endpoint: String,
612+
identity: String,
613+
logins: [CognitoLoginPair] = [],
614+
customRoleArn: String? = nil,
615+
proxyOptions: HTTPProxyOptions? = nil,
616+
shutdownCallback: ShutdownCallback? = nil) -> Self {
617+
Self {
618+
var cognitoOptions = aws_credentials_provider_cognito_options()
619+
cognitoOptions.bootstrap = bootstrap.rawValue
620+
cognitoOptions.tls_ctx = tlsContext.rawValue
621+
let shutdownCallbackCore = ShutdownCallbackCore(shutdownCallback)
622+
cognitoOptions.shutdown_options = shutdownCallbackCore.getRetainedCredentialProviderShutdownOptions()
623+
624+
guard let provider: UnsafeMutablePointer<aws_credentials_provider> = (withByteCursorFromStrings(
625+
endpoint,
626+
identity) { endpointCursor, identityCursor in
627+
628+
cognitoOptions.endpoint = endpointCursor
629+
cognitoOptions.identity = identityCursor
630+
631+
return withOptionalCStructPointer(to: proxyOptions) { proxyOptionsPointer in
632+
cognitoOptions.http_proxy_options = proxyOptionsPointer
633+
634+
return logins.withAWSArrayList { loginArrayPointer in
635+
cognitoOptions.logins = UnsafeMutablePointer<aws_cognito_identity_provider_token_pair>(loginArrayPointer)
636+
cognitoOptions.login_count = logins.count
637+
638+
return withOptionalByteCursorPointerFromString(customRoleArn, { customRoleArnCursor in
639+
if let customRoleArnCursor {
640+
cognitoOptions.custom_role_arn = UnsafeMutablePointer<aws_byte_cursor>(mutating: customRoleArnCursor)
641+
}
642+
return aws_credentials_provider_new_cognito_caching(allocator.rawValue, &cognitoOptions)
643+
})
644+
}
645+
}
646+
})
647+
else {
648+
shutdownCallbackCore.release()
649+
throw CommonRunTimeError.crtError(CRTError.makeFromLastError())
650+
}
651+
return provider
652+
}
653+
}
570654
}
571655

572656
private func onGetCredentials(credentials: OpaquePointer?,

0 commit comments

Comments
 (0)