5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonを一行一行、見ていく(Pythonでトークン取得・パラメータストア登録/更新・デプロイ後のテスト失敗〜成功まで)

Last updated at Posted at 2020-09-04

どうも、こんにちは。お元気ですか?

ネットで昔の動画が配信されていると、
懐かしさで観てしまいますよね。
懐かしいというのは、それだけでエンターテイメントになるんですね。

以前はServerless FrameworkやPythonについてなど
有識者の方々のを見たり、聞いたりして、教わりながら
色々と新しいことを体験しながら覚えていったので
それらの知見? 感想? をここに残しておきたいと思います。

まずは、handler.pyを一行一行、見ていこうと思います

こういう記述がありました、どういう中身なのでしょう。
Python(パイソン)と聞くと、ムキムキの黒人ボクサーを思い出してしまいますよね。
あの人って、海外版だとバルログっていう名前になってるんですよね。

handler.py
from util import logging_decorator, build_response_decorator, get_logger

import app

logger = get_logger('INFO')

@logging_decorator
def xxxx_handler(event, context):
    return app._token(event)

from util import logging_decorator, build_response_decorator, get_logger

import app

  • これは、下記に記述されている内容です。同階層にあります

logger = get_logger('INFO')

@logging_decorator

def xxxx_handler(event, context):

  • defとは 英語のdefine(定義する)の略からきている そうです(Defaultと間違えていました)
  • xxxx_handlerと、定義された関数の中で、event, contextという引数を呼び出しています

return app._token(event)


続いて、app.pyを一行一行、見ていこうと思います

こういう記述がありました。ServerlessFrameworkに使うPythonです。
あと結構伏せ字(xxx)にしたので、変数の流れが間違っていたらすみません。
処理内容は、指定されたIDとパスワードを使用し、トークン情報(json形式)を指定されたところから取得して、 トークン情報のみを抽出し、パラメータストアに登録する というものです。

app.py
import json
import boto3
import requests
import os

def _token(event):
    
    try:
        # ===================================================================
        # トークン取得処理 
        # ===================================================================
        
        # boto3を使い、パラメータストアを利用する
        client = boto3.client('ssm')

        # シークレットキー取得
        # get_parameterでパラメータの値を取得
        response_get = client.get_parameter(
            Name = '/xxx/xxxx/xxxx',
            WithDecryption = True
        )
        client_secret_get = response_get['Parameter']['Value']

        # トークン取得に必要なキー一覧
        CLIENT_SECRET = xxxxx_xxxx_get
        CLIENT_ID = os.environ['XXXX']
        XXXX_URL = "https://xxxxx/xxxx"

        # あの夏、ボクらはキーを手にしたんだ
        xxxx_xxxx_key = {
            'xxxx_secret': XXXX_SECRET,
            'xxxx_id': XXXX_ID,
        }

        # トークン情報にアクセスし必要な情報を入力
        response_xxxx = requests.post(XXXX_URL, data=xxxx_xxxx_key)

        # トークン情報を出力
        # 結果はJSON形式なのでデコードする
        xxxx_data = json.loads(response_xxxx.text)

        # トークン情報の中からアクセストークンの値のみ抽出
        xxxx_xxxx_data = xxxx_data.get('access_token')

        # ===================================================================
        # 上で取得したトークン情報を - AWS Systems Manager - パラメータストアに送る
        # ===================================================================

        # put_parameterでパラメータの値を更新
        response_put = client.put_parameter(
            Name = '/xxxx/xxxx',
            Value = xxxx_xxxx_xxxx,
            Type = 'SecureString',
            Overwrite = True
        )

import json

import boto3

import requests

import os

def _token(event):

try:

# エラーハンドリング
    except Exception as error:
        data = {'request': event}
        logger.exception(error, extra=dict(data))

        return_params = {
            'message': 'エラーが発生しました。もう一度操作を実行してください。 {}'.format(str(error))
        }
        return {
            'statusCode': 500,
            'body': return_params
        }

client = boto3.client('ssm')

response_get = client.get_parameter(

  • まずは事前にパラメーターストア画面に行って、あらかじめ頂いているキーを登録してきました
  • ↓↓↓↓ここのオレンジのところですね

image.png

  • こういう画面で作成していきます(名前はわかりやすく、説明もわかりやすく、標準で安全な文字列でキーを値の欄に書き込みました)

image.png

  • その後、登録したキー(JIjlksjdfaijklaIJ+IJ...こんな感じの文字列)をget_parameter関数で取ってきます

Name = '/xxx/xxxx/xxxx',

  • 登録した名前をここに書きます
  • ここに / が書いてあるのは、名前にあえて / を入れて、他に登録したキーなどと被らず、かつ、このキーはどこに所属しているものかを階層という表記にして、わかりやすくしています

WithDecryption = True

)

  • カッコ閉じ

client_secret_get = response_get['Parameter']['Value']

CLIENT_SECRET = xxxxx_xxxx_get

  • ここで、上で取得した、シークレットキーを CLIENT_SECRET という変数にします(文字なのに

CLIENT_ID = os.environ['XXXX']

XXXX_URL = "https://xxxxx/xxxx"

  • トークンのある場所のURLを XXXX_URL という変数に入れました

xxxx_xxxx_key = {

         'xxxx_secret': XXXX_SECRET,
         'xxxx_id': XXXX_ID,
  • ここではリストの辞書型を使い、キーをまとめて xxxx_xxxx_key という変数に入れます
  • トークンを取得するために必要な、シークレットキーとIDを同じ場所に記述してはセキュリティ上よろしくない(ハードコーディングになる:別の場所に分けて書いた方が良い処理や値をソースコードの中に直接書いちゃうことだよ)ということで、シークレットキーはパラメータストアに、IDはLambdaの環境変数に分けて登録したので、それらを取得する記述が必要になっています

}

response_xxxx = requests.post(XXXX_URL, data=xxxx_xxxx_key)

xxxx_data = json.loads(response_xxxx.text)

xxxx_xxxx_data = xxxx_data.get('access_token')

response_put = client.put_parameter(

  • 上の方でgetをした内容を今度はput(置く、貼る)をします
  • 仕組みとしてはget_parameterと同じですね

Name = '/xxxx/xxxx',

  • putしたいパラメータストアの名前です(/が入っていますが、URLではなくてこちらで決めたネーミングルールです)

Value = xxxx_xxxx_xxxx,

  • わかりやすい説明をここで書きます

Type = 'SecureString',

  • ここが面白くて String だとそのままの文字が送られますが、SecureString にすると ***** となります
  • セキュリティですね

image.png

Overwrite = True

  • 今回は週一でトークンを書き直す処理を行っているので、上書きOKとしています

)


終わりに 今回も長かった!

本ページ内のリンクで引用、参照させていただいた、
公式ドキュメントや記事の筆者にお礼申し上げます。ありがとうございます。

さて、この段階に来て、次にこんなことも起こりました。
何度やってもデプロイ後、Lambda画面でのテストに失敗した んです!

なぜLambda画面でのテストに失敗したのか、それは…

Lambda(つまりserverless.yml)で設定していたPythonのバージョンは3.8だったのですが、
ローカルで編集していたときのPython環境は3.7だったんです。
てっきりデプロイする(ローカルから離れる)タイミングで最新に切り替わると思っていたのですが、そうではなかった。
作業をしているローカル環境のPythonのバージョンを3.8にしてデプロイしたら正常に動きました。
みなさまもお気をつけくださいませ。

5
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?