aws / aws-iot-device-sdk-java

Java SDK for connecting to AWS IoT from a device.
https://aws.amazon.com/iot/sdk/
Apache License 2.0
211 stars 168 forks source link

Cannot connect to AWS IoT using MQTT over WebSocket with AWS Signature Version 4 authentication #162

Closed volphy closed 3 years ago

volphy commented 3 years ago

I have observed the same issue as https://github.com/aws/aws-iot-device-sdk-java/issues/109.

My environment:

jmklix commented 3 years ago

Are you using the exact same code as in #109? If not can you please include a minimal code snippet that reproduces the error?

Also have you only tried this using Windows Subsystem for Linux?

volphy commented 3 years ago

My code is slightly different (more PoC style than production style):

import com.amazonaws.services.iot.client.AWSIotException;
import com.amazonaws.services.iot.client.AWSIotMqttClient;

import java.io.File;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

public class MqttCheck {

    public static void main(String[] args) throws CertificateException,
            NoSuchAlgorithmException,
            KeyStoreException,
            IOException, AWSIotException {

        String endpoint = "******-ats.iot.eu-west-2.amazonaws.com";
        String clientId = "testIdv1";

        char[] keyPassword = {'c', 'h', 'a', 'n', 'g', 'e', 'i', 't'};

        // Keystore contains: Amazon Root CA 1 certificate, device certificate, factory CA certificate
        KeyStore keyStore = KeyStore.getInstance(
                new File("src/main/resources/****_aws_iot.jks"),
                keyPassword);

        // MQTT
//        AWSIotMqttClient mqttClient = new AWSIotMqttClient(endpoint,
//                clientId,
//                keyStore,
//                String.copyValueOf(keyPassword));

        // MQTT + WS
        Credentials credentials = new Credentials("***", "***");
        CredentialsProvider credentialsProvider = new StaticCredentialsProvider(credentials);
        AWSIotMqttClient mqttClient = new AWSIotMqttClient(endpoint,
                clientId,
                credentialsProvider,
                "eu-west-2"
                );

        mqttClient.connect();

        mqttClient.publish("myTopic", "Hello World! from v1".getBytes());

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        mqttClient.disconnect();
    }
}

In the code above I have replaced sensitive information with '***'.

My exception looks as follows:

Mar 31, 2021 11:24:24 AM com.amazonaws.services.iot.client.mqtt.AwsIotMqttConnectionListener onFailure
WARNING: Connect request failure
MqttException (0) - java.io.IOException: WebSocket Response header: Incorrect upgrade.
    at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:738)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.io.IOException: WebSocket Response header: Incorrect upgrade.
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketHandshake.receiveHandshakeResponse(WebSocketHandshake.java:162)
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketHandshake.execute(WebSocketHandshake.java:80)
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketSecureNetworkModule.start(WebSocketSecureNetworkModule.java:65)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:724)
    ... 1 more

Mar 31, 2021 11:24:24 AM com.amazonaws.services.iot.client.core.AwsIotConnection onConnectionFailure
INFO: Connection temporarily lost
Mar 31, 2021 11:24:24 AM com.amazonaws.services.iot.client.core.AbstractAwsIotClient onConnectionFailure
INFO: Client connection lost: testIdv1
Mar 31, 2021 11:24:27 AM com.amazonaws.services.iot.client.core.AwsIotConnection$1 run
INFO: Connection is being retried
Mar 31, 2021 11:24:28 AM com.amazonaws.services.iot.client.mqtt.AwsIotMqttConnectionListener onFailure
WARNING: Connect request failure
MqttException (0) - java.io.IOException: WebSocket Response header: Incorrect upgrade.
    at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:738)
    at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.io.IOException: WebSocket Response header: Incorrect upgrade.
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketHandshake.receiveHandshakeResponse(WebSocketHandshake.java:162)
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketHandshake.execute(WebSocketHandshake.java:80)
    at org.eclipse.paho.client.mqttv3.internal.websocket.WebSocketSecureNetworkModule.start(WebSocketSecureNetworkModule.java:65)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:724)
    ... 1 more

Mar 31, 2021 11:24:28 AM com.amazonaws.services.iot.client.core.AwsIotConnection onConnectionFailure
INFO: Connection temporarily lost
Mar 31, 2021 11:24:28 AM com.amazonaws.services.iot.client.core.AbstractAwsIotClient onConnectionFailure
INFO: Client connection lost: testIdv1

I have tested this code in MS Windows 10 as well.

I have not tested with version 1.3.8 because it's not available in Maven Central yet.

volphy commented 3 years ago

The issue is still the same with version 1.3.9.

volphy commented 3 years ago

I have simplified the code by removing commented out/unused parts and replacing deprecated method usage with the recommended one:

import com.amazonaws.services.iot.client.AWSIotException;
import com.amazonaws.services.iot.client.AWSIotMqttClient;
import com.amazonaws.services.iot.client.auth.Credentials;
import com.amazonaws.services.iot.client.auth.CredentialsProvider;
import com.amazonaws.services.iot.client.auth.StaticCredentialsProvider;

public class MqttCheck {

    public static void main(String[] args) throws
            AWSIotException {

        String endpoint = "***.iot.eu-west-2.amazonaws.com";
        String clientId = "testIdv1";

        // MQTT + WS
        Credentials credentials = new Credentials("***",
                "***",
                "***");
        CredentialsProvider credentialsProvider = new StaticCredentialsProvider(credentials);
        AWSIotMqttClient mqttClient = new AWSIotMqttClient(endpoint,
                clientId,
                credentialsProvider,
                "eu-west-2"
        );

        mqttClient.connect();

        mqttClient.publish("myTopic", "Hello World! from v1".getBytes());

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        mqttClient.disconnect();
    }
}

The same exception is being thrown.

bretambrose commented 3 years ago

What is the IAM policy attached to the user for the credentials you are using?

github-actions[bot] commented 3 years ago

Greetings! It looks like this issue hasn’t been active in longer than a week. Because it has been longer than a week since the last update on this, and in the absence of more information, we will be closing this issue soon. If you find that this is still a problem, please feel free to provide a comment or add an upvote to prevent automatic closure, or if the issue is already closed, please feel free to open a new one, also please try V2 as this might be solved there too.

volphy commented 3 years ago

Back from vacation.

@bretambrose I am using IoT Full policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

In the meantime, I have also introduced the following changes:

chochstedler commented 3 weeks ago

Was there a solution to this? I am seeing the exact same issue.