AWS 기술 블로그

AWS IoT Private CA을 이용하여 Amazon API Gateway에서 양방향 TLS 인증하기

배경

사물 인터넷(IoT) 환경에서 IoT 디바이스들은 MQTT 프로토콜을 사용해서 클라우드와 통신을 하고 있습니다. 이러한 MQTT 프로토콜을 이용한 통신 방식에는 다음과 같은 한계가 있습니다.

  • 비동기 통신 방식 : MQTT 프로토콜은 비동기식 방식이며, 많은 고객사의 사물 인터넷(IoT) 디바이스들은 HTTPS와 같은 동기 방식 통신만을 지원하고 있습니다.
  • 최대 Payload 크기 : MQTT 프로토콜의 최대 Payload 크기는 128KB 입니다. 그 이상의 크기의 payload을 전달하기 위해서는 데이터 Fragmentation이 필요합니다.
  • Amazon API Gateway 인증 방식 : Amazon API Gateway 인증 방식에서 API Key을 사용한 인증 방식은 API Key 전달 과정에서 보안 취약점을 가지고 있습니다.
  • Amazon CA : 현재 기본 설정으로 AWS IoT Core에서 디바이스 인증서를 생성할 때 Amazon CA에서 발급한 디바이스 인증서가 생성됩니다.

현재 사물 인터넷(IoT) 환경에서 많이 사용하고 있는 동기 방식에 128KB 이상의 payload가 필요한 통신 방식을 사용하기 위해서는 HTTPS 통신 방식인 REST API을 사용해야 하는데 이 경우 양방향 TLS 인증 방식을 사용하면 보안적으로 보다 안전하게 통신을 할 수 있습니다. 특히 고객사 Private CA을 이용해 양방향 TLS 인증을 수행할 수 있다면 고객사 인증서 체계를 자체적으로 구축할 수 있는 장점이 있습니다.

솔루션 개요

이번 게시글에서는 사물 인터넷 환경(IoT)에서 IoT 디바이스들이 자체 Private CA을 이용해 AWS IoT Core에서 디바이스 인증서를 발급 받고, 이 디바이스 인증서를 이용해 Amazon API Gateway와 양방향 TLS 인증을 통해 HTTPS 통신을 할 수 있는 방법에 대해서 알아보기로 합니다.

이를 통해서 IoT 디바이스들이 가지고 있는 1개의 디바이스 인증서를 이용해 AWS IoT Core와 MQTT 통신을 수행할 수 있고, 양방향 TLS 인증을 통해 Amazon API Gateway와는 HTTPS 통신을 할 수 있습니다.

솔루션 아키텍처

전체적인 동작 흐름은 관리자가 Private CA를 AWS IoT Core와 Custom Domain Name(TLS/SSL 서버)에 등록합니다. 이후 IoT 디바이스가 디바이스 인증서를 AWS IoT Core로부터 발급받은 후, 이 디바이스 인증서를 이용해 Server Contents와 HTTPS 통신을 할 수 있습니다. 이를 상세히 설명하면 다음과 같습니다.

  1. Private CA 등록 : 기본적으로 AWS IoT Core에서 IoT 디바이스 인증서를 발급할 때 Amazon CA로 서명한 후 디바이스 인증서를 생성합니다. 하지만 Private CA를 AWS IoT Core에 등록하면 Amazon CA가 아니라 해당 Private CA로 서명한 후 디바이스 인증서를 생성합니다. 이를 통해 자체 인증서 체계를 구축할 수 있습니다. 마찬가지로 Custom Domain Name(TLS/SSL 서버) 서버에도 Private CA를 등록합니다. IoT 디바이스에서 보낸 디바이스 인증서를 Private CA로 검증합니다.
  2. Device Onboarding : AWS IoT Core에서 디바이스 인증서를 발급하여 IoT 디바이스에 전송합니다.
  3. MQTT 통신 : 발급받은 디바이스 인증서를 사용해 AWS IoT Core와 MQTT 통신을 할 수 있습니다. 또한, 안전한 MQTT 통신으로 IoT Topic 및 IoT Rule을 통해 다양한 AWS 서비스와 연동할 수 있습니다.
  4. HTTPS 통신 : 발급받은 디바이스 인증서를 사용해 Amazon API Gateway와 HTTPS 통신을 할 수 있으며, REST API 을 양방향 인증을 통해 안전하게 사용할 수 있습니다.

사전 준비 사항

다음과 같은 사항이 사전에 준비되어야 합니다.

  • AWS Account
  • AWS 리전 : 발급 받은 SSL/TLS 도메인이 한국 도메인(Korea)이기 때문에 AWS 리전은 Asia Pacific(Seoul)을 사용합니다. 이후 모든 리전은 Asia Pacific(Seoul)을 사용합니다.

단계 요약

이번 게시글은 아래와 같은 단계로 구성됩니다.

  • 단계 1 : Private CA 생성하기
  • 단계 2 : AWS IoT Core에 Private CA 등록하기
  • 단계 3 : 디바이스 인증서 생성하기
  • 단계 4 : Domain Name Server 구성하기
  • 단계 5 : Custom Domain Name구성하기
  • 단계 6 : 구성 테스트 하기

단계 1 : Private CA 생성하기

다음과 같이 명령어 창에서 Private CA로 사용할 인증서를 생성합니다. 인증서를 생성할 때는 ‘openssl’ 명령어를 이용합니다.

// Private Key Pair 생성
% openssl genrsa -out HMCRootCA.key 4096

% openssl req -x509 -new -nodes -key HMCRootCA.key -sha256 -days 1024 -out HMCRootCA.pem

// rootCA_openssl.conf 생성
% nano rootCA_openssl.conf

// rootCA_openssl.conf에 아래와 같이 입력합니다.
[ req ]
distinguished_name = req_distinguished_name
extensions = v3_ca
req_extensions = v3_ca
[ v3_ca ]
basicConstraints = CA:TRUE
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = KR
countryName_min = 2
countryName_max = 2
organizationName = Organization Name (eg, company)
organizationName_default = Inc.

// CSR 파일 생성
% openssl req -new -sha256 -key HMCRootCA.key -nodes -out HMCRootCA.csr -config rootCA_openssl.conf

// PEM 파일 생성
% openssl x509 -req -days 3650 -extfile rootCA_openssl.conf -extensions v3_ca -in HMCRootCA.csr -signkey HMCRootCA.key -out HMCRootCA.pem
// Private Key Pair 생성
% openssl genrsa -out HMCRootCA.key 4096

% openssl req -x509 -new -nodes -key HMCRootCA.key -sha256 -days 1024 -out HMCRootCA.pem

// rootCA_openssl.conf 생성
% nano rootCA_openssl.conf

// rootCA_openssl.conf에 아래와 같이 입력합니다.
[ req ]
distinguished_name = req_distinguished_name
extensions = v3_ca
req_extensions = v3_ca
[ v3_ca ]
basicConstraints = CA:TRUE
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = KR
countryName_min = 2
countryName_max = 2
organizationName = Organization Name (eg, company)
organizationName_default = Inc.

// CSR 파일 생성
% openssl req -new -sha256 -key HMCRootCA.key -nodes -out HMCRootCA.csr -config rootCA_openssl.conf

// PEM 파일 생성
% openssl x509 -req -days 3650 -extfile rootCA_openssl.conf -extensions v3_ca -in HMCRootCA.csr -signkey HMCRootCA.key -out HMCRootCA.pem

단계 2 : AWS IoT Core에 Private CA 등록하기

단계 1에서 생성한 Private CA 를 AWS IoT Core에 등록합니다.

  1. AWS Console → AWS IoT Core → 보안 → 인증 기관 → CA 인증서 등록 메뉴 이동
  2. Private CA을 등록하기 위해서는 확인 인증서를 통해서 검증해야 합니다. 확인 인증서를 생성하기 위해 아래 명령을 이용하고, Common Name 입력 값에는 AWS IoT Core 콘솔에서 등록 코드를 복사하여 입력합니다.
    // Generate a key pair for the private key verification certificate
    % openssl genrsa -out verification_cert_key_filename.key 2048
    
    % openssl req -new \
        -key verification_cert_key_filename.key \
        -out verification_cert_csr_filename.csr
    
    // Copy this registration code(Aws IoT Core Console 참고)
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:
        State or Province Name (full name) []:
        Locality Name (for example, city) []:
        Organization Name (for example, company) []:
        Organizational Unit Name (for example, section) []:
        Common Name (e.g. server FQDN or YOUR name) []: “등록 코드”
        Email Address []:
    
        Please enter the following 'extra' attributes
        to be sent with your certificate request
        A challenge password []:
        An optional company name []:
    
    // Generate CRT file
    % openssl x509 -req \
        -in verification_cert_csr_filename.csr \
        -CA root_CA_cert_filename.pem \
        -CAkey root_CA_key_filename.key \
        -CAcreateserial \
        -out verificationCert.crt \
        -days 500 -sha256
    

  3. 생성한 CA Certificate(HMCRootCA.pem) 파일과 확인 인증서(verificationCert.crt)를 다음과 같이 AWS IoT Core에 업로드 한 후 ‘등록’ 버튼을 클릭합니다.
  4. 성공적으로 등록이 되면 다음 화면처럼 ‘상태’가 ‘활성’으로 변경됩니다.
  5. Customer Domain Name에서 사용할 수 있도록 생성한 Private CA를 Amazon S3에 다음과 같이 저장한다.
    // 파일명을 변경합니다.
    % cp HMCRootCA.pem truststore.pem
    
    // truststore.pem  파일을 S3에 저장합니다.
    % aws s3 cp ./truststore.pem s3://dyseo-iot2/

단계 3 : 디바이스 인증서 생성하기

단계 1에서 생성한 Private CA를 이용해서 디바이스 인증서를 생성합니다. 실환경에서는 IoT Device가 AWS IoT Core에 처음 연결될 때, AWS IoT Core가 디바이스 인증서를 생성해 전달하지만, 이번 게시글에서는 디바이스 인증서를 미리 생성한 후 사용합니다.

  1. 디바이스 key pair을 생성합니다.
    % openssl genrsa -out hmc_client01.key 2048
    % openssl req -new -key hmc_client01.key -out hmc_client01.csr
  2. 아래와 같이 CSR 파일을 생성합니다.
  3. Private CA로 디바이스 인증서를 서명합니다.
    % openssl x509 -req -in hmc_client01.csr -CA HMCRootCA.pem -CAkey 
    % HMCRootCA.key -set_serial 01 -out hmc_client01.pem -days 3650 -sha256
    

단계 4 : Domain Name Server 구성하기

도메인을 구매하는 방법은 2가지가 있습니다. 첫 번째는 Amazon Route 53에서 도메인을 구매하는 방법이고 두 번째는 가비아(https://www.gabia.com/)에서 도메인을 구매하고 Amazon Route 53에서 등록하는 방법입니다. 여기서는 두 번째 방법을 사용해서 domain name 서버를 구성합니다. 구성 방법은 다음과 같습니다.

    1. 가비아에서 도메인을 구매합니다. 구매 방법은 다음 링크를 참고합니다.
    2. 구매한 도메인 정보는 다음과 같습니다.
    3. Amazon Route 53에서 해당 도메인 주소이름으로 호스팅 영역을 생성합니다.
    4. 생성된 호스팅 영역 NS 레코드의 네임 서버 주소를 가비아 네임서버 정보로 변경합니다.

    5. 설정된 도메인 주소가 정상 동작하는지 다음과 같이 확인합니다. 설정하고 30분 정도 뒤부터 정상 동작합니다.
      % nslookup daeyeol80.shop
      
      Server: 192.168.50.1
      Address: 192.168.50.1#53
      
      Non-authoritative answer:
      Name: daeyeol80.shop
      Address: 13.209.164.24
      Name: daeyeol80.shop
      Address: 52.79.113.253

단계 5 : Custom Domain Name 구성하기

Server Contents 구성을 위해 Amazon API Gateway에서 기본 예제로 제공되는 API PetStore 예제를 사용해 배포합니다. 해당 API는 Custom Domain Name 뒤 편에서 동작하게 되고 Custom Domain Name에서 양방향 인증이 성공하면 해당 API가 호출되어 양방향 인증 동작을 확인할 수 있습니다.

  1. 다음과 같이 API PetStore을 구성합니다.

  2. 생성 후 동작 테스트는 다음과 같이 ‘curl’ 명령어를 이용합니다.
  3. Amazon API Gateway 콘솔 화면에서 사용자 지정 도메인 이름 메뉴에서 사용자 지정 도메인 이름을 먼저 생성합니다. 설정화면에서 양방향(상호) TLS는 비활성화하고 TLS 1.2를 선택합니다.
  4. 사용자 지정 도메인 생성 시 ACM(Amazon Certificate Manager) 인증서를 지정해야 하는데 ACM 콘솔 창에서 설정합니다.
  5. ACM 콘솔 창에서 인증서 요청  퍼블릭 인증서 요청을 선택하고 다음과 같이 입력합니다.
  6. 퍼블릭 인증서를 생성하면 상태가 ‘검증 대기 중’으로 변경되고, Route 53 레코드를 생성하면 검증이 완료됩니다.
  7. 정상적으로 생성 완료 되면 호스팅 영역 레코드 화면에서 아래와 같이 추가되는 것을 확인합니다.
  8. Amazon API Gateway 사용자 지정 도메인 이름 생성이 완료되면 API 매핑을 구성해서 PetStore와 연결시킵니다.
  9. 도메인으로 입력 시(daeyeol80.shop) Amazon API Gateway에 설정된 사용자 지정 도메인 이름으로 라우팅이 되도록 레코드를 추가합니다.
  10. 도메인 주소로만 접근하기 위해서 PetStore API의 기본 엔드 포인트를 비활성화 시킵니다.
  11. 연결 테스트를 수행합니다.
    curl https://daeyeol80.shop

  12. API Gateway 콘솔에서 사용자 지정 도메인 이름 메뉴를 선택한 후 생성한 사용자 지정 도메인 이름을 선택합니다.

  13. Customer Domain Name(사용자 지정 도메인) 설정 화면에서 도메인 이름과 최소 TLS 버전을 선택하고, 양방향(상호) TLS 인증을 활성화합니다. 여기서 트러스트 스토어 URI는 Private CA를 저장한 S3 위치를 지정합니다.

단계 6: 구성 테스트 하기

다음과 같이 하나의 IoT 디바이스 인증서를 이용해서 HTTPS 통신과 MQTT 통신이 정상 동작하는지 확인합니다.

  1. HTTPS 통신을 확인합니다.
    % curl --key hmc_client01.key --cert hmc_client01.pem https://daeyeol80.shop

  2. MQTT Broker인 Mosquitto을 사용해서 MQTT 통신을 확인합니다.
    % mosquitto_pub --cafile ~/root.ca.bundle.pem \
    --cert ./hmc_client01.pem \
    --key ./hmc_client01.key \
    --tls-version tlsv1.2 \
    -h a2c8ulgtgy0edz-ats.iot.ap-northeast-2.amazonaws.com \
    -p 8883 \
    -q 0 -t test/ws \
    -i HMC_ssl444444 -d \
    -m "{\"prov\": \"first\", \"date\": \"$(date)\"}"

리소스 정리하기

이 게시글에서 사용했던 리소스는 향후 불필요한 과금을 방지하기 위해 삭제하여야 합니다. 삭제해야 할 리소스는 다음과 같습니다.

  • AWS IoT Core에 등록 된 Private CA
  • Amazon API Gateway에 PetStore API
  • Customer Domain Name
  • pem을 저장한 Amazon S3 버킷
  • Amazon Route53 호스팅 영역

결론

이번 게시글에서는 AWS IoT Private CA을 이용하여 Amazon API Gateway에서 양방향 TLS 인증을 위한 구성 방법을 알아보았습니다. 사물 인터넷(IoT) 환경에서 양방향 TLS 인증(Mutual TLS Authentication)을 사용하면 IoT 디바이스를 안전하게 클라우드와 연결할 수 있습니다. 특히 고객사 Private CA을 이용해 양방향 TLS 인증을 수행하면 고객사 인증서 체계를 확장할 수 있습니다.

Daeyeol Seo

Daeyeol Seo

서대열 IoT 아키텍트는 다양한 IoT 디바이스에 대한 개발 경험을 바탕으로 고객이 최적의 솔루션을 선택하여 비즈니스 성과를 달성할 수 있도록 고객과 함께 효율적인 IoT 아키텍처를 구성하는 역할을 수행하고 있습니다.