
AWS IoTのコード署名を作成してみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
サーバーレス開発部@大阪の岩田です。 前回のブログでAWS IoTのジョブ機能を試してみました。
この手順でもソフトウェアの配布自体は可能ですが、本来はソフトウェアが改竄されていないことを保証するためにコードファイルに署名することが推奨されます。 AWS IoTの開発者ガイドでも下記のように紹介されています。
コードをデバイスに送信する場合、ベストプラクティスはコードファイルに署名することです。これにより、デバイスでコードが転送中に変更されているかどうかを検出できます。
このブログでは実際にコード署名を作成する手順についてご紹介します。
やってみる
順を追って進めていきます。
CA証明書の作成
後ほど作成する証明書に署名するためオレオレCA証明書を作成します。 AWS IoTのコード署名では署名アルゴリズムにSHA256WITHECDSAを使う必要があるため、各オプションを適切に設定します。
$ openssl ecparam -genkey -name prime256v1 -out ca.key $ openssl req -x509 -sha256 -new -nodes -key ca.key -days 3650 -out ca.crt 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) []:JP State or Province Name (full name) []:Osaka Locality Name (eg, city) []:Osaka Organization Name (eg, company) []:Classmethod Organizational Unit Name (eg, section) []:Serverless Common Name (eg, fully qualified host name) []:CM-Iwata CA Email Address []:
証明書の作成
作成したオレオレCA証明書を使ってオレオレ証明書を作成します。
$ openssl ecparam -genkey -name prime256v1 -noout -out server.key $ openssl req -new -sha256 -key server.key > server.csr 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) []:JP State or Province Name (full name) []:Osaka Locality Name (eg, city) []:Osaka Organization Name (eg, company) []:Classmethod Organizational Unit Name (eg, section) []:Serverless Common Name (eg, fully qualified host name) []:iwata.classmethod.local Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: $ openssl x509 -req -sha256 -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
ACMに証明書をインポート
作成した証明書をACMにインポートします。
$ aws acm import-certificate --certificate file://server.crt --private-key file://server.key --certificate-chain file://ca.crt
インポートが成功したら署名アルゴリズムがSHA256WITHECDSAとなっていることを確認しARNを控えておきます。

署名用プロファイルの作成
次に署名用のプロファイルを作成します。 まず下記の要領でJSONファイルを用意します。
{
    "profileName": "<適当なプロファイル名>",
    "signingMaterial": {
        "certificateArn": "<先ほどACMにインポートした証明書のARN>"
    },
    "platformId": "AWSIoTDeviceManagement-SHA256-ECDSA"
}
作成したJSONファイルを使って署名用プロファイルを作成します。
$ aws signer put-signing-profile --cli-input-json file://profile.json
{
    "arn": "arn:aws:signer::xxxxxxxxxxxx:/signing-profiles/test_profile"
}
バージョニングを有効にしたS3バケットの作成
コード署名にはバージョニングを有効にしたS3バケットが必要になります。 下記のコマンドで作成します。
$ aws s3 mb s3://<適当なバケット名> $ aws s3api put-bucket-versioning --versioning-configuration Status=Enabled --bucket <作成したバケット名>
バケットが作成できたら署名対象となるコードをS3にアップしてバージョンを確認します
$ aws s3 cp <署名対象のファイル> s3://<作成したバケット名> $ aws s3api list-object-versions --bucket <作成したバケット名> --query 'Versions[?Key==`<署名対象のファイル>`]'
コード署名
準備ができたのでコード署名のジョブを実行します。 下記のようなJSONファイルを準備します。
{
    "source": {
        "s3": {
            "bucketName": "<作成したS3バケット>",
            "key": "<署名対象のコード>",
            "version": "<先ほど確認した署名対象コードのバージョンID>"
        }
    },
    "destination": {
        "s3": {
            "bucketName": "<作成したS3バケット>",
            "prefix": "<署名結果のS3オブジェクトに付与する適当なプレフィックス>"
        }
    },
    "profileName": "<作成した署名用プロファイルの名前>"
}
作成したJSONファイルを使ってコード署名のジョブを開始します。
$ aws signer start-signing-job --cli-input-json file://sign.json
{
    "jobId": "xxxxxxxxxxxxxxxxxx"
}
ジョブIDが出力されるので、ジョブの実行状況を確認します。
$ aws signer describe-signing-job --job-id <出力されたジョブID>
{
    "jobId": "xxxxxxxxxxxxxxxxxx",
    "source": {
        "s3": {
            "bucketName": "<作成したS3バケット>",
            "key": "<署名対象のコード>",
            "version": "<署名対象コードのバージョンID>"
        }
    },
    "signingMaterial": {
        "certificateArn": "<ACMにインポートした証明書のARN>"
    },
    "platformId": "AWSIoTDeviceManagement-SHA256-ECDSA",
    "profileName": "署名に使用したプロファイル名",
    "createdAt": 1549621529,
    "completedAt": 1549621530,
    "requestedBy": "ジョブを開始したIAMユーザー",
    "status": "Succeeded",
    "statusReason": "Signing Succeeded",
    "signedObject": {
        "s3": {
            "bucketName": "<作成したS3バケット>",
            "key": "<署名結果のオブジェクトキー>"
        }
    }
}
statusがSucceededになっていれば成功です。 署名結果のオブジェクトキーが出力されているので、適当にDLして中身を確認してみましょう。
$ aws s3 cp s3://<作成したS3バケット>/<署名結果のオブジェクトキー> sign_result.json
$ jq . < sign_result.json
{
  "rawPayloadSize": 6610,
  "signature": "署名",
  "signatureAlgorithm": "SHA256withECDSA",
  "payloadLocation": {
    "s3": {
      "bucketName": "<作成したS3バケット>",
      "key": "<署名対象のコード>",
      "version": "<署名対象コードのバージョンID>"
    }
  }
}
無事に署名成功です!!
まとめ
初めてAWS IoTのコード署名を作成してみたのですが、コード署名周りはかなり情報が少ない印象でした。 誰かのお役にたてば幸いです。












