공유 액세스 서명 및 보안 토큰을 사용하여 Azure IoT Hub DPS(Device Provisioning Service)에 대한 액세스 제어

이 문서에서는 Azure IoT Hub DPS(Device Provisioning Service)를 보호하는 데 사용할 수 있는 옵션에 대해 설명합니다. 프로비전 서비스는 인증권한을 사용하여 각 엔드포인트에 대한 액세스 권한을 부여합니다. 권한을 통해 인증 프로세스는 기능에 따라 서비스 인스턴스에 대한 액세스를 제한할 수 있습니다.

이 문서에서는 다음에 대해 설명합니다.

  • 프로비전 서비스에서 Service 및 Device REST API에 대한 권한을 확인하는 데 사용하는 인증 프로세스 및 토큰.

  • Service API에 액세스하기 위해 백 엔드 앱에 부여할 수 있는 다양한 권한.

인증

Device API는 키 기반 및 X.509 인증서 기반 디바이스 인증을 지원합니다.

서비스 API는 백 엔드 앱에 대한 키 기반 인증을 지원합니다.

키 기반 인증을 사용할 때 Device Provisioning Service는 네트워크에서 키가 전송되는 것을 피하기 위해 보안 토큰을 사용하여 서비스를 인증합니다. 또한 보안 토큰은 유효 기간 및 범위가 제한됩니다. Azure IoT Device Provisioning SDK는 특별한 구성이 필요하지 않고 토큰을 자동으로 생성합니다.

경우에 따라 SDK를 사용하지 않고 HTTP Device Provisioning Service REST API를 직접 사용해야 할 수 있습니다. 다음 섹션에서는 REST API에 대해 직접 인증하는 방법을 설명합니다.

Device API 인증

Device API는 디바이스에서 Device Provisioning Service를 증명하고 IoT Hub 연결을 수신하는 데 사용됩니다.

참고 항목

인증된 연결을 받으려면 먼저 등록을 통해 Device Provisioning Service에 디바이스를 등록해야 합니다. Service API를 사용하여 등록을 통해 프로그래밍 방식으로 디바이스를 등록합니다.

디바이스는 프로비전 프로세스의 일부로 Device API에 인증해야 합니다. 디바이스에서 인증하는 데 사용하는 방법은 등록 그룹 또는 개별 등록을 설정할 때 정의됩니다. 인증 방법이 무엇이든 디바이스는 다음 URL에 HTTPS PUT을 발급하여 자체 프로비전해야 합니다.

    https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01

키 기반 인증을 사용하는 경우 보안 토큰은 HTTP 권한 부여 요청 헤더에 다음 형식으로 전달됩니다.

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

키 기반 인증을 위한 보안 토큰 구조

보안 토큰은 HTTP 권한 부여 요청 헤더에 다음 형식으로 전달됩니다.

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

예상 값은 다음과 같습니다.

설명
{signature} 형식의 HMAC-SHA256 서명 문자열은 {URL-encoded-resourceURI} + "\n" + expiry입니다. 중요: 키는 base64에서 디코딩되며 HMAC-SHA256 계산을 수행하는 데 키로 사용됩니다.
{expiry} 1970년 1월 1일 epoch 0시 UTC 이후의 초 수에 대한 UTF8 문자열입니다.
{URL-encoded-resourceURI} {ID_Scope}/registrations/{registration_id}의 소문자 URL 인코딩
{policyName} Device API의 경우 이 정책은 항상 “등록”입니다.

다음 Python 코드 조각은 대칭 키 인증 유형을 사용하는 개별 등록의 경우 입력 uri, key, policy_name, expiry에서 토큰을 계산하는 generate_sas_token이라는 함수를 보여 줍니다.


from base64 import b64encode, b64decode, encode 
from hashlib import sha256 
from time import time 
from urllib.parse import quote_plus, urlencode 
from hmac import HMAC 

 def generate_sas_token(uri, key, policy_name, expiry=3600): 
    ttl = time() + expiry 
    sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl)) 
    signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest()) 

    rawtoken = { 
        'sr' :  uri, 
        'sig': signature, 
        'se' : str(int(ttl)), 
        'skn' : policy_name 
    } 

    return 'SharedAccessSignature ' + urlencode(rawtoken) 

print(generate_sas_token("myIdScope/registrations/mydeviceregistrationid", "00mysymmetrickey", "registration"))

결과는 다음 출력과 같습니다.


SharedAccessSignature sr=myIdScope%2Fregistrations%2Fmydeviceregistrationid&sig=SDpdbUNk%2F1DSjEpeb29BLVe6gRDZI7T41Y4BPsHHoUg%3D&se=1630175722&skn=registration 

다음 예제에서는 공유 액세스 서명을 사용하여 Device API로 인증하는 방법을 보여 줍니다.


curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

대칭 키 기반 등록 그룹을 사용하는 경우 먼저 등록 그룹 키를 사용하여 device symmetric 키를 생성해야 합니다. 등록 그룹 기본 또는 보조 키를 사용하여 디바이스에 대한 등록 ID의 HMAC-SHA256을 계산합니다. 그런 다음, 결과를 Base64 형식으로 변환하여 파생된 디바이스 키를 가져옵니다. 코드 예제를 보려면 대칭 키 등록 그룹을 사용하여 디바이스를 프로비전하는 방법을 참조하세요. 디바이스 대칭 키가 파생되면 이전 예제를 사용하여 디바이스를 등록할 수 있습니다.

Warning

디바이스 코드에 그룹 마스터 키를 포함하지 않도록 하려면 디바이스에서 디바이스 키를 파생시키는 프로세스를 수행해야 합니다.

인증서 기반 인증

X.509 인증서 기반 인증에 대한 개별 등록 또는 등록 그룹을 설정한 경우 디바이스는 발급된 X.509 인증서를 사용하여 Device API를 증명해야 합니다. 등록을 설정하고 디바이스 인증서를 생성하는 방법에 대한 다음 문서를 참조하세요.

등록이 설정되고 디바이스 인증서가 발급되었으므로 다음 예제에서는 디바이스의 X.509 인증서를 사용하여 Device API에 인증하는 방법을 설명합니다.


curl -L -i -X PUT –cert ./[device_cert].pem –key ./[device_cert_private_key].pem -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

Service API 인증

Service API는 등록 상태를 검색하고 디바이스 등록을 제거하는 데 사용됩니다. 서비스는 백 엔드 앱에서 개별 그룹등록 그룹을 프로그래밍 방식으로 관리하는 데도 사용됩니다. 서비스 API는 백 엔드 앱에 대한 키 기반 인증을 지원합니다.

Service API 엔드포인트에 액세스하려면 적절한 권한이 있어야 합니다. 예를 들어 백 엔드 앱은 서비스에 보내는 모든 메시지와 함께 보안 자격 증명을 포함하는 토큰을 포함해야 합니다.

Azure IoT Hub Device Provisioning Service는 공유 액세스 정책에 대한 토큰을 확인하여 엔드포인트에 대한 액세스를 부여합니다. 대칭 키와 같은 보안 자격 증명은 통신 중에 전송되지 않습니다.

액세스 제어 및 권한

권한은 다음과 같은 방식으로 부여할 수 있습니다.

  • 공유 액세스 권한 부여 정책. 공유 액세스 정책은 모든 조합의 권한을 부여할 수 있습니다. Azure Portal에서 또는 프로그래밍 방식으로 Device Provisioning Service REST API를 사용하여 정책을 정의할 수 있습니다. 새로 만든 프로비전 서비스에는 다음과 같은 기본 정책이 있습니다.

  • provisioningserviceowner: 모든 사용 권한이 있는 정책입니다. 자세한 내용은 사용 권한을 참조하세요.

참고 항목

Device Provisioning Service 리소스 공급자는 Azure Resource Manager의 모든 공급자처럼 Azure 구독을 통해 보호됩니다.

보안 토큰을 생성 및 사용하는 방법에 대한 자세한 내용은 다음 섹션을 참조하세요.

HTTP는 유일하게 지원되는 프로토콜이며 권한 부여 요청 헤더에서 유효한 토큰을 포함하여 인증을 구현합니다.

예시

SharedAccessSignature sr = 
   mydps.azure-devices-provisioning.net&sig=kPszxZZZZZZZZZZZZZZZZZAhLT%2bV7o%3d&se=1487709501&skn=provisioningserviceowner`\

참고 항목

Azure IoT Device Provisioning Service SDK는 서비스에 연결할 때 토큰을 자동으로 생성합니다.

보안 토큰

Device Provisioning Service는 네트워크에서 키가 전송되는 것을 피하기 위해 보안 토큰을 사용하여 서비스를 인증합니다. 또한 보안 토큰은 유효 기간 및 범위가 제한됩니다. Azure IoT Device Provisioning Service SDK는 특별한 구성이 필요하지 않고 토큰을 자동으로 생성합니다. 일부 시나리오에서는 사용자가 보안 토큰을 직접 생성하고 사용해야 합니다. 이러한 시나리오에는 HTTP 화면의 직접 사용이 포함됩니다.

보안 토큰 구조

보안 토큰을 사용하여 IoT Device Provisioning Service에서 특정 기능에 대한 시간 제한 액세스 권한을 부여합니다. 권한 부여를 얻어 프로비전 서비스에 연결하려면 서비스는 공유 액세스 또는 대칭 키 중 하나로 서명된 보안 토큰을 전송해야 합니다.

공유 액세스 키로 서명된 토큰은 공유 액세스 정책 권한과 관련된 모든 기능에 대한 액세스를 부여합니다.

보안 토큰의 형식은 다음과 같습니다.

SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

다음은 예상 값입니다.

설명
{signature} 형식의 HMAC-SHA256 서명 문자열은 {URL-encoded-resourceURI} + "\n" + expiry입니다. 중요: 키는 base64에서 디코딩되며 HMAC-SHA256 계산을 수행하는 데 키로 사용됩니다.
{expiry} 1970년 1월 1일 epoch 0시 UTC 이후의 초 수에 대한 UTF8 문자열입니다.
{URL-encoded-resourceURI} 소문자 리소스 URI의 소문자 URL 인코딩. 이 토큰으로 액세스할 수 있는 엔드포인트의 URI 접두사(세그먼트별)이며 IoT Device Provisioning Service의 호스트 이름으로 시작합니다(프로토콜 없음). 예: mydps.azure-devices-provisioning.net.
{policyName} 이 토큰을 참조하는 공유 액세스 정책의 이름입니다.

참고

문자가 아니라 세그먼트에 의해 계산된 URI 접두사입니다. 예를 들어 /a/b/a/b/c에 대한 접두사이지만 /a/bc에 대한 접두사는 아닙니다.

다음 Node.js 코드 조각은 입력 resourceUri, signingKey, policyName, expiresInMins의 토큰을 계산하는 generateSasToken이라는 함수를 보여줍니다. 다음 섹션에서는 여러 토큰 사용 사례에 대해 서로 다른 입력을 초기화하는 방법을 자세히 설명합니다.

var generateSasToken = function(resourceUri, signingKey, policyName, expiresInMins) {
    resourceUri = encodeURIComponent(resourceUri);

    // Set expiration in seconds
    var expires = (Date.now() / 1000) + expiresInMins * 60;
    expires = Math.ceil(expires);
    var toSign = resourceUri + '\n' + expires;

    // Use crypto
    var hmac = crypto.createHmac('sha256', new Buffer(signingKey, 'base64'));
    hmac.update(toSign);
    var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));

    // Construct authorization string
    var token = "SharedAccessSignature sr=" + resourceUri + "&sig="
    + base64UriEncoded + "&se=" + expires + "&skn="+ policyName;
    return token;
};

비교를 위해 보안 토큰을 생성하는 동일한 Python 코드는 다음과 같습니다.

from base64 import b64encode, b64decode
from hashlib import sha256
from time import time
from urllib.parse import quote_plus, urlencode
from hmac import HMAC

def generate_sas_token(uri, key, policy_name, expiry=3600):
    ttl = time() + expiry
    sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl))
    print sign_key
    signature = b64encode(HMAC(b64decode(key), sign_key, sha256).digest())

    rawtoken = {
        'sr' :  uri,
        'sig': signature,
        'se' : str(int(ttl)),
        'skn' : policy_name
    }

    return 'SharedAccessSignature ' + urlencode(rawtoken)

참고 항목

IoT Device Provisioning Service 머신에서 토큰의 유효 기간이 확인되므로 토큰을 생성하는 머신의 시계에서 편차가 최소여야 합니다.

서비스 구성 요소에서 보안 토큰 사용

앞에서 설명했듯이 서비스 구성 요소는 적절한 권한을 부여하는 공유 액세스 정책을 사용하여 보안 토큰을 생성할 수 있습니다.

다음은 엔드포인트에 노출된 서비스 기능입니다.

엔드포인트 기능
{your-service}.azure-devices-provisioning.net/enrollments Device Provisioning Service에서 디바이스 등록 항목을 제공합니다.
{your-service}.azure-devices-provisioning.net/enrollmentGroups 디바이스 등록 그룹을 관리하기 위한 작업을 제공합니다.
{your-service}.azure-devices-provisioning.net/registrations/{id} 디바이스 등록 상태를 검색 및 관리하기 위한 작업을 제공합니다.

예를 들어 enrollmentread라는 미리 생성된 공유 액세스 정책을 사용하여 생성하는 서비스는 다음 매개 변수로 토큰을 만듭니다.

  • 리소스 URI: {mydps}.azure-devices-provisioning.net,
  • 서명 키: enrollmentread 정책의 키 중 하나,
  • 정책 이름: enrollmentread,
  • 임의의 만료 시간.backn

Create a shared access policy for your Device Provisioning Service instance in the portal

var endpoint ="mydps.azure-devices-provisioning.net";
var policyName = 'enrollmentread'; 
var policyKey = '...';

var token = generateSasToken(endpoint, policyKey, policyName, 60);

모든 등록 레코드에 대한 읽기 권한을 부여하는 결과는 다음과 같습니다.

SharedAccessSignature sr=mydps.azure-devices-provisioning.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=enrollmentread

SDK 및 샘플

참조 항목:

다음 참조 항목에서는 IoT Device Provisioning Service 액세스 제어에 대한 자세한 정보를 제공합니다.

Device Provisioning Service 권한

다음 테이블에는 IoT Device Provisioning Service에 대한 액세스를 제어하는 데 사용할 수 있는 권한이 나열되어 있습니다.

Permission 주의
ServiceConfig 서비스 구성을 변경하기 위한 액세스 권한을 부여합니다.
이 사용 권한은 백 엔드 클라우드 서비스에서 사용됩니다.
EnrollmentRead 디바이스 등록 및 등록 그룹에 대한 읽기 권한을 부여합니다.
이 사용 권한은 백 엔드 클라우드 서비스에서 사용됩니다.
EnrollmentWrite 디바이스 등록 및 등록 그룹에 대한 쓰기 권한을 부여합니다.
이 사용 권한은 백 엔드 클라우드 서비스에서 사용됩니다.
RegistrationStatusRead 디바이스 등록 상태에 대한 읽기 권한을 부여합니다.
이 사용 권한은 백 엔드 클라우드 서비스에서 사용됩니다.
RegistrationStatusWrite 디바이스 등록 상태에 대한 삭제 권한을 부여합니다.
이 사용 권한은 백 엔드 클라우드 서비스에서 사용됩니다.