diff --git a/.github/workflows/aws-service-sanity-check.yml b/.github/workflows/aws-service-sanity-check.yml new file mode 100644 index 00000000..30904a41 --- /dev/null +++ b/.github/workflows/aws-service-sanity-check.yml @@ -0,0 +1,38 @@ +name: Main Branch Checks +permissions: + contents: read + +on: + push: + branches-ignore: + - 'main' + - 'docs' + +jobs: + verify-documentation-links: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Verify documentation files and links + # check if the files exists in the repository. The file list is in utils/doc-links.txt. + run: | + missing=0 + while read -r file || [ -n "$file" ]; do + if [ ! -f "$file" ]; then + if [ $missing -eq 0 ]; then + echo "❌ Missing files referenced in AWS documentation:" + missing=$((missing + 1)) + fi + echo " - $file" + fi + done < utils/ci-aws-doc-links.txt + + if [ $missing -ge 1 ]; then + echo "Instructions:" + echo " The above files are required for AWS services or documentations." + echo " Restore missing files or update documentation before merge." + echo " Refer to team wiki "AWS Service and Documentation Links" for details. " + exit 1 + else + echo "✅ All documentation-referenced files exist" + fi \ No newline at end of file diff --git a/documents/FAQ.md b/documents/FAQ.md index a91b66d8..5bb2589e 100644 --- a/documents/FAQ.md +++ b/documents/FAQ.md @@ -14,7 +14,7 @@ ### Where should I start? -If you are just getting started make sure you [install this sdk](https://github.com/aws/aws-iot-device-sdk-java-v2#installation) and then build and run the [basic PubSub](https://github.com/aws/aws-iot-device-sdk-java-v2/tree/main/samples#pubsub) +If you are just getting started make sure you [install this sdk](https://github.com/aws/aws-iot-device-sdk-java-v2#installation) and then build and run the [Mqtt5 X509 Sample](https://github.com/aws/aws-iot-device-sdk-java-v2/tree/main/samples/Mqtt/Mqtt5X509) ### How do I enable logging? @@ -32,10 +32,10 @@ To enable logging in the samples, you will need to set the following system prop * `aws.crt.log.level`: The level of logging shown. Can be `Trace`, `Debug`, `Info`, `Warn`, `Error`, `Fatal`, or `None`. Defaults to `Warn`. * `aws.crt.log.filename`: The path to save the log file. Only needed if `aws.crt.log.destination` is set to `File`. -For example, to run `BasicPubSub` with logging you could use the following: +For example, to run `Mqtt X509` with logging you could use the following: ```sh -mvn compile exec:java -pl samples/Mqtt/Mqtt5X509 -Daws.crt.debugnative=true -Daws.crt.log.level=Debug -Daws.crt.log.destionation=Stdout -Dexec.mainClass=pubsub.PubSub -Dexec.args='--endpoint --cert --key ' +mvn compile exec:java -pl samples/Mqtt/Mqtt5X509 -Daws.crt.debugnative=true -Daws.crt.log.level=Debug -Daws.crt.log.destionation=Stdout -Dexec.args='--endpoint --cert --key ' ``` You can also enable [CloudWatch logging](https://docs.aws.amazon.com/iot/latest/developerguide/cloud-watch-logs.html) for IoT which will provide you with additional information that is not available on the client side sdk. diff --git a/documents/MIGRATION_GUIDE.md b/documents/MIGRATION_GUIDE.md index a17d6888..b83a6d9c 100644 --- a/documents/MIGRATION_GUIDE.md +++ b/documents/MIGRATION_GUIDE.md @@ -905,8 +905,8 @@ samples. ### Example It's always helpful to look at a working example to see how new functionality works, to be able to tweak different options, -to compare with existing code. For that reason, we implemented a [Publish/Subscribe example](https://github.com/aws/aws-iot-device-sdk-java-v2/tree/main/samples/Mqtt5/PubSub) -([source code](https://github.com/aws/aws-iot-device-sdk-java-v2/blob/main/samples/Mqtt5/PubSub/src/main/java/pubsub/PubSub.java)) +to compare with existing code. For that reason, we implemented a [Publish/Subscribe example](https://github.com/aws/aws-iot-device-sdk-java-v2/tree/main/samples/Mqtt/Mqtt5X509) +([source code](https://github.com/aws/aws-iot-device-sdk-java-v2/blob/main/samples/Mqtt/Mqtt5X509/src/main/java/mqtt5x509/Mqtt5X509.java)) in the V2 SDK similar to a sample provided by V1 SDK (see a corresponding [readme section](https://github.com/aws/aws-iot-device-sdk-java/tree/master?tab=readme-ov-file#sample-applications) and [source code](https://github.com/aws/aws-iot-device-sdk-java/blob/master/aws-iot-device-sdk-java-samples/src/main/java/com/amazonaws/services/iot/client/sample/pubSub/PublishSubscribeSample.java)). diff --git a/pom.xml b/pom.xml index d8dd14a6..0ddbeacb 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,6 @@ sdk - samples/BasicPubSub samples/Mqtt/Mqtt5X509 samples/Mqtt/Mqtt5AwsWebsocket samples/Mqtt/Mqtt5CustomAuthSigned diff --git a/samples/BasicPubSub/README.md b/samples/BasicPubSub/README.md deleted file mode 100644 index af3d8ee1..00000000 --- a/samples/BasicPubSub/README.md +++ /dev/null @@ -1,373 +0,0 @@ -# MQTT5 PubSub - -[**Return to main sample list**](../../README.md) - -This sample uses the -[Message Broker](https://docs.aws.amazon.com/iot/latest/developerguide/iot-message-broker.html) -for AWS IoT to send and receive messages through an MQTT connection using MQTT5. - -MQTT5 introduces additional features and enhancements that improve the development experience with MQTT. You can read more about MQTT5 in the Java V2 SDK by checking out the [MQTT5 user guide](../../../documents/MQTT5_Userguide.md). - -Your IoT Core Thing's [Policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must provide privileges for this sample to connect, subscribe, publish, and receive. Below is a sample policy that can be used on your IoT Core Thing that will allow this sample to run as intended. - -
-(see sample policy) -
-{
-  "Version": "2012-10-17",
-  "Statement": [
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Publish",
-        "iot:Receive"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topic/test/topic"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Subscribe"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:topicfilter/test/topic"
-      ]
-    },
-    {
-      "Effect": "Allow",
-      "Action": [
-        "iot:Connect"
-      ],
-      "Resource": [
-        "arn:aws:iot:region:account:client/test-*"
-      ]
-    }
-  ]
-}
-
- -Replace with the following with the data from your AWS account: -* ``: The AWS IoT Core region where you created your AWS IoT Core thing you wish to use with this sample. For example `us-east-1`. -* ``: Your AWS IoT Core account ID. This is the set of numbers in the top right next to your AWS account name when using the AWS IoT Core website. -* ``: The name of your AWS IoT Core thing you want the device connection to be associated with - -Note that in a real application, you may want to avoid the use of wildcards in your ClientID or use them selectively. Please follow best practices when working with AWS on production applications using the SDK. Also, for the purposes of this sample, please make sure your policy allows a client ID of `test-*` to connect or use `--client_id ` to send the client ID your policy supports. - -
- -## How to run - -### Direct MQTT via mTLS - -To Run this sample using a direct MQTT connection with a key and certificate, use the following command: - -```sh -mvn compile exec:java -pl samples/Mqtt5/PubSub -Dexec.mainClass=mqtt5.pubsub.PubSub -Dexec.args='--endpoint --cert --key ' -``` - -You can also pass a Certificate Authority file (CA) if your certificate and key combination requires it: - -```sh -mvn compile exec:java -pl samples/Mqtt5/PubSub -Dexec.mainClass=mqtt5.pubsub.PubSub -Dexec.args='--endpoint --cert --key --ca_file ' -``` -### Websockets - -To Run this sample using Websockets, use the following command: -```sh -mvn compile exec:java -pl samples/Mqtt5/PubSub -Dexec.mainClass=mqtt5.pubsub.PubSub -Dexec.args='--endpoint --signing_region ' -``` - -Note that to run this sample using Websockets, you will need to set your AWS credentials in your environment variables or local files. See the [authorizing direct AWS](https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html) page for documentation on how to get the AWS credentials, which then you can set to the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` environment variables. - -## Alternate Connection Configuration Methods supported by AWS IoT Core - -All MQTT5 clients should be created using a MQTT5 client builder. A MQTT5 client builder is a factory of sorts for making MQTT5 clients, where you setup the builder and then can create fully configured MQTT5 clients from the settings setup in the builder. The Java SDK provides an easy to use builder designed to make it as easy as possible to get a configuration for common configuration types, like direct MQTT connections and websockets. Each configuration has various levels of flexibility and requirements in the information needed to authenticate a connection with AWS IoT Core. While MQTT5 clients can be created without the use of a MQTT5 client builder, it is strongly recommended to use a MQTT5 client builder when connecting to AWS IoT Core. - -### Authentication Methods - -* [Direct MQTT with X509-based Mutual TLS Method](#direct-mqtt-with-x509-based-mutual-tls-method) -* [Direct MQTT with Custom Authorizer Method](#direct-mqtt-with-custom-authorizer-method) -* [Direct MQTT with PKCS11 Method](#direct-mqtt-with-pkcs11-method) -* [Direct MQTT with PKCS12 Method](#direct-mqtt-with-pkcs12-method) -* [Direct MQTT with Custom Key Operations Method](#direct-mqtt-with-custom-key-operation-method) -* [Direct MQTT with Windows Certificate Store Method](#direct-mqtt-with-windows-certificate-store-method) -* [Direct MQTT with Java Keystore Method](#direct-mqtt-with-java-keystore-method) -* [Websocket Connection with Sigv4 Authentication Method](#websocket-connection-with-sigv4-authentication-method) -* [Websocket Connection with Cognito Authentication Method](#websocket-connection-with-cognito-authentication-method) -### HTTP Proxy -* [Adding an HTTP Proxy](#adding-an-http-proxy) - -### **Direct MQTT with X509-based Mutual TLS Method** -A direct MQTT5 connection requires a valid endpoint, a client certificate in X.509 format, and a PEM encoded private key. To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromPath(clientEndpoint, "", ""); -~~~ - -You can also create a client where the certificate and private key are in memory: - -~~~ java -// Credit: https://stackoverflow.com/a/326440 -static String readFile(String path, Charset encoding) - throws IOException -{ - byte[] encoded = Files.readAllBytes(Paths.get(path)); - return new String(encoded, encoding); -} - -String clientEndpoint = "-ats.iot..amazonaws.com"; -String certificateData = readFile("", StandardCharsets.UTF_8); -String keyData = readFile("", StandardCharsets.UTF_8); -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromMemory(clientEndpoint, certificateData, keyData); -~~~ - -### **Direct MQTT with Custom Authorizer Method** - -A MQTT5 direct connection can be made using a [Custom Authorizer](https://docs.aws.amazon.com/iot/latest/developerguide/custom-authentication.html) rather than a certificate and key file like in the Direct Connection section above. Instead of using Mutual TLS to connect, a Custom Authorizer can be invoked instead and used to authorize the connection. When making a connection using a Custom Authorizer, the MQTT5 client can optionally passing username, password, and/or token signature arguments based on the configuration of the Custom Authorizer on AWS IoT Core. - -You will need to setup your Custom Authorizer so that the lambda function returns a policy document to properly connect. See [this page on the documentation](https://docs.aws.amazon.com/iot/latest/developerguide/config-custom-auth.html) for more details and example return results. - -If your Custom Authorizer does not use signing, you don't specify anything related to the token signature and can use the following code: - -~~~ java -AwsIotMqtt5ClientBuilder.MqttConnectCustomAuthConfig customAuthConfig = new AwsIotMqtt5ClientBuilder.MqttConnectCustomAuthConfig(); -customAuthConfig.authorizerName = ""; -customAuthConfig.username = ""; -customAuthConfig.password = "".getBytes(); - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithCustomAuth(clientEndpoint, customAuthConfig); -~~~ - -If your custom authorizer uses signing, you must specify the three signed token properties as well. It is your responsibility to URI-encode the username, authorizerName, and tokenKeyName parameters. - -~~~ java -AwsIotMqtt5ClientBuilder.MqttConnectCustomAuthConfig customAuthConfig = new AwsIotMqtt5ClientBuilder.MqttConnectCustomAuthConfig(); -customAuthConfig.authorizerName = ""; -customAuthConfig.username = ""; -customAuthConfig.password = "".getBytes(); -customAuthConfig.tokenValue = ""; -customAuthConfig.tokenKeyName = ""; -customAuthConfig.tokenSignature = ""; - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithCustomAuth(clientEndpoint, customAuthConfig); -~~~ - -In both cases, the builder will construct a final CONNECT packet username field value for you based on the values configured. Do not add the token-signing fields to the value of the username that you assign within the custom authentication config structure. Similarly, do not add any custom authentication related values to the username in the CONNECT configuration optionally attached to the client configuration. The builder will do everything for you. - -### **Direct MQTT with PKCS11 Method** - -A MQTT5 direct connection can be made using a PKCS11 device rather than using a PEM encoded private key, the private key for mutual TLS is stored on a PKCS#11 compatible smart card or Hardware Security Module (HSM). To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java - -Pkcs11Lib pkcs11Lib = new Pkcs11Lib(""); -TlsContextPkcs11Options pkcs11Options = new TlsContextPkcs11Options(pkcs11Lib)) { -pkcs11Options.withCertificateFilePath(""); -pkcs11Options.withUserPin(""); - -// Pass arguments to help find the correct PKCS#11 token, -// and the private key on that token. You don't need to pass -// any of these arguments if your PKCS#11 device only has one -// token, or the token only has one private key. But if there -// are multiple tokens, or multiple keys to choose from, you -// must narrow down which one should be used. -/* -if (pkcs11TokenLabel != null && pkcs11TokenLabel != "") { - pkcs11Options.withTokenLabel(pkcs11TokenLabel); -} -if (pkcs11SlotId != null) { - pkcs11Options.withSlotId(pkcs11SlotId); -} -if (pkcs11KeyLabel != null && pkcs11KeyLabel != "") { - pkcs11Options.withPrivateKeyObjectLabel(pkcs11KeyLabel); -} -*/ - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromPkcs11(clientEndpoint, pkcs11Options); -~~~ - -**Note**: Currently, TLS integration with PKCS#11 is only available on Unix devices. - -### **Direct MQTT with PKCS12 Method** - -A MQTT5 direct connection can be made using a PKCS12 file rather than using a PEM encoded private key. To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromPkcs12(clientEndpoint, "", ""); -~~~ - -**Note**: Currently, TLS integration with PKCS12 is only available on MacOS devices. - -### **Direct MQTT with Custom Key Operation Method** - -A MQTT5 direct connection can be made with a set of custom private key operations during the mutual TLS handshake. This is necessary if you require an external library to handle private key operations such as signing and decrypting. To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java -class MyKeyOperationHandler implements TlsKeyOperationHandler { - - // Implement based on the operation. See CustomKeyOpsConnect sample for example - public void performOperation(TlsKeyOperation operation) { - try { - throw new RuntimeException("This is just an example!"); - } catch (Exception ex) { - operation.completeExceptionally(ex); - } - } -} - -MyKeyOperationHandler myKeyOperationHandler = new MyKeyOperationHandler(); -TlsContextCustomKeyOperationOptions keyOperationOptions = new TlsContextCustomKeyOperationOptions(myKeyOperationHandler); -keyOperationOptions.withCertificateFilePath(""); - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMtlsCustomKeyOperationsBuilder(clientEndpoint, keyOperationOptions) -~~~ - -**Note**: Currently, Custom Key Operation support is only available on Linux devices. - -### **Direct MQTT with Windows Certificate Store Method** - -A MQTT5 direct connection can be made with mutual TLS with the certificate and private key in the [Windows certificate store](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/certificate-stores), rather than simply being files on disk. To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java -// Certificate store path below is an example. See WindowsCert Connect sample for more info -String certificateStorePath = "CurrentUser\\MY\\A11F8A9B5DF5B98BA3508FBCA575D09570E0D2C6" -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromWindowsCertStorePath(clientEndpoint, certificateStorePath) -~~~ - -**Note**: Windows Certificate Store connection support is only available on Windows devices. - -### **Direct MQTT with Java Keystore Method** - -A MQTT5 direct connection can be made with mutual TLS using the certificate and private key in a Java Keystore file. - -To use the certificate and key files provided by AWS IoT Core, you will need to convert them into PKCS12 format and then import them into your Java keystore. You can convert the certificate and key file to PKCS12 using the following command: - -```sh -openssl pkcs12 -export -in -inkey -out my-pkcs12-key.p12 -name -password pass: -``` - -Once you have a PKCS12 certificate and key, you can import it into a Java keystore using the following: - -```sh -keytool -importkeystore -srckeystore my-pkcs12-key.p12 -destkeystore -srcstoretype pkcs12 -alias -srcstorepass -deststorepass -``` - -With those steps completed and the PKCS12 key in the Java keystore, you can use the following code to load the certificate and private key from the Java keystore in the Java V2 SDK: - -~~~ java -java.security.KeyStore keyStore; -try { - keyStore = java.security.KeyStore.getInstance("PKCS12"); -} catch (java.security.KeyStoreException ex) { - throw new CrtRuntimeException("Could not get instance of Java keystore with format PKCS12"); -} - -String keyStorePath = "destination_keystore.keys"; -String keyStorePassword = "keystore_password"; - -try (java.io.FileInputStream fileInputStream = new java.io.FileInputStream(keyStorePath)) { - keyStore.load(fileInputStream, keyStorePassword.toCharArray()); -} catch (java.io.FileNotFoundException ex) { - throw new CrtRuntimeException("Could not open Java keystore file"); -} catch (java.io.IOException | java.security.NoSuchAlgorithmException | java.security.cert.CertificateException ex) { - throw new CrtRuntimeException("Could not load Java keystore"); -} - -String keyStoreCertificateAlias = "certificate_alias"; -String keyStoreCertificatePassword = "PKCS12_password"; - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithJavaKeystore(clientEndpoint, keyStore, keyStoreCertificateAlias, keyStoreCertificatePassword) -~~~ - -### **Websocket Connection with Sigv4 Authentication Method** - -Sigv4-based authentication requires a credentials provider capable of sourcing valid AWS credentials. Sourced credentials will sign the websocket upgrade request made by the client while connecting. The default credentials provider chain supported by the SDK is capable of resolving credentials in a variety of environments according to a chain of priorities: - -~~~ -Environment -> Profile (local file system) -> STS Web Identity -> IMDS (ec2) or ECS -~~~ - -If the default credentials provider chain and built-in AWS region extraction logic are sufficient, you do not need to specify any additional configuration and can use the following code: - -~~~ java -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newWebsocketMqttBuilderWithSigv4Auth(clientEndpoint, null); -~~~ - -See the [authorizing direct AWS](https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html) page for documentation on how to get the AWS credentials, which then can be set to the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS`, and `AWS_SESSION_TOKEN` environment variables prior to running the application. - -Alternatively, if you're connecting to a special region for which standard pattern matching does not work, or if you need a specific credentials provider, you can specify advanced websocket configuration options using the following code: - -~~~ java -WebsocketSigv4Config websocketConfig = new WebsocketSigv4Config(); -websocketConfig.region = "us-east-1"; -DefaultChainCredentialsProvider.DefaultChainCredentialsProviderBuilder providerBuilder = new DefaultChainCredentialsProvider.DefaultChainCredentialsProviderBuilder(); -providerBuilder.withClientBootstrap(ClientBootstrap.getOrCreateStaticDefault()); -websocketConfig.credentialsProvider = providerBuilder.build(); - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newWebsocketMqttBuilderWithSigv4Auth(clientEndpoint, websocketConfig); -~~~ - -### **Websocket Connection with Cognito Authentication Method** - -A MQTT5 websocket connection can be made using Cognito to authenticate rather than the AWS credentials located on the device or via key and certificate. Instead, Cognito can authenticate the connection using a valid Cognito identity ID. This requires a valid Cognito identity ID, which can be retrieved from a Cognito identity pool. A Cognito identity pool can be created from the AWS console. - -To create a MQTT5 builder configured for this connection, see the following code: - -~~~ java -WebsocketSigv4Config websocketConfig = new WebsocketSigv4Config(); - -CognitoCredentialsProvider.CognitoCredentialsProviderBuilder cognitoBuilder = new CognitoCredentialsProvider.CognitoCredentialsProviderBuilder(); -// See https://docs.aws.amazon.com/general/latest/gr/cognito_identity.html for Cognito endpoints -String cognitoEndpoint = "cognito-identity..amazonaws.com"; -cognitoBuilder.withEndpoint(cognitoEndpoint).withIdentity(""); -cognitoBuilder.withClientBootstrap(ClientBootstrap.getOrCreateStaticDefault()); -TlsContextOptions cognitoTlsContextOptions = TlsContextOptions.createDefaultClient(); -ClientTlsContext cognitoTlsContext = new ClientTlsContext(cognitoTlsContextOptions); -cognitoTlsContextOptions.close(); -cognitoBuilder.withTlsContext(cognitoTlsContext); -websocketConfig.credentialsProvider = cognitoBuilder.build(); - -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newWebsocketMqttBuilderWithSigv4Auth(clientEndpoint, websocketConfig); -~~~ - -**Note**: A Cognito identity ID is different from a Cognito identity pool ID and trying to connect with a Cognito identity pool ID will not work. If you are unable to connect, make sure you are passing a Cognito identity ID rather than a Cognito identity pool ID. - -## **Adding an HTTP Proxy** - -No matter what your connection transport or authentication method is, you may connect through an HTTP proxy by applying proxy configuration to the builder using the following code: - -~~~ java -String clientEndpoint = "-ats.iot..amazonaws.com"; -AwsIotMqtt5ClientBuilder builder = AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromPath(clientEndpoint, "", ""); - -HttpProxyOptions proxyOptions = new HttpProxyOptions(); -proxyOptions.setHost(""); -proxyOptions.setPort(); -builder.withHttpProxyOptions(proxyOptions); -~~~ - -SDK Proxy support also includes support for basic authentication and TLS-to-proxy. SDK proxy support does not include any additional proxy authentication methods (kerberos, NTLM, etc...) nor does it include non-HTTP proxies (SOCKS5, for example). - -## ⚠️ Usage disclaimer - -These code examples interact with services that may incur charges to your AWS account. For more information, see [AWS Pricing](https://aws.amazon.com/pricing/). - -Additionally, example code might theoretically modify or delete existing AWS resources. As a matter of due diligence, do the following: - -- Be aware of the resources that these examples create or delete. -- Be aware of the costs that might be charged to your account as a result. -- Back up your important data. diff --git a/samples/BasicPubSub/pom.xml b/samples/BasicPubSub/pom.xml deleted file mode 100644 index 8b6a8e57..00000000 --- a/samples/BasicPubSub/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - 4.0.0 - software.amazon.awssdk.iotdevicesdk - BasicPubSub - jar - 1.0-SNAPSHOT - ${project.groupId}:${project.artifactId} - Java bindings for the AWS IoT Core Service - https://github.com/awslabs/aws-iot-device-sdk-java-v2 - - 1.8 - 1.8 - UTF-8 - - - - software.amazon.awssdk.iotdevicesdk - aws-iot-device-sdk - 1.0.0-SNAPSHOT - - - commons-cli - commons-cli - 1.9.0 - - - - - latest-release - - - software.amazon.awssdk.iotdevicesdk - aws-iot-device-sdk - 1.27.4 - - - - - default - - true - - - - software.amazon.awssdk.iotdevicesdk - aws-iot-device-sdk - 1.0.0-SNAPSHOT - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.4.0 - - pubsub.PubSub - - - - - diff --git a/samples/BasicPubSub/src/main/java/pubsub/PubSub.java b/samples/BasicPubSub/src/main/java/pubsub/PubSub.java deleted file mode 100644 index 72a21eae..00000000 --- a/samples/BasicPubSub/src/main/java/pubsub/PubSub.java +++ /dev/null @@ -1,304 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -package pubsub; - -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import software.amazon.awssdk.crt.CRT; -import software.amazon.awssdk.crt.CrtResource; -import software.amazon.awssdk.crt.CrtRuntimeException; -import software.amazon.awssdk.crt.io.ClientBootstrap; -import software.amazon.awssdk.crt.mqtt5.*; -import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.LifecycleEvents; -import software.amazon.awssdk.crt.mqtt5.packets.*; -import software.amazon.awssdk.iot.AwsIotMqtt5ClientBuilder; - -public class PubSub { - - static void onApplicationFailure(Throwable cause) { - throw new RuntimeException("Mqtt5 PubSub: execution failure", cause); - } - - static final class SampleLifecycleEvents - implements Mqtt5ClientOptions.LifecycleEvents { - CompletableFuture connectedFuture = new CompletableFuture<>(); - CompletableFuture stoppedFuture = new CompletableFuture<>(); - - @Override - public void - onAttemptingConnect(Mqtt5Client client, - OnAttemptingConnectReturn onAttemptingConnectReturn) { - System.out.println("Mqtt5 Client: Attempting connection..."); - } - - @Override - public void - onConnectionSuccess(Mqtt5Client client, - OnConnectionSuccessReturn onConnectionSuccessReturn) { - System.out.println("Mqtt5 Client: Connection success, client ID: " + - onConnectionSuccessReturn.getNegotiatedSettings() - .getAssignedClientID()); - connectedFuture.complete(null); - } - - @Override - public void - onConnectionFailure(Mqtt5Client client, - OnConnectionFailureReturn onConnectionFailureReturn) { - String errorString = - CRT.awsErrorString(onConnectionFailureReturn.getErrorCode()); - System.out.println("Mqtt5 Client: Connection failed with error: " + - errorString); - connectedFuture.completeExceptionally( - new Exception("Could not connect: " + errorString)); - } - - @Override - public void onDisconnection(Mqtt5Client client, - OnDisconnectionReturn onDisconnectionReturn) { - System.out.println("Mqtt5 Client: Disconnected"); - DisconnectPacket disconnectPacket = - onDisconnectionReturn.getDisconnectPacket(); - if (disconnectPacket != null) { - System.out.println("\tDisconnection packet code: " + - disconnectPacket.getReasonCode()); - System.out.println("\tDisconnection packet reason: " + - disconnectPacket.getReasonString()); - } - } - - @Override - public void onStopped(Mqtt5Client client, OnStoppedReturn onStoppedReturn) { - System.out.println("Mqtt5 Client: Stopped"); - stoppedFuture.complete(null); - } - } - - static final class SamplePublishEvents - implements Mqtt5ClientOptions.PublishEvents { - CountDownLatch messagesReceived; - - SamplePublishEvents(int messageCount) { - messagesReceived = new CountDownLatch(messageCount); - } - - @Override - public void onMessageReceived(Mqtt5Client client, - PublishReturn publishReturn) { - PublishPacket publishPacket = publishReturn.getPublishPacket(); - - System.out.println("Publish received on topic: " + - publishPacket.getTopic()); - System.out.println("Message: " + new String(publishPacket.getPayload())); - - List packetProperties = publishPacket.getUserProperties(); - if (packetProperties != null) { - for (int i = 0; i < packetProperties.size(); i++) { - UserProperty property = packetProperties.get(i); - System.out.println("\twith UserProperty: (" + property.key + ", " + - property.value + ")"); - } - } - - messagesReceived.countDown(); - } - } - - public static void main(String[] args) { - Options cliOptions = new Options(); - cliOptions.addOption(Option.builder("e") - .longOpt("endpoint") - .desc("AWS IoT endpoint to connect to") - .hasArg() - .required() - .build()); - cliOptions.addOption(Option.builder("c") - .longOpt("cert") - .desc("file path to X509 certificate") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("k") - .longOpt("key") - .desc("file path to X509 private key") - .hasArg() - .build()); - cliOptions.addOption(Option.builder() - .longOpt("ca_file") - .desc("file path to root CA certificate") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("i") - .longOpt("client_id") - .desc("MQTT client ID") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("t") - .longOpt("topic") - .desc("MQTT topic") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("m") - .longOpt("message") - .desc("message to publish") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("n") - .longOpt("count") - .desc("number of messages to send") - .hasArg() - .build()); - cliOptions.addOption(Option.builder("r") - .longOpt("region") - .desc("AWS region for WebSocket") - .hasArg() - .build()); - cliOptions.addOption( - Option.builder("h").longOpt("help").desc("prints help").build()); - - CommandLineParser parser = new DefaultParser(); - CommandLine commandLine; - try { - commandLine = parser.parse(cliOptions, args); - } catch (Exception e) { - System.err.println("Error parsing arguments: " + e.getMessage()); - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("PubSub", cliOptions); - return; - } - - if (commandLine.hasOption("help")) { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("PubSub", cliOptions); - return; - } - - String endpoint = commandLine.getOptionValue("endpoint"); - String certPath = commandLine.getOptionValue("cert", ""); - String keyPath = commandLine.getOptionValue("key", ""); - String caFile = commandLine.getOptionValue("ca_file", ""); - String clientId = commandLine.getOptionValue("client_id", "test-client"); - String topic = commandLine.getOptionValue("topic", "test/topic"); - String message = commandLine.getOptionValue("message", "Hello World"); - int messageCount = - Integer.parseInt(commandLine.getOptionValue("count", "10")); - String signingRegion = commandLine.getOptionValue("region", "us-east-1"); - - try { - SampleLifecycleEvents lifecycleEvents = new SampleLifecycleEvents(); - SamplePublishEvents publishEvents = new SamplePublishEvents(messageCount); - Mqtt5Client client; - - /** - * Create the MQTT connection from the builder - */ - if (!certPath.isEmpty() || !keyPath.isEmpty()) { - AwsIotMqtt5ClientBuilder builder = - AwsIotMqtt5ClientBuilder.newDirectMqttBuilderWithMtlsFromPath( - endpoint, certPath, keyPath); - - if (!caFile.isEmpty()) { - builder.withCertificateAuthorityFromPath(null, caFile); - } - - ConnectPacket.ConnectPacketBuilder connectProperties = - new ConnectPacket.ConnectPacketBuilder(); - connectProperties.withClientId(clientId); - builder.withConnectProperties(connectProperties); - builder.withLifeCycleEvents(lifecycleEvents); - builder.withPublishEvents(publishEvents); - client = builder.build(); - builder.close(); - } else { - AwsIotMqtt5ClientBuilder.WebsocketSigv4Config websocketConfig = - new AwsIotMqtt5ClientBuilder.WebsocketSigv4Config(); - websocketConfig.region = signingRegion; - AwsIotMqtt5ClientBuilder builder = - AwsIotMqtt5ClientBuilder.newWebsocketMqttBuilderWithSigv4Auth( - endpoint, websocketConfig); - ConnectPacket.ConnectPacketBuilder connectProperties = - new ConnectPacket.ConnectPacketBuilder(); - - if (!caFile.isEmpty()) { - builder.withCertificateAuthorityFromPath(null, caFile); - } - connectProperties.withClientId(clientId); - builder.withConnectProperties(connectProperties); - builder.withLifeCycleEvents(lifecycleEvents); - builder.withPublishEvents(publishEvents); - client = builder.build(); - builder.close(); - } - - /* Connect */ - client.start(); - try { - lifecycleEvents.connectedFuture.get(60, TimeUnit.SECONDS); - } catch (Exception ex) { - throw new RuntimeException("Exception occurred during connect", ex); - } - - /* Subscribe */ - SubscribePacket.SubscribePacketBuilder subscribeBuilder = - new SubscribePacket.SubscribePacketBuilder(); - subscribeBuilder.withSubscription( - topic, QOS.AT_LEAST_ONCE, false, false, - SubscribePacket.RetainHandlingType.DONT_SEND); - try { - client.subscribe(subscribeBuilder.build()).get(60, TimeUnit.SECONDS); - } catch (Exception ex) { - onApplicationFailure(ex); - } - - /* Publish */ - PublishPacket.PublishPacketBuilder publishBuilder = - new PublishPacket.PublishPacketBuilder(); - publishBuilder.withTopic(topic).withQOS(QOS.AT_LEAST_ONCE); - int count = 0; - try { - while (count++ < messageCount) { - publishBuilder.withPayload( - ("\"" + message + ": " + String.valueOf(count) + "\"") - .getBytes()); - CompletableFuture published = - client.publish(publishBuilder.build()); - published.get(60, TimeUnit.SECONDS); - Thread.sleep(1000); - } - } catch (Exception ex) { - onApplicationFailure(ex); - } - publishEvents.messagesReceived.await(120, TimeUnit.SECONDS); - - /* Disconnect */ - DisconnectPacket.DisconnectPacketBuilder disconnectBuilder = - new DisconnectPacket.DisconnectPacketBuilder(); - disconnectBuilder.withReasonCode( - DisconnectPacket.DisconnectReasonCode.NORMAL_DISCONNECTION); - client.stop(disconnectBuilder.build()); - try { - lifecycleEvents.stoppedFuture.get(60, TimeUnit.SECONDS); - } catch (Exception ex) { - onApplicationFailure(ex); - } - - /* Close the client to free memory */ - client.close(); - - } catch (CrtRuntimeException | InterruptedException ex) { - onApplicationFailure(ex); - } - - CrtResource.waitForNoResources(); - System.out.println("Complete!"); - } -} diff --git a/sdk/tests/android/testapp/src/androidTest/java/software/amazon/awssdk/iottest/MainActivityTest.kt b/sdk/tests/android/testapp/src/androidTest/java/software/amazon/awssdk/iottest/MainActivityTest.kt index 3bc2e9af..1f0d0654 100644 --- a/sdk/tests/android/testapp/src/androidTest/java/software/amazon/awssdk/iottest/MainActivityTest.kt +++ b/sdk/tests/android/testapp/src/androidTest/java/software/amazon/awssdk/iottest/MainActivityTest.kt @@ -41,10 +41,6 @@ class MainActivityTest { // Add sample specific file loading here when(name) { - "pubsub.PubSub" -> { - resourceNames.add("pubSubCertificate.pem") - resourceNames.add("pubSubPrivatekey.pem") - } "shadow.ShadowSample" -> { resourceNames.add("shadowCertificate.pem") @@ -60,11 +56,6 @@ class MainActivityTest { resourceNames.add("cognitoIdentity.txt") } - "mqtt5.pubsub.PubSub" -> { - resourceNames.add("mqtt5PubSubCertificate.pem") - resourceNames.add("mqtt5PubSubPrivatekey.pem") - } - "mqtt5x509.Mqtt5X509" -> { resourceNames.add("mqtt5PubSubCertificate.pem") resourceNames.add("mqtt5PubSubPrivatekey.pem") @@ -99,13 +90,6 @@ class MainActivityTest { // Set sample specific args when(name){ - "pubsub.PubSub" -> { - args.addAll(arrayOf( - "--cert", resourceMap["pubSubCertificate.pem"], - "--key", resourceMap["pubSubPrivatekey.pem"], - "--port", "8883", - "--message", "message.txt", "Hello World From Android")) - } "jobs.JobsSample" -> { args.addAll(arrayOf( diff --git a/utils/ci-aws-doc-links.txt b/utils/ci-aws-doc-links.txt new file mode 100644 index 00000000..5630cb76 --- /dev/null +++ b/utils/ci-aws-doc-links.txt @@ -0,0 +1 @@ +samples/Mqtt/Mqtt5X509/pom.xml