2018年1月27日土曜日

SSHでシェルを実行するLambda(python) 関数をAWS SAM Local でテストする

前回の記事で、AWS SAM Local をインストトールしたので、

今回は、Lambda(python)から、SSH接続してコマンド(シェル)を実行してみます。

1.python モジュールの取得


Lambda で使用する pythonモジュールを用意します。
Lambda で python を実行する場合は、AmazonLinux が前提になるので、Docker の AmazonLinux で python モジュールを取得します。

AmazonLinux の Dockerイメージを取得します。
[root@centos702 python]# docker pull amazonlinux
Using default tag: latest
latest: Pulling from library/amazonlinux
40280b975f14: Pull complete
Digest: sha256:b852ce504670f604074bb0a0285849c95541453c39da4a6abe19c096695ccfca
Status: Downloaded newer image for amazonlinux:latest

作業用ディレクトリを作成し、そこに、モジュールを格納できるように Docker コンテナにマウントします。
AmazonLinux イメージでコンテナを起動します。
[root@centos702 ~]# mkdir lambda
[root@centos702 ~]# docker run --rm -it -v `pwd`/lambda:/lambda amazonlinux /bin/bash
bash-4.2#

pythonモジュールのインストールに必要なパッケージをインストールします。
bash-4.2# yum -y install python27-pip vi zip gcc python27-devel

ssh接続に必要な python のパッケージをインストールします。
bash-4.2# pip install pycrypto -t /lambda
bash-4.2# pip install paramiko -t /lambda
bash-4.2# exit
exit

2.Python プログラムの作成


今回は、 worker_function.py というファイル名でプログラムを保存します。
[root@centos702 ~]# cd lambda/
[root@centos702 lambda]# ls
Crypto                       cffi-1.11.4.dist-info         ipaddress.py              pycparser-2.18.egg-info
PyNaCl-1.2.1.dist-info       cryptography                  ipaddress.pyc             pycrypto-2.6.1.egg-info
_cffi_backend.so             cryptography-2.1.4.dist-info  nacl                      six-1.11.0.dist-info
asn1crypto                   enum                          paramiko                  six.py
asn1crypto-0.24.0.dist-info  enum34-1.1.6.dist-info        paramiko-2.4.0.dist-info  six.pyc
bcrypt                       idna                          pyasn1
bcrypt-3.1.4.dist-info       idna-2.6.dist-info            pyasn1-0.4.2.dist-info
cffi                         ipaddress-1.0.19.egg-info     pycparser
[root@centos702 lambda]# vi worker_function.py

ソースコードは以下のとおり。
[root@centos702 lambda]# cat worker_function.py
import boto3
import paramiko
def worker_handler(event, context):

    s3_client = boto3.client('s3')
    c = paramiko.SSHClient()
    c.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    host=event['IP']
    print "Connecting to " + host
    c.connect( hostname = host, username = "user01", password = "p@ssw0rd" )
    print "Connected to " + host

    commands = [
        "/usr/bin/aws s3 cp s3://blue21.dev.local/HelloWorld.sh /tmp/HelloWorld.sh --region us-east-1",
        "/usr/bin/chmod 700 /tmp/HelloWorld.sh",
        "/tmp/HelloWorld.sh",
        "/bin/rm /tmp/HelloWorld.sh"
        ]
    for command in commands:
        print "Executing {}".format(command)
        stdin , stdout, stderr = c.exec_command(command)
        print stdout.read()
        print stderr.read()

    return
    {
        'message' : "Script execution completed. See Cloudwatch logs for complete output"
    }
以下の処理を行います。
・イベントで渡されたIPアドレスにパスワード認証でSSHログインする
・S3 から、HelloWorld.sh をダウンロードして実行する

3.AWS SAM 用の設定ファイル作成


template.yml を作成します。(AWS SAM ドキュメント)
[root@centos702 lambda]# cat template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: ssh application.
Transform: AWS::Serverless-2016-10-31
Resources:
  WorkerFunction:
    Properties:
      CodeUri: .
      FunctionName: SSHFunction
      Handler: worker_function.worker_handler
      MemorySize: 128
      Role: arn:aws:iam::xxxxxxxx5:role/Lambda01_Role
      Runtime: python2.7
      Timeout: 30
      VpcConfig:
        SubnetIds:
          - subnet-f528a2ad
          - subnet-ceb59087
        SecurityGroupIds:
          - sg-bbf176df
    Type: AWS::Serverless::Function

event.json を作成します。
[root@centos702 lambda]# cat event.json
{
    "IP": "192.168.56.102"
}

4. S3 に HelloWorld.sh を用意


今回作成するLambda関数は、SSHログインしたサーバで、S3からシェルをダウンロードして実行します。
S3 に格納する HelloWorld.sh を作成します。
[root@centos702 lambda]# cat /root/HelloWorld.sh
#!/bin/bash
date
hostname
echo "Hello"

s3 バケットを作成します。
[root@centos702 lambda]# aws s3api create-bucket --bucket blue21.dev.local --region us-east-1

s3 にアップロードします。
[root@centos702 lambda]# aws s3 cp /root/HelloWorld.sh s3://blue21.dev.local --region us-east-1

5.動作確認


AWS SAM Local で動作確認します。
[root@centos702 lambda]# sam local invoke "WorkerFunction" -e event.json
A newer version of the AWS SAM CLI is available!
Your version:   0.2.4
Latest version: 0.2.6
See https://github.com/awslabs/aws-sam-local for upgrade instructions

2018/01/28 08:57:49 Successfully parsed template.yaml
2018/01/28 08:57:49 Connected to Docker 1.35
2018/01/28 08:57:49 Fetching lambci/lambda:python2.7 image for python2.7 runtime...
python2.7: Pulling from lambci/lambda
Digest: sha256:87a3b9bb1ba6ae666b0087107852b67415cae0660669ae5633a0ab828aea2c69
Status: Image is up to date for lambci/lambda:python2.7
2018/01/28 08:57:51 Invoking worker_function.worker_handler (python2.7)
2018/01/28 08:57:51 Mounting /root/lambda as /var/task:ro inside runtime container
START RequestId: 98cc5738-0ad4-4ef9-952f-51b9d56870b9 Version: $LATEST
Connecting to 192.168.56.102
Connected to 192.168.56.102
Executing /usr/bin/aws s3 cp s3://blue21.dev.local/HelloWorld.sh /tmp/HelloWorld.sh --region us-east-1
download: s3://blue21.dev.local/HelloWorld.sh to ../tmp/HelloWorld.sh


Executing /usr/bin/chmod 700 /tmp/HelloWorld.sh


Executing /tmp/HelloWorld.sh
2018年  1月 28日 日曜日 08:57:56 JST
centos702
Hello


Executing /bin/rm /tmp/HelloWorld.sh


END RequestId: 98cc5738-0ad4-4ef9-952f-51b9d56870b9
REPORT RequestId: 98cc5738-0ad4-4ef9-952f-51b9d56870b9 Duration: 3507 ms Billed Duration: 3600 ms Memory Size: 128 MB Max Memory Used: 38 MB

null


[root@centos702 lambda]#