Skip to content

Commit 7f5fcee

Browse files
authored
Secure Tunnel V2 WebSocket Protocol support (#533)
* Secure Tunnel API Expansion * Secure Tunnel V2 WebSocket Protocol support (Multiplexing)
1 parent 2e96394 commit 7f5fcee

File tree

12 files changed

+1818
-628
lines changed

12 files changed

+1818
-628
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ __Jump To:__
2323
* [FAQ](./documents/FAQ.md)
2424
* [Giving Feedback and Contributions](#Giving-Feedback-and-Contributions)
2525
* [MQTT5 User Guide](./documents/MQTT5_Userguide.md)
26+
* [Secure Tunnel User Guide](./documents/Secure_Tunnel_Userguide.md)
2627

2728

2829
## Installation

crt/aws-crt-cpp

documents/Secure_Tunnel_Userguide.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# Introduction
2+
When devices are deployed behind restricted firewalls at remote sites, you need a way to gain access to those devices for troubleshooting, configuration updates, and other operational tasks. Use secure tunneling to establish bidirectional communication to remote devices over a secure connection that is managed by AWS IoT. Secure tunneling does not require updates to your existing inbound firewall rules, so you can keep the same security level provided by firewall rules at a remote site.
3+
4+
More information on the service and how to open, close, and manage secure tunnels can be found here: https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html
5+
6+
A sample is also provided and can be found here: https://github.com/aws/aws-iot-device-sdk-cpp-v2/tree/main/samples#secure-tunnel
7+
8+
9+
10+
# Getting started with Secure Tunnels
11+
## How to Create a Secure Tunnel Client
12+
Once a Secure Tunnel builder has been created, it is ready to make a Secure Tunnel client. Something important to note is that once a Secure Tunnel client is built and finalized, the configuration is immutable and cannot be changed. Further modifications to the Secure Tunnel builder will not change the settings of already created Secure Tunnel clients.
13+
14+
```cpp
15+
// Create Secure Tunnel Builder
16+
SecureTunnelBuilder builder = SecureTunnelBuilder(...);
17+
18+
// Build Secure Tunnel Client
19+
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();
20+
21+
if (secureTunnel == nullptr)
22+
{
23+
fprintf(stdout, "Secure Tunnel creation failed.\n");
24+
return -1;
25+
}
26+
27+
// Start the secure tunnel connection
28+
if (!secureTunnel->Start())
29+
{
30+
fprintf("Failed to start Secure Tunnel\n");
31+
return -1;
32+
}
33+
```
34+
## Callbacks
35+
36+
### OnConnectionSuccess
37+
When the Secure Tunnel Client successfully connects with the Secure Tunnel service, this callback will return the available (if any) service ids.
38+
39+
### OnConnectionFailure
40+
When a WebSocket upgrade request fails to connect, this callback will return an error code.
41+
42+
### OnConnectionShutdown
43+
When the WebSocket connection shuts down, this callback will be invoked.
44+
45+
### OnSendDataComplete
46+
When a message has been completely written to the socket, this callback will be invoked.
47+
48+
### OnMessageReceived
49+
When a message is received on an open Secure Tunnel stream, this callback will return the message.
50+
51+
### OnStreamStarted
52+
When a stream is started by a Source connected to the Destination, the Destination will invoke this callback and return the stream information.
53+
54+
### OnStreamStopped
55+
When an open stream is closed, this callback will be invoked and return the stopped stream's information.
56+
57+
### OnSessionReset
58+
When the Secure Tunnel service requests the Secure Tunnel client fully reset, this callback is invoked.
59+
60+
### OnStopped
61+
When the Secure Tunnel has reached a fully stopped state this callback is invoked.
62+
63+
## Setting Secure Tunnel Callbacks
64+
The Secure Tunnel client uses callbacks to keep the user updated on its status and pass along relavant information. These can be set up using the Secure Tunnel builder's With functions.
65+
66+
```cpp
67+
// Create Secure Tunnel Builder
68+
SecureTunnelBuilder builder = SecureTunnelBuilder(...);
69+
70+
// Setting the onMessageReceived callback using the builder
71+
builder.WithOnMessageReceived([&](SecureTunnel *secureTunnel, const MessageReceivedEventData &eventData) {
72+
{
73+
std::shared_ptr<Message> message = eventData.message;
74+
if (message->getServiceId().has_value()){
75+
fprintf(
76+
stdout,
77+
"Message received on service id:'" PRInSTR "'\n",
78+
AWS_BYTE_CURSOR_PRI(message->getServiceId().value()));
79+
}
80+
81+
if(message->getPayload().has_value()){
82+
fprintf(
83+
stdout,
84+
"Message has payload:'" PRInSTR "'\n",
85+
AWS_BYTE_CURSOR_PRI(message->getPayload().value()));
86+
}
87+
}
88+
});
89+
90+
// Build Secure Tunnel Client
91+
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();
92+
93+
if (secureTunnel == nullptr)
94+
{
95+
fprintf(stdout, "Secure Tunnel creation failed.\n");
96+
return -1;
97+
}
98+
99+
// Start the secure tunnel connection
100+
if (!secureTunnel->Start())
101+
{
102+
fprintf("Failed to start Secure Tunnel\n");
103+
return -1;
104+
}
105+
106+
// Messages received on a stream will now be printed to stdout.
107+
```
108+
109+
# How to Start and Stop
110+
111+
## Start
112+
Invoking `Start()` on the Secure Tunnel Client will put it into an active state where it recurrently establishes a connection to the configured Secure Tunnel endpoint using the provided [Client Access Token](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling-concepts.html). If a [Client Token](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling-concepts.html) is provided, the Secure Tunnel Client will use it. If a Client Token is not provided, the Secure Tunnel Client will automatically generate one for use on a reconnection attempts. The Client Token for any initial connection to the Secure Tunnel service **MUST** be unique. Reusing a Client Token from a previous connection will result in a failed connection to the Secure Tunnel Service.
113+
```cpp
114+
// Create Secure Tunnel Builder
115+
SecureTunnelBuilder builder = SecureTunnelBuilder(...);
116+
117+
// Adding a client token to the builder
118+
String clientToken;
119+
builder.WithClientToken(clientToken.c_str());
120+
121+
// Build Secure Tunnel Client
122+
std::shared_ptr<SecureTunnel> secureTunnel = builder.Build();
123+
124+
if (secureTunnel == nullptr)
125+
{
126+
fprintf(stdout, "Secure Tunnel creation failed.\n");
127+
return -1;
128+
}
129+
130+
// Start the secure tunnel connection
131+
if (!secureTunnel->Start())
132+
{
133+
fprintf("Failed to start Secure Tunnel\n");
134+
return -1;
135+
}
136+
```
137+
138+
## Stop
139+
Invoking `Stop()` on the Secure Tunnel Client breaks the current connection (if any) and moves the client into an idle state.
140+
```cpp
141+
if(!secureTunnel->Stop()){
142+
fprintf(stdout, "Failed to stop the Secure Tunnel connection session. Exiting..\n");
143+
}
144+
```
145+
146+
# Secure Tunnel Operations
147+
148+
## Send Message
149+
The SendMessage operation takes a description of the Message you wish to send and returns a success/failure in the synchronous logic that kicks off the Send Message operation. When the message is fully written to the socket, the OnSendDataComplete callback will be invoked.
150+
151+
```cpp
152+
Crt::String serviceId_string = "ssh";
153+
Crt::String message_string = "any payload";
154+
155+
ByteCursor serviceId = ByteCursorFromString(serviceId_string);
156+
ByteCursor payload = ByteCursorFromString(message_string);
157+
158+
// Create Message
159+
std::shared_ptr<Message> message = std::make_shared<Message>();
160+
message->withServiceId(serviceId);
161+
message->withPayload(payload);
162+
163+
// Send Message
164+
secureTunnel->SendMessage(message);
165+
```

samples/README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ using a permanent certificate set, replace the paths specified in the `--cert` a
977977
978978
## Secure Tunnel
979979
980-
This sample uses AWS IoT [Secure Tunneling](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html) Service to connect a destination and a source with each other through the AWS Secure Tunnel endpoint using access tokens.
980+
This sample uses AWS IoT [Secure Tunneling](https://docs.aws.amazon.com/iot/latest/developerguide/secure-tunneling.html) Service to connect a destination and a source with each other through the AWS Secure Tunnel endpoint using access tokens using the [V2WebSocketProtocol](https://github.com/aws-samples/aws-iot-securetunneling-localproxy/blob/main/V2WebSocketProtocolGuide.md). [Secure Tunnel Userguide](https://github.com/aws/aws-iot-device-sdk-cpp-v2/blob/main/documents/Secure_Tunnel_Userguide.md)
981981
982982
Source: `samples/secure_tunneling/secure_tunnel`
983983
@@ -986,17 +986,13 @@ Create a new secure tunnel in the AWS IoT console (https://console.aws.amazon.co
986986
Provide the necessary arguments along with the destination access token and start the sample in destination mode (default).
987987
988988
``` sh
989-
./secure_tunnel --endpoint <endpoint> --ca_file <path to root CA>
990-
--cert <path to the certificate> --key <path to the private key>
991-
--thing_name <thing name> --region <region> --access_token_file <path to destination access token>
989+
./secure_tunnel --region <region> --access_token_file <path to destination access token>
992990
```
993991
994992
Provide the necessary arguments along with the source access token and start a second sample in source mode by using the flag --localProxyModeSource.
995993
996994
``` sh
997-
./secure_tunnel --endpoint <endpoint> --ca_file <path to root CA>
998-
--cert <path to the certificate> --key <path to the private key>
999-
--thing_name <thing name> --region <region> --access_token_file <path to source access token>
995+
./secure_tunnel --region <region> --access_token_file <path to source access token>
1000996
--localProxyModeSource
1001997
```
1002998

0 commit comments

Comments
 (0)