IT初心者のSORACOMジャーニー SORACOM Kryptonで認証キーを手放す


本記事はSORACOM Advent Calendar 2019の6日目のものです!

「クラウドって何?サーバーって何?」の状態で、2018年8月からPython・AWSを勉強し始めて、今年はJAWS-FESTA2019にて「IT初心者のクラウドジャーニー」というテーマでプレゼンして、2019年11月12日 SORACOM-UG#1 札幌初開催! 勢いのままに、Qiita初投稿です!

初心者は何から始めるか?

プログラムもデバイスもクラウドサービス利用も全部わからないけど、自己満足できるレベルのアウトプットを求めて、IoT〜通信〜クラウドまで一連で勉強するテーマを決めました。
 「定期的に写真を撮るデバイスを作って、簡単なホームページを開設してみる」

 

初期の構成要素

構成 デバイス 備考
デバイス      Raspberry Pi 3B+   
通信手段 SORACOM SIM  Plan−D
クラウドサービス   AWS      S3、CLI、IAM
プログラミング言語 Python     3.5.3
オープンソースモジュール OpenCV   4.1.1

開発の変遷 

【第一段階】
1. ラズパイからPythonでPiカメラをOpenCVで起動させて、画像を撮影。
2. S3へのアクセス権限をIAMユーザから認証キーを払い出す。
3. AWS CLIで認証して、Boto3でS3へアップロード。
4. S3を公開にして、「index.html」に画像を埋め込んで、HTTPSにて静的サイトのURLを払い出す。
5. AWS Certificate Managerからドメインを購入し、静的サイトの独自ドメイン化を図る。
6. S3 → CloudFront → Route53 にて独自ドメインURLの払い出し。

~簡単な構成図~

 この構成で撮影画像をS3の静的サイト上で見れました!

セキュリティを考える

 セキュリティの知識ゼロで、デバイスを作成していました。見直した際の問題点を下記に記載。
  1.ラズパイにIAMユーザ権限を直接払い出し
  2.ラズパイのホームをPi設定、初期パスワードのまま利用
  3.S3のポリシーを全公開

 もうガバガバの状態でした!知らないって怖いです。
 少しずつ整理をしていくことにしました。
 

セキュリティに対して、Kryptonに至る経緯

【まずAWS側でできるセキュリティを確認してみた】
 1.AWS Cognitoを用いて、ユーザープールからIDを払い出し、承認キーの取得。
   AWS CLIから、Pythonのboto3を用いてS3へアップロード完了!
 2.AWS STSで認証をやってみようと思ったけどわからなかったので、やめる。
  
   Cognitoは便利な機能であることがわかった。が、認証キーの管理はいずれにせよ発生する。

【続いて、SORACOMのサービス内容を確認】
今回、作成したカメラデバイスとの相性がいいSORACOMサービスを選ぶ必要がある。
クラウドへのデータ転送を実施する上では、下記のサービスが存在する。

サービス名称 評価  結果
Beam     送信前後のプロトコル変換があり △ ※1
Funnel AWS IoTへの接続可能      ✖︎ ※2
Krypton  AWS Cognitoの認証を肩代わり ○ ※3

 ※1 データの暗号化におけるプロトコル変換が初心者の私にとっては、難しい。
 ※2 AWS IoTからS3へのデータ容量制限が128kByteであるため、画像をUPする上では不向き。
 ※3 認証キーの管理不要。認証の再生成時間も設定可能。
 

Kryptonを実装

 SORACOMさんのホームページ(こちら)を参考に実装しました。
 ホームページの内容のまま、SORACOM Kryptonを実装することができました。 
 ただし、画像をS3へUPする際に、PythonのSDKが無い?あるようだけど作る必要あり?とのことで、
 手っ取り早く実装したいので、既にSDKが存在するNode.jsを勉強し、S3へのアップロード用のプログラムを一部書き換えました。

 コード公開です。毎分撮影画像を指定のS3へアップロード。

Node.js
'use strict';
const AWS = require('aws-sdk');
const exec = require('await-exec');
const credentialsRefreshInterval = 15 * 60 * 1000;
const fs = require('fs');
const cron = require('node-cron')

// Executes krypton client to get open ID token
async function getToken(){
  let execResult = await exec("./krypton-cognito");
  return JSON.parse(execResult.stdout);
}

// Initializes AWS credentials and set timer to refresh periodically
async function initializeCredentials(){
  let data = await getToken();
  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityId: data.identityId,
    Logins: {
      'cognito-identity.amazonaws.com': data.token
    }
  }, {region: data.region});
  setInterval(
    async () => {
      data = await getToken();
      AWS.config.credentials.params.Logins['cognito-identity.amazonaws.com'] = data.token;
      AWS.config.credentials.refresh(err => {
        console.log("successfully refreshed AWS credentials");
      });
    },
    credentialsRefreshInterval
  );
}

initializeCredentials().then(() => {
  console.log("Successfully obtained AWS credentials");

  const s3 = new AWS.S3();
  const params = {
    Bucket: 'バケット名称',
    Key: "S3に保存する名前の画像名称"
    };
  let v = fs.readFileSync("./撮影画像名称");
  params.Body=v;
  cron.schedule(' 0 * * * * *',() => { 
  s3.putObject(params, function(err, data){
      if(err) console.log(eer, err.stack);
      else{    console.log(data);
               console.log('update image to S3!!');
           }
        });
    console.log('wait for next action');
    });
})

soracom-krypton-client-for-java中の”kryptonExamples”フォルダの中にある”cognito-auth.js”に対して、「定期実行」と「S3へのアップロード」を追加しています。
参照: Node.js 定期実行
参照: Node.js S3へのアップロード

最終的な構成

Plan-DのSIMで上記の構成にたどり着きました!
無事に、認証キーを手放すことができました!

さっそく大容量アップロード用のPlan-DU SIMで運用開始しようとしたが、Plan-DU用ドングルを購入しておらず、ドコモのWifiルーターで代用中だったことを思い出す。

あれ、そもそもWifiルーターに設置されたSIMに対してもKryptonって使えるんだけっけ?
よくわかっていないことが判明しました。とりあえず、Plan-DU用のドングルを購入しよう。

そして、Wifiルーターに対するKrypton設定についてご存知の方、教えて頂きたいです。
出来ないような気もしてます。。。

IT初心者が記載したブログとなります。
表現に誤りがある場合には、ご指摘いただけますと幸いです。
Advent Calendar 楽しんで参りましょう〜!

参照サイト

【ラズパイの設定に関する資料】
参照: 【python/OpenCV】カメラの歪み補正を行う方法

参照: ラズパイ3にOpenCV3/4を簡単に導入
 OpenCVがPython2に入ってしまう場合に動きません。python3を起動させてcv2のバージョンをチェックしてみるといいです。

参照: boto3を使ってS3にファイルのアップ&ダウンロード
boto3をラズパイに入れる際には、sudo pip3 install boto3
pip3で入れないと、Python3で使えないので注意ください。

【ラズパイとクラウド連携に関する資料】
参照: AWS CLIの設定とS3へのアップロード

【S3の静的サイト作成に関わる資料】
 参照: 【図解】AWS S3を静的なWebサーバーとして利用する

 参照: AWS S3で静的Webページをホスティングする

【クラウド上のセキュリティを高める資料】
参照: AWSにおける静的コンテンツ配信パターンカタログ(アンチパターン含む)

参照: AWS再入門 Amazon CloudFront編

参照: SSL証明書発行時のドメイン認証メールをSESで受け取ってみた

参照: S3と独自ドメインで公開しているサイトをSSL(https)化する