Skip to content

IoT ๋””๋ฐ”์ด์Šค ์—ฐ๊ฒฐ์— ๋Œ€ํ•ด ์ง์ ‘์ ์œผ๋กœ ๋‹ด๋‹นํ–ˆ๋˜ ๊ฒฝํ—˜์€ ์—†์ง€๋งŒ IoT Core ์ปจํŠธ๋กค ํ”Œ๋ ˆ์ธ ์ž‘์—…์— ์ด์–ด์„œ IoT ๋””๋ฐ”์ด์Šค์— ๋Œ€ํ•œ AWS IoT Device SDK for Java v2์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‹ค๋ฌด์—์„œ IoT ๋””๋ฐ”์ด์Šค์— ๋Œ€ํ•œ SDK๋Š” C ๋˜๋Š” ํŒŒ์ด์ฌ์œผ๋กœ ์ž‘์„ฑ๋œ ๊ฒƒ์„ ํ™œ์šฉํ•˜๊ฒ ์ง€๋งŒ ์ด์— ๋Œ€ํ•œ ๊ฒฝํ—˜์€ ์—†์œผ๋ฉฐ C ์™€ ํŒŒ์ด์ฌ์„ ๋‹ค๋ฃจ๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์•„๋‹ˆ๋ฏ€๋กœ ์ž๋ฐ” SDK๋กœ ํ™•์ธํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

IoT ๋””๋ฐ”์ด์Šค ๋ฐ์ดํ„ฐ ์—”๋“œํฌ์ธํŠธ โ€‹

IoT ๋””๋ฐ”์ด์Šค์—์„œ X.509 ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ์™€ ํ•จ๊ป˜ MQTT ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ AWS IoT ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค์— ์—ฐ๊ฒฐํ•  ๋•Œ๋Š” Data-ATS ์—”๋“œํฌ์ธํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์—”๋“œํฌ์ธํŠธ ์ฃผ์†Œ๋Š” AWS IoT Core์˜ DescribeEndpoint ๋ช…๋ น์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์ˆ˜์‹œ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์ •๋ณด๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์›น ์ฝ˜์†”์—์„œ ํ™•์ธํ•ด๋„ ๋ฌด๋ฐฉํ•˜๋ฏ€๋กœ IoT ์—ฐ๊ณ„ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ, ๊ฐœ์ธํ‚ค ํŒŒ์ผ, X.509 ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ๊ทธ๋ฆฌ๊ณ  ๋ฃจํŠธ CA ์ธ์ฆ์„œ ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ์—ฐ๊ฒฐ ๊ถŒํ•œ โ€‹

์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋Š” ์‚ฌ๋ฌผ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณด์•ˆ ์ •์ฑ…์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, MQTT ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•  ๋•Œ X.509 ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ์— ๋“ฑ๋ก๋œ ์—ฐ๊ฒฐ ์ •์ฑ…์œผ๋กœ ์ •์˜๋œ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋ฅผ ์‚ฌ๋ฌผ ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” MQTT ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค์— ๋™์ผํ•œ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ด์ „ ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-2:[account-id]:client/${iot:Connection.Thing.ThingName}"
    }
  ]
}

๋””๋ฐ”์ด์Šค ์—ฐ๊ฒฐ ์ƒํƒœ โ€‹

ํ”Œ๋ฆฟ ์ธ๋ฑ์‹ฑ์˜ ์‚ฌ๋ฌผ ์—ฐ๊ฒฐ์„ ํ™œ์„ฑํ™”ํ•˜๋ฉด IoT Core ์—์„œ IoT ๋””๋ฐ”์ด์Šค ์—ฐ๊ฒฐ ์ƒํƒœ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ”Œ๋ฆฟ ์ธ๋ฑ์‹ฑ์œผ๋กœ ์‚ฌ๋ฌผ ์—ฐ๊ฒฐ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” MQTT ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋ฅผ ์‚ฌ๋ฌผ ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•ž์„œ, ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ์—ฐ๊ฒฐ ๊ถŒํ•œ์—์„œ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋ฅผ ์‚ฌ๋ฌผ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ์ด์œ ๊ฐ€ ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ ์ƒํƒœ์— ๋Œ€ํ•œ ์ƒ์„ธ ์ด์œ ๋Š” ์›น ์ฝ˜์†”์˜ ์‚ฌ๋ฌผ ์—ฐ๊ฒฐ์„ฑ API ํ…Œ์ŠคํŠธ ๋˜๋Š” ์‚ฌ๋ฌผ ํ™œ๋™ ์ด๋ ฅ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

IoT Device Java SDK v2 ๊ธฐ๋ฐ˜ ์—ฐ๊ฒฐ ์ฝ”๋“œ โ€‹

AWS IoT Device SDK๋กœ IoT ๋””๋ฐ”์ด์Šค์—์„œ AWS ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค๋กœ ์—ฐ๊ฒฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ  Java SDK v2 ๊ธฐ๋ฐ˜์˜ ์ƒ˜ํ”Œ ์ฝ”๋“œ ์ค‘์—์„œ Direct MQTT with X509-based Mutual TLS Method ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ž‘์„ฑํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ƒ˜ํ”Œ ์˜ˆ์ œ ๋ฌธ์„œ์™€ ๋‹ค๋ฅด๊ฒŒ AwsIotMqtt5ClientBuilder ์—๋Š” newMtlsBuilder๋ผ๋Š” ํ•จ์ˆ˜๊ฐ€ ์—†์œผ๋ฏ€๋กœ newDirectMqttBuilderWithMtlsFromMemory ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋ฉฐ PEM ํ˜•์‹์˜ ๋ฌธ์ž์—ด์„ ์ฝ๊ธฐ ์œ„ํ•ด์„œ Files.readAllBytes ๋Œ€์‹ ์— JDK 11์—์„œ ์ถ”๊ฐ€๋œ Files.readString ์„ ๋Œ€์‹  ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

java
Mqtt5Client client = null;
try (IotClient iotClient = IotClient.builder()
        .credentialsProvider(DefaultCredentialsProvider.create())
        .region(Region.AP_NORTHEAST_2)
        .build()) {

    DescribeEndpointResponse endpoint = iotClient.describeEndpoint(builder ->
            builder.endpointType("iot:Data-ATS").build());

    String dataAtsEndpoint = endpoint.endpointAddress();
    String certificatePem = getPem("certificate.pem");
    String privateKey = getPem("privateKey.pem");
    String caRoot = getPem("AmazonRootCA1.pem");
    ConnectPacket.ConnectPacketBuilder connectProperties = new ConnectPacket.ConnectPacketBuilder()
            .withClientId("PC");

    client = AwsIotMqtt5ClientBuilder
            .newDirectMqttBuilderWithMtlsFromMemory(dataAtsEndpoint, certificatePem, privateKey)
            .withCertificateAuthority(caRoot)
            .withConnectProperties(connectProperties)
            .build();
    client.start();

    Thread.sleep(Duration.ofMinutes(5));
} finally {
    if (client != null) {
        client.close();
    }
}
java
public static String getPem(String filename) {
    try {
        return Files.readString(Path.of(ClassLoader.getSystemResource(filename).toURI()), StandardCharsets.UTF_8);
    } catch (Exception e) {
        return "";
    }
}

์—ฐ๊ฒฐ ์‹คํŒจ์— ๋Œ€ํ•œ ์˜ค๋ฅ˜ ์›์ธ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ธฐ โ€‹

IoT ๋””๋ฐ”์ด์Šค์˜ MQTT ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๋Š” ๊ฒฝ์šฐ ์—ฐ๊ฒฐ ์‹คํŒจ์— ๋Œ€ํ•œ ์˜ค๋ฅ˜ ์›์ธ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์˜ˆ์™ธ ์ผ€์ด์Šค๋ฅผ ๋‹ค๋ฃฐ ์ˆ˜ ์—†์ง€๋งŒ ์ œ๊ฐ€ ๊ฒฝํ—˜ํ–ˆ๋˜ ์ผ€์ด์Šค๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜ ์›์ธ์„ ๋ฏธ๋ฆฌ ์•Œ์•„๋‘๋ฉด ์‰ฝ๊ฒŒ ์›์ธ์„ ์ฐพ์•„๊ฐˆ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋„์›€์ด ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

LifecycleEvent: no lifecycle events found! โ€‹
sh
software.amazon.awssdk.crt.CrtRuntimeException: LifecycleEvent: no lifecycle events found! - error code: 38 (aws_last_error: AWS_ERROR_INVALID_STATE(38), An invalid state was encountered.) AWS_ERROR_INVALID_STATE(38)

Mqtt5Client๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” Mqtt5ClientOptions.LifecycleEvents ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์ƒ์•  ์ฃผ๊ธฐ์— ๋Œ€ํ•œ ๋™์ž‘์„ ๋นŒ๋”์— ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์œ„์™€ ๊ฐ™์ด ๋ผ์ดํ”„ ์‚ฌ์ดํด์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉฐ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

CONNACK:Client is not authenticated/authorized to send the message โ€‹
sh
CONNACK:Client is not authenticated/authorized to send the message:30d84af7-ddab-fd2e-7931-2592832a22d5

์œ„ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” onConnectionFailure ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒฐ๊ณผ์— ํฌํ•จ๋˜๋Š” ์‚ฌ์œ ์ž…๋‹ˆ๋‹ค. ์ด ๋ฉ”์‹œ์ง€๋Š” ํด๋ผ์ด์–ธํŠธ๋กœ ์ธ์ฆํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””(์‚ฌ๋ฌผ ์ด๋ฆ„)์— ์—ฐ๊ฒฐ๋œ ์ธ์ฆ์„œ์— ์˜ฌ๋ฐ”๋ฅธ ์ •์ฑ…์ด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์•˜์„ ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ iot:Connect ์ž‘์—…์— ๋Œ€ํ•œ ์ •์ฑ…์ด ์—ฐ๊ฒฐ๋œ ์ƒํƒœ๊ฐ€ ์•„๋‹Œ์ง€ ์ž˜๋ชป๋œ ํด๋ผ์ด์–ธํŠธ์— ๋Œ€ํ•œ ๊ถŒํ•œ์„ ๊ฐ€์ง€๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์‹œ์ง€ ์—ฐ๊ฒฐ ๊ถŒํ•œ์—์„œ ํ™•์ธํ–ˆ๋˜ ์‚ฌ๋ฌผ ์ด๋ฆ„์„ ํด๋ผ์ด์–ธํŠธ ์•„์ด๋””๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ€์ง€๋„๋กํ•œ X.509 ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์„œ ์ •์ฑ…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ErrorCode: 5134 โ€‹

onConnectionFailure ์ฝœ๋ฐฑ ๊ฒฐ๊ณผ๊ฐ€ ConnAckPacket ์ด ๋น„์–ด์žˆ๊ณ  ์—๋Ÿฌ ์ฝ”๋“œ๊ฐ€ 5134 ๋กœ ์ „๋‹ฌ๋œ๋‹ค๋ฉด ์‚ฌ๋ฌผ์— ์—ฐ๊ฒฐ๋œ ์ธ์ฆ์„œ๊ฐ€ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์—ฐ๊ฒฐ๋œ ํด๋ผ์ด์–ธํŠธ์— ๋Œ€ํ•œ ์ธ์ฆ์„œ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ฑฐ๋‚˜ ์ธ์ฆ์„œ ์ •์ฑ…์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ์ด๋ฏธ ์—ฐ๊ฒฐ๋œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์—ฐ๊ฒฐ ํ•ด์ œ๋˜์ง„ ์•Š์œผ๋ฏ€๋กœ ์•Œ์•„๋‘๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Released under the MIT License.