Skip to content

Windows support for AWS IoT Client #460

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

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b302e4e
The initial commit with Windows support. It compiles, it starts, it h…
prilepski May 18, 2024
ad0586a
fixed test/code in the following test suites: ConfigTestFixture, Seri…
prilepski May 24, 2024
0c691f4
A fix for emptyMaptoString. AWS SDK initializtion was missing.
prilepski May 28, 2024
c06e132
Changing ThingName to a pointer to allow SharedResourceManager::initi…
prilepski May 28, 2024
551537d
Adding SharedCrtResourceManager::initializeAllocator() call into SetU…
prilepski May 28, 2024
2d5a71e
Converting Aws::Crt::String thingName into a shared_ptr to allow Shar…
prilepski May 28, 2024
6ce35e7
AWS SDK initialization in EmptyTemplateParameters test to address all…
prilepski May 29, 2024
1899c56
Fixes for the oversights after initial Windows version support was te…
prilepski May 29, 2024
413247f
Changes to create default configuration and to get AWS IoT Client sta…
prilepski Jun 3, 2024
946bab6
Merge branch 'basic_win_support' of https://github.com/prilepski/aws-…
prilepski Jun 3, 2024
40ddc29
Initializing the structure to handle no data read from the file case
prilepski Jun 5, 2024
1ef0bf7
Adding proper termination signal handling for Windows
prilepski Jun 5, 2024
8032ead
A fix for reading a file. ReadFromFile needs to expect CLRF in window…
prilepski Jun 5, 2024
738f775
Changes & fixes to support pubsub and SampleShadow file monitoring fu…
prilepski Jun 6, 2024
8f35030
EnvUtils test fixes to use ':' in Linux and ';' in Windows for PATH d…
prilepski Jun 6, 2024
5dba532
Adding persistence of publish-on-change parameter to the configuratio…
prilepski Jun 6, 2024
656e525
Only serializing publish-on-change config parameter if it is set to t…
prilepski Jun 6, 2024
a928d76
Support for Jobs / Remote Actions in Windows. Execute PowerShell inst…
prilepski Jun 6, 2024
adc17c4
Win32 only code cleanup
prilepski Jun 7, 2024
9961dd4
README changes to address Windows compatibility and building steps
prilepski Jun 7, 2024
f10112d
Adding changes specific to configuration under Windows and making set…
prilepski Jun 7, 2024
e656fa0
Changes to default log and configuration file locations for Windows
prilepski Jun 10, 2024
ed89f68
Checked default lock file location for Windows
prilepski Jun 10, 2024
0322b8e
Adding configuration file location for Windows
prilepski Jun 10, 2024
10ccf90
using proper quoations in the path
prilepski Jun 10, 2024
8069e44
Adding Lock file location information for Windows
prilepski Jun 10, 2024
4624c25
Adding information on Windows specific proxy file location
prilepski Jun 10, 2024
f1c2e3f
Adding information on Chmod to Windows permissions mapping
prilepski Jun 10, 2024
087977f
Fixes to address Linux build issues introduced by Windows-specific code
prilepski Jun 12, 2024
673ad1d
Merge branch 'awslabs:main' into basic_win_support
prilepski Jun 12, 2024
cecc109
Coming to a parity on Windows with "Add cli/json parsing to fleet pro…
prilepski Jun 15, 2024
6dd4b36
adding missing return statement after introduction of a windows versi…
prilepski Jun 15, 2024
5021fea
Adding Windows-specific post build steps to copy OpenSSL DLLs to the …
prilepski Jun 20, 2024
70b1287
Merge branch 'basic_win_support' of https://github.com/prilepski/aws-…
prilepski Jun 20, 2024
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
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -15,4 +15,13 @@ docs/latex/
.vscode/

# Mac
.DS_Store
.DS_Store
.vs/VSWorkspaceState.json
.vs/slnx.sqlite
.vs/ProjectSettings.json
.vs/CMake Overview
.vs/cmake.db
.vs/aws-iot-device-client/FileContentIndex/21ee8aa1-3595-428d-9ba2-0211ac531d8f.vsidx
.vs/aws-iot-device-client/v17/.wsuo
.vs/aws-iot-device-client/v17/Browse.VC.db
.vs/aws-iot-device-client/v17/DocumentLayout.json
36 changes: 35 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -16,7 +16,12 @@ option(EXCLUDE_CONFIG_SHADOW "Builds the device client without the IoT Config Sh
option(EXCLUDE_SAMPLE_SHADOW "Builds the device client without the IoT Sample Shadow Feature." OFF)
option(EXCLUDE_SECURE_ELEMENT "Builds the device client without the support for storing/accessing keys stored in a secure module using PKCS#11." ON)
option(EXCLUDE_SENSOR_PUBLISH "Builds the device client without the Sensor Publish over MQTT Feature." OFF)
option(EXCLUDE_SENSOR_PUBLISH_SAMPLES "Builds the device client without the Sensor Publish sample servers." OFF)
if (WIN32)
option(EXCLUDE_SENSOR_PUBLISH_SAMPLES "Builds the device client without the Sensor Publish sample servers." ON)
else()
# Exclude this example from windows version as it uses Linux sockets and needs to be reworked for Window
option(EXCLUDE_SENSOR_PUBLISH_SAMPLES "Builds the device client without the Sensor Publish sample servers." OFF)
endif ()
option(GIT_VERSION "Updates the version number using the Git commit history" ON)

if (EXCLUDE_JOBS)
@@ -71,6 +76,10 @@ if (EXCLUDE_SENSOR_PUBLISH_SAMPLES)
add_definitions(-DEXCLUDE_SENSOR_PUBLISH_SAMPLES)
endif()

if (WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()

list(APPEND CMAKE_MODULE_PATH "./sdk-cpp-workspace/lib/cmake")

file(GLOB CONFIG_SRC "source/config/*.cpp")
@@ -159,6 +168,15 @@ configure_file("source/Version.h.in" "${PROJECT_BINARY_DIR}/Version.h")
set(OPENSSL_USE_STATIC_LIBS TRUE)
find_package(OpenSSL REQUIRED)

#########################################
# Get unistd implementation for Windows #
#########################################
if (WIN32)
file(GLOB ST_WIN32 "source/win32/*.cpp")
list(APPEND DC_SRC ${ST_WIN32})
include_directories("source/win32")
endif ()

#########################################
# AWS IoT v2 SDK C++ dependency #
#########################################
@@ -245,6 +263,22 @@ if (LINK_DL)
target_link_libraries(${DC_PROJECT_NAME} dl)
endif ()

# Copy OpenSSL DLLs on Windows
# Set the output directory for the executable
# Use generator expressions to handle Debug/Release subfolders
if (WIN32)
set(OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE})
# Define a post-build step to copy multiple DLLs
add_custom_command(TARGET ${DC_PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${OPENSSL_INCLUDE_DIR}/../bin/libcrypto-3-x64.dll"
"${OUTPUT_DIRECTORY}/libcrypto-3-x64.dll"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${OPENSSL_INCLUDE_DIR}/../bin/libssl-3-x64.dll"
"${OUTPUT_DIRECTORY}/libssl-3-x64.dll"
)
endif()

if (BUILD_TEST_DEPS)
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.gtest
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@ The modular IoT Device Client consists of a “base client” and discrete “cl
when you onboard a fleet of devices using the [Fleet Provisioning capability](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html) of AWS IoT Core. It creates a device specific certificate and private key, and registers the device on AWS IoT Core.
* The client-side Named Shadows feature enables you to control your IoT device using [AWS IoT Named Shadows](https://docs.aws.amazon.com/iot/latest/developerguide/iot-device-shadows.html). Shadows can store your device's state information and make it available to your device, AWS IoT services, your custom apps and other AWS services whether the device is online and connected to AWS IoT or not.
### List of Supported Platforms
The AWS IoT Device Client is currently compatible with x86_64, aarch64, armv7l, mips32, ppc64, and ppc64le architectures and common Linux software environments (Debian, Ubuntu, and RHEL).
The AWS IoT Device Client is currently compatible with x86_64, aarch64, armv7l, mips32, ppc64, and ppc64le architectures, common Linux software environments (Debian, Ubuntu, and RHEL) and Windows 11.

## Installation
*__Sections:__*
@@ -91,12 +91,14 @@ from our repository [here](https://gallery.ecr.aws/aws-iot-device-client/aws-iot
### Building from source

To use the AWS IoT Device Client, you'll need to compile an executable using the source code provided by this
repository. Below, you'll find instructions for how to build the AWS IoT Device Client for your target machine.
repository. Below, you'll find instructions for how to build the AWS IoT Device Client for your target machine (Note: for Windows use PowerShell)

### Quick Start

The following commands should work for most users when you plan to run the AWS IoT Device Client on the same machine
that you're performing the compilation on:
that you're performing the compilation on.

#### Step 1: Building (Linux and Window)

```
# Building
@@ -106,11 +108,25 @@ mkdir build
cd build
cmake ../
cmake --build . --target aws-iot-device-client
```

#### Step 2: Setup (Linux)
```
# Setup
cd ../
./setup.sh # At this point you'll need to respond to prompts for information, including paths to your thing certs
```

#### Step 2: Setup (Windows)
```
# Setup
cd ../
./setup.ps1 # At this point you'll need to respond to prompts for information, including paths to your thing certs
```

#### Step 3: Run the Client

```
# Run the AWS IoT Device Client
./aws-iot-device-client # This command runs the executable
```
8 changes: 5 additions & 3 deletions docs/CONFIG.md
Original file line number Diff line number Diff line change
@@ -11,9 +11,11 @@ file, or both. For a complete list of available command line arguments, pass `--
Note: Parameters that are passed through the command line take precedence and overwrite any values that may have been written in the JSON configuration file.

To configure the AWS IoT Device Client via the JSON configuration file, you can also modify our configuration template
`config-template.json` located in the root of this package and store it at `~/.aws-iot-device-client/aws-iot-device-client.conf`
where `~/` refers to the home directory of the user running the Device Client. If you'd like to specify a different location
for your configuration file, you can pass the `--config-file <your-path>` flag to the AWS IoT Device Client.
`config-template.json` located in the root of this package and store it at
+ Linux: `~/.aws-iot-device-client/aws-iot-device-client.conf` where `~/` refers to the home directory of the user running the Device Client
+ Windows: `%USERPROFILE%\.aws-iot-device-client/aws-iot-device-client.conf` where `%USERPROFILE%` is an environment variable that contains the path to the profile directory of the user running the Device Client.

If you'd like to specify a different location for your configuration file, you can pass the `--config-file <your-path>` flag to the AWS IoT Device Client.

There are four (4) fields that MUST be passed to the AWS IoT Device Client through some combination of either CLI arguments,
JSON configuration, or both:
2 changes: 1 addition & 1 deletion docs/ENV.md
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ In addition to the application configuration settings described in [Configuring
* Enabling memory allocation tracing has a nontrivial cost and we do not recommend that customers enable this by default for production deployments.

* `LOCK_FILE_PATH`
* To enforce single instance creation, device client writes a file to a specific directory. By default, the device client will write the lockfile to `/run/lock/` and name it "devicecl.lock".
* To enforce single instance creation, device client writes a file to a specific directory. By default, the device client will write the lockfile "devicecl.lock" to `/run/lock/` in Linux or `%LOCALAPPDATA%\aws-iot-device-client\lock\` in Windows.
* To override the default directory, set `LOCK_FILE_PATH` to a writable directory e.g. `LOCK_FILE_PATH=/my/dir/`. Permissions still apply when writing to restricted directories.
* While this should in theory enforce a single instance of device client, double check with `ps` if device client is not starting properly.

11 changes: 9 additions & 2 deletions docs/HTTP_PROXY.md
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ The AWS IoT Device Client initiates the MQTT connection based on the implementat
### Configuring HTTP Proxy via the JSON configuration file
An HTTP Proxy configuration file is a JSON document that uses parameters to describe the proxy options used to interact with AWS IoT.

The default HTTP proxy config file should be placed on your device at `~/.aws-iot-device-client/http-proxy.conf`. AWS IoT Device Client would establish MQTT connect with HTTP proxy **only if the `http-proxy-enabled` flag in the configuration is set to `true`**.
The default HTTP proxy config file should be placed on your device at `~/.aws-iot-device-client/http-proxy.conf` in Linux and `%USERPROFILE%\.aws-iot-device-client/http-proxy.conf` in Windows. AWS IoT Device Client would establish MQTT connect with HTTP proxy **only if the `http-proxy-enabled` flag in the configuration is set to `true`**.
#### Sample HTTP proxy configuration
```
{
@@ -65,11 +65,18 @@ For more information regarding permission recommandations, check out the [permis

### Overriding the default configuration file from command line interface

User can switch between different HTTP proxy config files without modifying the default config. To override the default HTTP proxy config under the file path `~/.aws-iot-device-client/http-proxy.conf`, start the AWS IoT Device Client with the `--http-proxy-config` parameter and the file path of the overriding HTTP proxy config file.
User can switch between different HTTP proxy config files without modifying the default config. To override the default HTTP proxy config under the file path `~/.aws-iot-device-client/http-proxy.conf` in Linux or `%USERPROFILE%\.aws-iot-device-client/aws-iot-device-client.conf` in Windows, start the AWS IoT Device Client with the `--http-proxy-config` parameter and the file path of the overriding HTTP proxy config file.

#### Linux
```
$ ./aws-iot-device-client --http-proxy-config ~/.aws-iot-device-client/MyProxyConfig1.conf
```

#### Windows
```
$ .\aws-iot-device-client --http-proxy-config '%USERPROFILE%\.aws-iot-device-client\MyProxyConfig1.conf'
```

*Note:* User still need to follow the example format of the HTTP proxy configuration file. HTTP proxy will be enabled only if the `http-proxy-enabled` is set to `true`.

*Note:* File and parent folder permissions will also be enforced on the overriding configuration file.
24 changes: 23 additions & 1 deletion docs/PERMISSIONS.md
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@
## File and Directory Permissions
The AWS IoT Device Client requires specific permissions on files and directory storing these files. Please make sure these permissions are applied on files and directories which are created manually by user before starting the Device Client.

*Note: The numbers mentioned bellow are Chmod Permissions for File or Directory*

*Note: The numbers mentioned bellow are Chmod Permissions for File or Directory. In Windows refer to [Linux Chmod to Windows Permissions Mapping](#linux-chmod-to-windows-permissions-mapping).*

#### Recommended and Required permissions on files
File | Chmod Permissions | Required |
@@ -42,6 +43,27 @@ Directory Storing PKCS11 Library File | 700 | **Yes**

*Note: It is worth noting here that files are directories storing these files created by AWS IoT Device Client will have the above mentioned permissions set by default*

### Linux Chmod to Windows Permissions Mapping
For simplicity and corss-compatibility Linux Chmod permissions were mapped to Windows File SEcurity Permissions. The following tables provide the mapping:

#### Classes of Users
Linux | Windows |
-------- |-------- |
user / owner | User under which AWS IoT Device Client is running
group | Local Users group
others | Local Everyone group

#### Access Modes
Linux | Windows |
-------- |-------- |
r / read | Read
w / write | Write
x / execute | Read & Execute


*Note: AWS IoT Device CLient will remove permission inheritance from its files and folders and will always add Full Access for the local Administrators group.*


**Next**: [Environment Variables](ENV.md)

[*Back To The Top*](#permissions)
20 changes: 20 additions & 0 deletions docs/SETUP.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@

## Setting Up The Device Client

### Setting Up On Linux
This package comes with an interactive script for setting up the Device Client. This script can be used to generate
initial Device Client configuration, as well as setup the Device Client as a service.

@@ -30,6 +31,25 @@ By default, this will be `~/.aws-iot-device-client/aws-iot-device-client.conf` o

*Note: The Jobs and Secure Tunneling features are **enabled** by default, while all other Device Client features are **disabled** by default. You can use the JSON config file and/or CLI options to enable/disable any of these features.*

### Setting Up On Windows
This package comes with an interactive PowerShell script for setting up the Device Client. This script can be used to generate
initial Device Client configuration in the similar way as it is done for Linux. However, setting up Device Client as Windows Service is not supported at the moment.

To use the script, run the following command.

```
./setup.ps1
```

You should also make sure to run the script as Administrator or as a user with enough permissions to set / change file and folder security settings. The script will also ask you to provide a username under which you are planning to run AWS IoT Device Client. The script will use provided account to setup AWS IoT Device Client's file and folder permissions appropriately (refer to [Permissions Page][PERMISSIONS.md]).

After completing the prompts, check if the config file exists in the proper directory.
By default, this will be `%USERPROFILE%/.aws-iot-device-client/aws-iot-device-client.conf` (Note, it will the the %USERPROFILE% of the provided user account or the current user if none provided).

*Note: The Jobs and Secure Tunneling features are **enabled** by default, while all other Device Client features are **disabled** by default. You can use the JSON config file and/or CLI options to enable/disable any of these features.*

### Additional / Other Settings

You can use the following command to see all of the CLI options available for the Device Client

```
21 changes: 21 additions & 0 deletions sample-job-docs/win32/download-file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"_comment": "This sample JSON file can be used for downloading specific file from cloud storage. The arguments passed here in `steps`->`action`->`args` are valid file URL and path where we want to store the downloaded file on the device.",
"version": "1.0",
"steps": [
{
"action": {
"name": "Download File",
"type": "runHandler",
"input": {
"handler": "download-file.ps1",
"args": [
"https://github.com/awslabs/aws-iot-device-client/archive/refs/tags/v1.3.tar.gz",
"C:\\tmp\\Downloaded_File.tar.gz"
],
"path": "default"
},
"runAsUser": "root"
}
}
]
}
18 changes: 18 additions & 0 deletions sample-job-docs/win32/echo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"_comment": "This sample JSON file can be used for running the echo command on the device side.",
"version": "1.0",
"steps": [
{
"action": {
"name": "Echo Messages",
"type": "runHandler",
"input": {
"handler": "echo",
"args": [
"Hello IoT World!"
]
}
}
}
]
}
19 changes: 19 additions & 0 deletions sample-job-docs/win32/health-check.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"_comment": "This sample JSON file can be used to check device responsiveness to Jobs",
"version": "1.0",
"steps": [
{
"action": {
"name": "Health Check",
"type": "runHandler",
"input": {
"handler": "health-check.ps1",
"args": [
],
"path": "default"
},
"runAsUser": "root"
}
}
]
}
16 changes: 16 additions & 0 deletions sample-job-docs/win32/run-shellcommand.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"_comment": "This sample JSON file can be used for creating a new directory newDir at the current filepath.",
"version": "1.0",
"steps": [
{
"action": {
"name": "Create New Directory",
"type": "runCommand",
"input": {
"command": "mkdir,newDir"
},
"runAsUser": "root"
}
}
]
}
18 changes: 18 additions & 0 deletions sample-job-handlers/win32/download-file.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Capture parameters
$user = $args[0]
$fileUrl = $args[1]
$outputFile = $args[2]

$ErrorActionPreference = "Stop"

Write-Host ("Username (ignored in Windows): " + $user)
Write-Host ("File URL: $fileUrl")
Write-Host ("Write documents to file: $outputFile")

# Check target folder and create it if missing
$outputPath = Split-Path -Path $outputFile -Parent
if (-Not (Test-Path $outputPath)) {
New-Item -Path $outputPath -ItemType Directory -Force | Out-Null
}

Invoke-WebRequest -Uri $fileUrl -OutFile $outputFile
7 changes: 7 additions & 0 deletions sample-job-handlers/win32/health-check.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This handler simply exits 0 so that the simplest possible Job may be run to confirm the devices connectivity and ability
# to process Jobs.
# Set error action preference to stop on any error
$ErrorActionPreference = "Stop"

# Exit the script with a status code of 0
exit 0
Loading