SlackにAWSとPythonを使って簡単なアプリを作る記録

このサイトのやり方でアプリを作る

qiita.com

Slackで新規にアプリとボットユーザを作成する

  1. 「Create New App」ボタンから新規アプリを作成する。
  2. サイドメニューの[Bot Users]から新規ボットユーザを作成する。

AWSでLambda関数からCloudWatchにデバッグ用のログを出力するためのIAMロールを追加する

  1. f:id:ponsuke_tarou:20190507135118p:plain
    [IAM]画面を開く。
  2. f:id:ponsuke_tarou:20190507135340p:plain
    サイドメニューの[Role]を選択して[Create role]ボタンを押下する。
  3. f:id:ponsuke_tarou:20190507135531p:plain
    [AWS service]の[Lambda]を選択し、画面下の[Next: Permissions]ボタンを押下する。
  4. f:id:ponsuke_tarou:20190507135836p:plain
    [AWSLambdaBasicExecutionRole]を選択してロールを追加する。
  5. f:id:ponsuke_tarou:20190507140448p:plain
    Roleが追加される。

AWSでSlack Event APIの認証を行うLambda関数を作成する

  1. f:id:ponsuke_tarou:20190507141038p:plain
    コンソールで[Lambda]を選択する。
  2. f:id:ponsuke_tarou:20190507141332p:plain
    [Create a function]ボタンを押下する。
  3. f:id:ponsuke_tarou:20190507141453p:plain
    [Author from scratch]を選択して必要な項目を入力する。
    1. [Runtime]は、「Python 3.6」を選択する。
    2. [Permission]は、[Execution role]で「Use an existing role」を選択して[Existing role]で追加したIAMロールを選択する。
  4. f:id:ponsuke_tarou:20190507143045p:plain
    参考にしているQiitaページに記載されているコードとHandlerを転記して保存する。
    • エンドポイントを認証するためにSlackからリクエストが送られてきた際には、認証をとおすためにchalleng要素をレスポンスする必要がある。そのための処理。

AWSで新規にAPI Gatawayを作成する

Lambda関数を叩くためのエンドポイントとなるAPIを作成する

  1. f:id:ponsuke_tarou:20190507144320p:plain
    コンソールから[API Gateway]を選択する。
  2. f:id:ponsuke_tarou:20190507144525p:plain
    [Get started]ボタンを押下する。
  3. f:id:ponsuke_tarou:20190507144602p:plain
    [OK]ボタンを押下する。
  4. f:id:ponsuke_tarou:20190507145026p:plain
    内容を入力してAPIを作成する。

APIにPOSTメソッドを作成する

  1. f:id:ponsuke_tarou:20190507145810p:plain
    POSTメソッドを追加する。

デプロイしてエンドポイントを作成する

  1. f:id:ponsuke_tarou:20190507150340p:plain
    [Action]セレクトから「Deploy API」を選択してデプロイを行う。
  2. 画面上部にエンドポイントとなるURLが表示されます。

テストする

  1. f:id:ponsuke_tarou:20190508125412p:plain
    [Test]リンクを押下します。
  2. f:id:ponsuke_tarou:20190508125617p:plain
    [Test]ボタンを押下します。
  3. f:id:ponsuke_tarou:20190508125841p:plain
    Lambda関数が呼ばれてログが出力されました。
  4. f:id:ponsuke_tarou:20190508130138p:plain
    CloudWatchにもログが出力されました。

Slackで作成したAPIを設定する

  1. サイドメニューの[Event Subscriptions]を選択する。
  2. [Enable Events]を「On」にする。
  3. [Request URL]にエンドポイントとなるURLを入力する。
  4. [Subscribe to Bot Events]に「message.channels」か「message.groups」を追加する。
  5. [Save Changes]ボタンで保存する。

f:id:ponsuke_tarou:20190507151234p:plain

「message.channels」を設定することでボットユーザが参加しているパブリックチャンネルに投稿されたメッセージを取得できる

api.slack.com

「message.groups」を設定することでボットユーザが参加しているプライベートチャネルに投稿されたメッセージを取得できる

api.slack.com

パブリックチャンネルプライベートチャネルかを見分ける簡単な方法

Slackの画面横に表示されているチャネル名の横にあるマークを見るとわかる。

f:id:ponsuke_tarou:20190508152336p:plain
#マーク
f:id:ponsuke_tarou:20190508152400p:plain
鍵マーク
get.slack.help

ボットユーザをワークスペースに追加する

アプリをインストールする

f:id:ponsuke_tarou:20190507151911p:plain
サイドメニューの[Install App]を選択し[Install App to Workspace]ボタンを押下してインストールする。

チャネルにボットを参加させる

f:id:ponsuke_tarou:20190507152311p:plain
Slackの歯車マークから[Add people to チャネル]からボットを追加する。

メッセージをチャネルに投げるとAWSのCloudwatchのLogに内容が出力される

START RequestId: 24..................... Version: $LATEST
[INFO]	2019-05-08T06:11:48.565Z	24......................
{
    "token": "hogehoge",
    "team_id": "hogehoge",
    "api_app_id": "hogehoge",
    "event": {
        "client_msg_id": "hogehoge",
        "type": "message",
        "text": "chanelとgroupの違いがよくわからない",
        "user": "投稿したユーザID",
        "ts": "1557295907.016900",
        "channel": "チャネルID",
        "event_ts": "1557295907.016900",
        "channel_type": "group"
    },
    "type": "event_callback",
    "event_id": "イベントID",
    "event_time": 1557295907,
    "authed_users": [
        "hogehoge"
    ]
}
ログはLambda関数に書いた「logging.info(json.dumps(slack_event))」で出力される

ボットユーザがメッセージを投稿する機能を作る

AWSにOAuth Tokenを設定する環境変数を設定する

Slack APIの画面でOAuth Tokenを確認する
  1. サイドメニューの[OAuth & Permissions]を選択してOAuth Tokenを確認する。
    • OAuth Tokenは、ワークスペースにアプリをインストールした際に生成されている。
Lambda画面でOAuth Tokenを設定する環境変数を設定する
  1. [Lambda]の画面 > サイドメニューの[Functions] > 作成した関数 で関数の画面を開く。
  2. [Environment variables]にKEY「SLACK_APP_AUTH_TOKEN」「SLACK_BOT_USER_ACCESS_TOKEN」を入力して各OAuth Tokenを設定する。
  3. 画面右上の[Save]ボタンで保存する。

Lambd関数を更新する

  1. [Function code]に参考にしているQiitaページに記載されているコードを転記する。
  2. [Save]ボタンで保存する。
メッセージの投稿には、ボットユーザがメッセージを投稿できるchat.postMessageを使用しています。

api.slack.com

メッセージを投稿して動かしてみる

f:id:ponsuke_tarou:20190508154352g:plain
できあがり

MacのPhpStormでLaravelプロジェクトでPHPUnitをできるようにする記録

  • 環境
    • macOS Mojave バージョン10.14.4
    • Composer version 1.8.0

以前、Laravelのプロジェクトを作ったことがありましたが、今回はPhpStormを使ってやります。

ponsuke-tarou.hatenablog.com

PhpStormをインストールします。

  1. JetBeanのPHPStormのサイトからダウンロードします。
  2. ダウンロードしたPhpStorm-yyyy.x.x.dmgをクリックします。
  3. f:id:ponsuke_tarou:20190424223044p:plain
  4. f:id:ponsuke_tarou:20190424223107p:plain
  5. f:id:ponsuke_tarou:20190424223120p:plain
  6. f:id:ponsuke_tarou:20190424223133p:plain
  7. f:id:ponsuke_tarou:20190424223145p:plain
  8. f:id:ponsuke_tarou:20190424223205p:plain
    好きな色を選びます
  9. f:id:ponsuke_tarou:20190424223227p:plain
  10. f:id:ponsuke_tarou:20190424223239p:plain

新規にComposerプロジェクトを作成します。

# 事前にインストールしてあるComposerの場所を確認
$ which composer
/usr/local/bin/composer
  1. f:id:ponsuke_tarou:20190424223355p:plain
  2. f:id:ponsuke_tarou:20190424230607p:plain
    プロジェクトを作成するディレクトリとComposerの場所とpackageでLaravelを選択して作ります
  3. f:id:ponsuke_tarou:20190424234741p:plain
    プロジェクト作成中です。
  4. f:id:ponsuke_tarou:20190424235113p:plain
    プロジェクトが作成されました。

qiita.com

Composerがインストールされていない場合はPhpStormのサイトを参照して作成します。

以下サイトの[新しいComposerプロジェクトを作成するには] > [2. ダイアログで、プロジェクトのパラメータを指定します。] > [b. Composerコマンドの実行方法を選択します。]を参照
pleiades.io

Command line parameterで指定した「–prefer-dist」はLaravelをZIPでダウンロードするということです。

# こんなコマンドが動きます。
/usr/local/bin/composer create-project laravel/laravel /path/to/project/directory/tryPhp/composer --prefer-dist

kin29.info
getcomposer.org

Laravelのバージョンを確認します。

# ウィンドウの下にある[Terminal]またはMacのターミナルで確認します。
$ php artisan -V
Laravel Framework 5.8.14

LaravelにくっついているサーバでLaravelの初期画面を確認します。

# サーバを起動します
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>
# 表示されたURLにブラウザでアクセスします。
[Wed Apr 24 23:58:16 2019] 127.0.0.1:51584 [200]: /favicon.ico

f:id:ponsuke_tarou:20190425000004p:plain
表示されました。

Xdebugをインストールします。

qiita.com

プロジェクトを設定します。

PHP language levelを使っているPHPのバージョンに合わせます。

# [PHP language level]用に使っているPHPのバージョンを確認します
$ php --version
PHP 7.3.1 (cli) (built: Jan 10 2019 13:15:37) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.1, Copyright (c) 1998-2018 Zend Technologies
    with Xdebug v2.7.2, Copyright (c) 2002-2019, by Derick Rethans
    with Zend OPcache v7.3.1, Copyright (c) 1999-2018, by Zend Technologies

# [CLI Interpreter]用に使っているPHPのディレクトリを確認します
$ which php
/usr/local/bin/php
$ ls -la /usr/local/bin/ | grep php
# 省略
lrwxr-xr-x    1 mana  admin       27  1 20 14:09 php -> ../Cellar/php/7.3.1/bin/php
# 省略
  1. [PhpStorm] > [Preferences...] > [Languages & Frameworks] > [PHP]を選択します。
  2. [PHP language level]を使っているPHPのバージョンへ変更します。
  3. [CLI Interpreter]の[...]ボタンでダイアログを開き、使っているPHPの場所を設定します。
    • f:id:ponsuke_tarou:20190507231840p:plain
      XdebugがDebuggerとして設定されます。
PHP language levelが非活性で変更できない場合の対応方法

qiita.com

PHPUnitは、プロジェクトを作ったときに配置されています。

プロジェクトの直下にあるcomposer.jsonを確認するとデフォルトでインストールされています。
venderディレクトリにもphpunitディレクトリが配置されています。

    "require-dev": {
        "beyondcode/laravel-dump-server": "^1.0",
        "filp/whoops": "^2.0",
        "fzaninotto/faker": "^1.4",
        "mockery/mockery": "^1.0",
        "nunomaduro/collision": "^2.0",
        "phpunit/phpunit": "^7.5"
    },
$ ls -l vendor/ | grep phpunit
drwxr-xr-x@  8 mana  staff  256  4 24 23:47 phpunit

f:id:ponsuke_tarou:20190506130945p:plain
venderディレクトリにもphpunitディレクトリが配置されています。

PHPUnitの設定をします。

(Macのターミナルを使う場合)PHPUnitのパスを通します。

# .bash_profileにphpunitのパスを書いて
$ echo 'export PATH="/Path/To/vendor/phpunit/phpunit:$PATH"' >> ~/.bash_profile
# 反映して
$ source ~/.bash_profile
# 確認します。
$ phpunit --version
PHPUnit 7.5.9 by Sebastian Bergmann and contributors.
パスはbin配下ではなくphpunit配下を指定します。

以前PHPStormを使わなかった時は、PHPUnitのPathにbin配下を指定しました。

$ echo 'export PATH="/Path/To/vendor/bin/phpunit:$PATH"' >> ~/.bash_profile

PHPUnitを使えるようにする。 - Qiita

今回はうまくいきませんでした。

$ echo 'export PATH="/Path/To/vendor/bin/phpunit:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile
$ phpunit --version
-bash: phpunit: command not found

シンボリックリンクが貼ってあるけどだめなのですね。

$ ls -la vendor/bin/
total 32
drwxr-xr-x@  6 mana  staff   192  5  6 14:50 .
drwxr-xr-x@ 47 mana  staff  1504  5  6 14:43 ..
-rwxr-xr-x@  1 mana  staff  6028  2 17 05:54 php-parse
lrwxr-xr-x   1 mana  staff    26  5  6 14:43 phpunit -> ../phpunit/phpunit/phpunit
-rwxr-xr-x@  1 mana  staff  4305 10 14  2018 psysh
lrwxr-xr-x   1 mana  staff    51  5  6 14:43 var-dump-server -> ../symfony/var-dumper/Resources/bin/var-dump-server

composer.jsonにautoloadの定義があることを確認します。

定義がなければ環境に合わせて定義します。

    "autoload": {
        "psr-4": {
            "App\\": "app/"
        },
        "classmap": [
            "database/seeds",
            "database/factories"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },

対応付けのためのクラスマップ生成を行います。

# クラスマップ生成
$ composer dump-autoload
Generating optimized autoload files> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/nexmo-notification-channel
Discovered Package: laravel/slack-notification-channel
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.                                                                                                           Generated optimized autoload files containing 3759 classes

# 確認します
$ cat vendor/composer/autoload_psr4.php
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
    'Zend\\Diactoros\\' => array($vendorDir . '/zendframework/zend-diactoros/src'),
    'XdgBaseDir\\' => array($vendorDir . '/dnoegel/php-xdg-base-dir/src'),
    'Whoops\\' => array($vendorDir . '/filp/whoops/src/Whoops'),
    'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
    'TijsVerkoyen\\CssToInlineStyles\\' => array($vendorDir . '/tijsverkoyen/css-to-inline-styles/src'),
    'Tests\\' => array($baseDir . '/tests'),
    'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
    'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
    'Symfony\\Polyfill\\Iconv\\' => array($vendorDir . '/symfony/polyfill-iconv'),
    'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
    'Symfony\\Contracts\\' => array($vendorDir . '/symfony/contracts'),
    'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
    'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
    'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
    'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
    'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
    'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
    'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
    'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
    'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
    'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
    'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
    'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
    'Psy\\' => array($vendorDir . '/psy/psysh/src'),
    'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
    'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
    'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
    'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
    'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
    'Opis\\Closure\\' => array($vendorDir . '/opis/closure/src'),
    'NunoMaduro\\Collision\\' => array($vendorDir . '/nunomaduro/collision/src'),
    'Nexmo\\' => array($vendorDir . '/nexmo/client/src'),
    'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
    'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
    'Lcobucci\\JWT\\' => array($vendorDir . '/lcobucci/jwt/src'),
    'Laravel\\Tinker\\' => array($vendorDir . '/laravel/tinker/src'),
    'JakubOnderka\\PhpConsoleHighlighter\\' => array($vendorDir . '/jakub-onderka/php-console-highlighter/src'),
    'JakubOnderka\\PhpConsoleColor\\' => array($vendorDir . '/jakub-onderka/php-console-color/src'),
    'Illuminate\\Notifications\\' => array($vendorDir . '/laravel/nexmo-notification-channel/src', $vendorDir . '/laravel/slack-notification-channel/src'),
    'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
    'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'),
    'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'),
    'Http\\Adapter\\Guzzle6\\' => array($vendorDir . '/php-http/guzzle6-adapter/src'),
    'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
    'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
    'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
    'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'),
    'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
    'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'),
    'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
    'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
    'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
    'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
    'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
    'BeyondCode\\DumpServer\\' => array($vendorDir . '/beyondcode/laravel-dump-server/src'),
    'App\\' => array($baseDir . '/app'),
    '' => array($vendorDir . '/nesbot/carbon/src'),
);

PHPUnitの設定ファイルとなるphpunit.xmlを確認します。

自動でできるなんて素敵ですね。

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>

        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="BCRYPT_ROUNDS" value="4"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="MAIL_DRIVER" value="array"/>
        <env name="QUEUE_CONNECTION" value="sync"/>
        <env name="SESSION_DRIVER" value="array"/>
    </php>
</phpunit>

PhpStormにPHPUnitを設定します。

  1. [PhpStorm] > [Preferences...] > [Languages & Frameworks] > [PHP] > [Test Frameworks]を選択します。
  2. リストに「Local」がない場合は[+]ボタンで追加します。
  3. [PHPUnit library]で「Use Composer autoloder」を選択してvenderディレクトリ配下のautoloder.phpへのパスを設定します。
  4. [Test Runner]で[Default configuration file:]にチェックを入れてphpunit.xmlへのパスを設定します。

テストコードを作る

以前作ったファイルを流用します。なのでLaravelのディレクトリ構成とかからとっても外れています。
qiita.com

テスト対象ソースのエディタ上からテストクラスを生成します。

  1. f:id:ponsuke_tarou:20190506154955p:plain
    テスト対象ソース上でコンテキストメニュー > [Go To] > [Test]を選択します。
  2. f:id:ponsuke_tarou:20190506155122p:plain
    [Create New Test...]を選択します。既にテストペアが存在する場合はそのテストソースも表示されます。
  3. f:id:ponsuke_tarou:20190506155343p:plain
    テスト対象のメソッドを[Geneate test method for:]から選択して[OK]ボタンを押下します。
  4. f:id:ponsuke_tarou:20190506155514p:plain
    テストクラスが生成されました。

継承しているクラスをPHPUnit\Framework\TestCaseへ変更します。

自動生成時はHPUnit_Framework_TestCaseとなっていますがエラーとなるため変更します。
tomomik.hatenablog.com

Macのデフォルトではバックスラッシュが円マークになる事があるので以下のサイトを見てバックスラッシュで記載します。
Macにおけるバックスラッシュ(\)の入力方法 - Qiita

<?php

namespace App;

use PHPUnit\Framework\TestCase;

class controlStdClassArrayTest extends TestCase
{
// 省略

自動生成されたメソッドへテストコードを記載して保存します。

<?php

namespace App;

use PHPUnit\Framework\TestCase;

class controlStdClassArrayTest extends TestCase
{

    public function testCreateStdClassArrayNew()
    {
        $target = new controlStdClassArray();
        $stdList = $target->createStdClassArrayNew();

        foreach ($stdList as $std) {
            $this->assertInstanceOf(\stdClass::class, $std);
        }
    }
// 省略

作ったテストコード用に設定を追加します。

  1. f:id:ponsuke_tarou:20190507233810p:plain
    上部にある[Add Configurations...]を押下します。
  2. f:id:ponsuke_tarou:20190507234037p:plain
    [+]ボタンで表示されるテンプレートから[PHPUnit]を選択します。
  3. f:id:ponsuke_tarou:20190507235136p:plain
    各項目を入力して設定を追加します。

PHPUnitでテストコードを実行します。

f:id:ponsuke_tarou:20190507235717p:plain
[▶]ボタンで実行できます。

デバックしてブレークポイントで止めることもできます。

f:id:ponsuke_tarou:20190508000342p:plain
受話器マークをクリック後に虫ボタンでデバック実行してブレークポイントで止めることができます。

はじめてAWSのインスタンスを作ってSSH接続した時の記録

  • 環境
    • macOS Mojave バージョン10.14.4
    • ssh : OpenSSH_7.9p1, LibreSSL 2.7.3

ドキュメントどおりにやっていれば超簡単にできます。
が、無駄につまずくので記録します。

AWSのアカウントを作成します。

aws.amazon.com

住所は英語で入力します。

www.scriptlife.jp

EC2インスタンスを作成してSSH接続します。

aws.amazon.com

# ssh接続する方法
$ ssh -i {作成した秘密鍵のファイルパス} {ユーザ名:AMIの種類で変わる}@{インスタンスのIPv4パブリックIP}

Amazon Machine Image (AMI) で何を選択したかによってSSH接続する時のユーザ名が異なります。

上記ドキュメントの例では、

ですが初めて作ったインスタンスでは

でした。
これに気がつくのにかなり時間がかかりました。
xn--o9j8h1c9hb5756dt0ua226amc1a.com

f:id:ponsuke_tarou:20190501212514j:plain
乙女の滝

サイドチャネル攻撃とテンペスト攻撃の違い

前回の勉強内容

ponsuke-tarou.hatenablog.com

勉強のきっかけになった問題

テンペスト攻撃を説明したものはどれか。

  1. 故意に暗号化演算を誤動作させて正しい処理結果との差異を解析する。
  2. 処理時間の差異を計測して解析する。
  3. 処理中に機器から放射される電磁波を観測して解析する。
  4. チップ内の信号線などに探針を直接当て,処理中のデータを観測して解析する。

平成30年春期問13 テンペスト攻撃を説明したもの|情報処理安全確保支援士.com

サイドチャネル攻撃とテンペスト攻撃は、暗号装置を解析し暗号を盗む方法に使用されます。

サイドチャネル攻撃は、動いている装置から出る電流や電磁波・振動を計測して暗号解析の手がかりを得る攻撃です。

  • 英語 : Side Channel Attack
  • 外部と隔離された機器でも攻撃される可能性があります。

https://www.keirex.com/img/CypherAttack_j.jpg
ケイレックス・テクノロジー >> システムソリューション技術 >> 暗号セキュリティーの脅威と対策

https://www.togawa.cs.waseda.ac.jp/img/research/secu-sidechannel-attack.png
研究紹介 | 早稲田大学 戸川研究室

http://www.ec.okayama-u.ac.jp/~sws/nogami/Works/pic5.png
SCOPE:IoT時代における機器認証を安全に実現するセキュリティ計算チップの開発

テンペスト攻撃は、サイドチャネル攻撃の種類の1つです。

テンペスト攻撃は、機器やその周辺機器から出力される微弱な電磁波を計測して元情報を復元しようとします。

ディスプレイから発生される電磁波の放射レベルは強く、復号も容易になっています。
https://cybersecurity-jp.com/wp000/wp-content/uploads/2018/10/img_27685_1.png
テンペスト技術とは?遠隔で不正に情報を傍受する技術への対策について

漏洩電磁波から画面表示を“再現”したパソコン・モニター
https://tech.nikkeibp.co.jp/it/free/ITPro/NEWS/20041124/153009/1.jpg
「10万円の受信機でパソコンからの漏洩電磁波を“盗聴”できる」――ISTがデモ | 日経 xTECH(クロステック)

サイドチャネル攻撃には、他にも種類があります。

http://tooljp.com/windows/chigai/img/sidechannel-attack-valiation.png
サイドチャネル攻撃とテンペスト攻撃の違い

https://www.uec.ac.jp/research/information/column/22/images/pct_03.jpg
ユニーク&エキサイティング研究探訪 No.22│電気通信大学

電力解析攻撃は、機器の電力を計測します。

  • 英語 : Simple Powering Analysis
  • 別名 : SPA

https://www.netagent.co.jp/study/blog/img/20170914/20170914_overview.png
RHme3 WriteUp 第2問 - セキュリティごった煮ブログ|ネットエージェント

故障利用攻撃は、故意に暗号化演算を誤動作させて正しい処理結果との差異を解析します。

  • 別名 : フォールト解析攻撃

https://image.itmedia.co.jp/enterprise/articles/0806/05/fta.jpg
確率論を究める――交通事故とシステムダウンの関係 (2/3) - ITmedia エンタープライズ

タイミング攻撃は、処理時間の差異を計測して解析します。

タイミング攻撃では、攻撃対象の処理の実装を分析して応答時間が変化する要因を見つけることで、入力とその応答時間から隠されたデータ(パスワードなど)の特定を試みます。
https://corgi-lab.com/blog/wp-content/uploads/2018/01/time-attack_result.png
corgi-lab.com

プローブ解析は、チップ内の信号線などに探針を直接当て,処理中のデータを観測する破壊型解析です。

  • 別名 : プロ―ビング

他にもCache攻撃、スキャンベース攻撃等色々あります。

次回の勉強内容

勉強中・・・

2進数の問題を見ると頭が混乱します。

前回の勉強内容

ponsuke-tarou.hatenablog.com

2進数の表現の問題

aを正の整数とし,b=aの2乗 とする。aを2進数で表現するとnビットであるとき,bを2進数で表現すると高々何ビットになるか。

  1. n+1
  2. 2n
  3. nの2乗
  4. 2のn乗

平成25年春期問1 2進数の表現|応用情報技術者試験.com

f:id:ponsuke_tarou:20190416193255p:plain
あの日の思い出

「高々」とは、「最大」のことです。

  • 読み方 : たかだか
  • bを2進数で表現すると高々何ビット = bを2進数で表現すると最大何ビット

数学において、高々(たかだか)という表現は、英語の at most に対応した厳密な意味を持つ用語である。
「xは高々2である」という表現は「xは多くとも2である」事、すなわち「x≦2」を意味する。
高々 (数学) - Wikipedia

超地道な解き方:「aを2進数で表現するとnビット」のnに値を入れて考えてみる。

  • aが2bitだと、bの最大は1001で4bitになる
    1. aの最大 = (2進数)11 = (10進数)2 + 1 = (10進数)3
    2. bの最大 = aの2乗 = (10進数)9 = (10進数)8 + 0 + 0 + 1 = (2進数)1001 = 4bit
  • aが3bitだと、bの最大は110001で6bitになる
    1. aの最大 = (2進数)111 = (10進数)4 + 2 + 1 = (10進数)7
    2. bの最大 = aの2乗 = (10進数)49 = (10進数)32 + 16 + 0 + 0 + 0 + 1 = (2進数)110001 = 6bit
  • aが4bitだと、bの最大は11100001で8bitになる
    1. aの最大 = (2進数)1111 = (10進数)8 + 4 + 2 + 1 = (10進数)15
    2. bの最大 = aの2乗 = (10進数)225 = (10進数)128 + 64 + 32 + 0 + 0 + 0 + 0 + 1 = (2進数)11100001 = 8bit
  • aが5bitだと、bの最大は1111000001で10bitになる
    1. aの最大 = (2進数)11111 = (10進数)16 + 8 + 4 + 2 + 1 = (10進数)31
    2. bの最大 = aの2乗 = (10進数)961 = (10進数)512 + 256 + 128 + 64 + 0 + 0 + 0 + 0 + 0 + 1 = (2進数)1111000001 = 10bit
なんかaを1bit増やすとbのbitが2bit(真ん中の10分)増える・・・だから「2n」ですね。

Webツールを使ってちょっと大きめの値で確認してみる

サイトで紹介されている解き方

nけたの正の整数aと、mけたの正の整数bを乗算(a×b)したときのけた数はそれぞれの数字のけた数の和(n+m)を超えることはありません。
この性質は10進数に限ったことではなく、2進数、16進数などでも同じです。また、2進数では必ずけた数の和になります。
問題では2進数nビット(けた)の正の整数aを二乗したときのけた数ですから、
 (n+n)=2n
平成25年 春期 応用情報技術者 午前 問1

 2進数でnビットの最大値は、1111...112ですね(1がn個)。
 これを式変形します。
  1111...112(※1がn個) = 1000...002(※(n+1)桁。1の後ろに0がn個) - 12
 これを、10進数に直すと、
  2n - 1
 となります。
 ※注:簡単に導出しているように見えますが、実際には簡単な例(n=2のときとか)で確認しています。

 そうしたら、2乗しましょう。
  (2n - 1)2
    = 22n - 2 * 2n + 1

 これを2進数に直すと、
    = 1000...0002(※(2n+1)桁。1の後ろに0が2n個)
     - 100..002(※(n+1)桁。1の後ろに0がn個)
     + 12
となります。
計算後は、(2n+1)桁よりも小さな値になりますから、2n桁になります。
応用情報H25春 問1の解説 - だるまのエクセルVBA

ビット演算の応用問題

0以上255以下の整数nに対して、https://www.ap-siken.com/kakomon/22_haru/img/01.gifと定義する。next(n)と恒等的に等しい式はどれか。ここで,x AND y 及び x OR y は,それぞれxとyを2進数表現にして,けたごとの論理積及び論理和をとったものとする。

  1. (n+1) AND 255
  2. (n+1) AND 256
  3. (n+1) OR 255
  4. (n+1) OR 256

平成22年春期問1 ビット演算の応用|応用情報技術者試験.com

「恒等的に等しい」とは「どのような場合でも等しい」ということらしい

detail.chiebukuro.yahoo.co.jp
oshiete.goo.ne.jp

超地道な解き方:2進数にして論理演算してみます。

  1. nの最大値である255は2進数で書くと1111111となり、nは7bitで書ける範囲ということになります。
  2. n < 255の場合は、next(n) = n + 1 になります。
  3. n = 255の場合は、next(255) = 0になります。
  4. 以下表のようになる論理演算を選ぶわけです。
(10進数)n (10進数)next(n) (2進数)n (2進数)next(n)
255 0 1111111 0000000
254 255 1111110 1111111
2 3 0000010 0000011
1 2 0000001 0000010
0 1 0000000 0000001
  1. 回答群から推理して (n + 1) と (255 か 256) の組み合わせの論理演算になるはずです。
  2. 論理演算下後に (n + 1) になるはずです。
  3. nを7として8bitの2進数表記(256を表すため)で試してみます。

(n+1) AND 255

10進数 2進数
n+1=8 0000100
255 011111111
AND 0000100

(n+1) AND 256

10進数 2進数
n+1=8 0000100
256 10000000
AND 0000000

(n+1) OR 255

10進数 2進数
n+1=8 0000100
255 011111111
OR 011111111

(n+1) OR 256

10進数 2進数
n+1=8 0000100
256 10000000
OR 1000100
  • 答えは「 ( n + 1) AND 255 」です。

サイトで紹介されている解き方

定義式をみると、0なら1、1なら2と1ずつ足していって255だったら0にもどるという。いわゆる256進カウンタであることがわかります。これを2進数で考えます。255とは11111111です。ここで1を加えると0になるので100000000が0になる処理を考えると選択肢アが正解だとわかります。
平成18年度春期・ソフ開過去問・解説

ア 『(n +1)AND 255』は、255を2進数で表すと“1111 1111”なので、n =0のとき、next(n )=1になり、n =255のとき、next(n )=0になり、定義と一致する。
イ 『(n +1)AND 256』は、256を2進数で表すと“1 0000 0000”なので、n =0のとき、next(n )=0になり、定義と一致しない。
ウ 『(n +1)OR 255』は、255を2進数で表すと“1111 1111”なので、n =0のとき、next(n )=255になり、定義と一致しない。
エ 『(n +1)OR 256』は、256を2進数で表すと“1 0000 0000”なので、n =0のとき、next(n )=257になり、定義と一致しない。
平成18年 春期 ソフトウェア開発技術者 午前 問3

n が 255 の場合・・・

255+1=256

256と255は2進で
0001 0000 0000
0000 1111 1111

これらの AND は
0000 0000 0000
で、ゼロになります。

255未満で、例えば n が 254 については・・・

254+1=255

255と255は2進で
0000 1111 1111
0000 1111 1111

これらの AND は
0000 1111 1111
で、255 。n+1 になりました。
恒等式 - 合格☆情報処理技術者試験

f:id:ponsuke_tarou:20190417000727j:plain
思い出の一枚

次回の勉強内容

勉強中・・・

OP25BをしているプロバイダにはサブミッションポートかSMTPSかSTARTTLSを使おう

前回の勉強内容

ponsuke-tarou.hatenablog.com

勉強のきっかけになった問題

TCPのサブミッションポート(ポート番号587)の説明として,適切なものはどれか。

  1. FTPサービスで,制御用コネクションのポート番号21とは別にデータ転送用に使用する。
  2. Webアプリケーションで,ポート80番のHTTP要求とは別に,サブミットボタンをクリックした際の入力フォームのデータ送信に使用する。
  3. コマンド操作の遠隔ログインで,通信内容を暗号化するためにTELNETのポート番号23の代わりに使用する。
  4. 電子メールサービスで,迷惑メール対策としてSMTPのポート番号25の代わりに使用する。

平成25年秋期問20 TCPのサブミッションポートの説明|情報処理安全確保支援士.com

OP25Bは、ネットワーク内から外部のコンピュータのTCPポート25番への通信を禁止します。

ponsuke-tarou.hatenablog.com

外部からメールを送信する場合にOP25BをしているプロバイダではTCPポート25番が使えません。

f:id:ponsuke_tarou:20190411232733p:plain

サブミッションポートは、メール送信専用に利用するTCPポート587番のことです。

  • 英語 : submission port
  • OP25Bを実施しているプロバイダの場合はTCP25番ポートを通してのメール送信が出来なくなるが、このサブミッションポートを利用することで送信が可能となります。

SMTPSでは、TCPポート465番を使います。

SMTPSは、伝送路を暗号化するSSL/TLSSMTPに組み合わせたプロトコルです。

通常のSMTPとは異なる専用のポート番号(465番)を用いて最初からSSL/TLSにより通信を開始する方式。
トランスポート層において、データ完全性、機密性と通信相手を認証する機能を提供する。
アプリケーション層でクライアントとサーバは通常のSMTPを利用するが、コネクション自体はSSLもしくはTLSによって保護される。この動作はコネクションの確立時に行われる。クライアントやサーバがコネクションを確立する際、SSLTLSを利用するかどうかは分からないため、SMTPSのためのポート番号を割り当てることが一般的である。
SMTPS - Wikipedia

https://image.itmedia.co.jp/ait/articles/0801/18/wi-mailovssl01.gif
メールの送受信を暗号化するPOP3s/IMAP4s/SMTPs(over SSL)とは:Tech TIPS - @IT

https://image.itmedia.co.jp/ait/articles/0602/02/r13secripro4_02.gif
認証できないsmtpでメールを安全に送るには (3/3):セキュリティプロトコルマスター(4) - @IT

STARTTLSは、TCPポート25番か582番を使います。

STARTTLSは、送信側と受信側のサーバ療法がSSL/TLSに対応していると通信を暗号化する仕組みです。
  • 通信の流れ
    1. 通常のSMTPで通信を開始(セッション開始時は平文で始まる)
    2. 「STARTTLS」コマンドで双方がSSL/TLSに対応しているか確認(暗号化のためのネゴシエーションを行う)
    3. 対応していればSSL/TLSで再接続する

https://www.sendmagic.jp/wp-content/uploads/sm_starttls.png
STARTTLSに対応する | メール配信エンジンのSENDMAGIC

https://devcentral.f5.com/Portals/0/images/metapost/News-Articles/citizen_elah/2011/Oct/Windows-Live-Writer-iRuleologyTCPcollect-and-SMTP_87EF-starttls_flow_thumb.png
Advanced iRules: SMTP Start TLS

f:id:ponsuke_tarou:20190415230552j:plain
思い出の一枚

次回の勉強内容

ponsuke-tarou.hatenablog.com

いろんな攻撃手法を薄く広く知る

前回の勉強内容

ponsuke-tarou.hatenablog.com

今回の勉強内容 : いろんな攻撃手法を薄く広く知る

勉強のきっかけになった問題

データの破壊,改ざんなどの不正な機能をプログラムの一部に組み込んだものを送ってインストールさせ,実行させるものはどれか。

  1. DoS攻撃
  2. 辞書攻撃
  3. トロイの木馬 << 正解
  4. バッファオーバフロー攻撃

平成20年秋期問64 トロイの木馬|基本情報技術者試験.com

Dos攻撃DDos攻撃は、サーバやサイトに大きな負荷をかけてダウンさせるサイバー攻撃です。

ponsuke-tarou.hatenablog.com

バッファオーバフロー攻撃は、メモリ領域のバッファを超えて他のメモリを上書きします。

https://wa3.i-3-i.info/img/data/5600/d005642-4.pnghttps://wa3.i-3-i.info/img/data/5600/d005642-5.png
https://wa3.i-3-i.info/img/data/5600/d005642-6.pnghttps://wa3.i-3-i.info/img/data/5600/d005642-7.png
バッファオーバーフロー攻撃とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

https://cybersecurity-jp.com/wp000/wp-content/uploads/2018/03/img_18488-01.png
バッファオーバーフローとは?攻撃・対策方法とDoS攻撃との違いを解説

DOS攻撃とバッファオーバフロー攻撃は似ているけれど違うものです。
攻撃 やり方
DOS攻撃 大量にデータを送りつけてサーバをダウンさせる
バッファオーバフロー攻撃 バッファを溢れさせて、他のメモリに書き込むところに不正プログラムを仕込んで攻撃する

ブルートフォース攻撃は、ありとあらゆる文字列の組み合わせを片っ端から試してパスワードや鍵を見つける攻撃です。

ponsuke-tarou.hatenablog.com

辞書攻撃は、パスワードによく使われる文字を片っ端から入力して不正ログインを試みます。

もちろん手動では腱鞘炎になるのでツールを使ってガッツリ攻撃してきます。
ブルートフォース攻撃より「パスワードによく使われる文字」に絞るので効率は良いです。

https://iwiz-blog-cms.c.yimg.jp/c/blog-cms/about/blog/images/inline/dictionary.jpg
「スマホを落としただけなのに」スマホのセキュリティ対策 - Yahoo! JAPANコーポレートブログ

https://tech.nikkeibp.co.jp/it/article/COLUMN/20071126/287915/09_02.jpg
第17回 失敗しないパスワード管理(前編) | 日経 xTECH(クロステック)

https://store.boxil.jp/corp_media/images/corporation_cms_media_image/5470/244/large_e2a59e01-ea34-4c73-b7c9-e015433e31a8.jpg
企業を脅かす「パスワードリスト攻撃」 拡大する不正ログインの特徴や影響、対策を解説 | サムライズ 業務改善コラム

トロイの木馬とは、便利なソフトウェアに見せかけてユーザに被害を与える不正なプログラムです。

  • 英語 : Trojan Horse

便利なツールいろいろあるなぁ・・・って、よく確認しないと「トロイの木馬」に引っかかるです!

有用なソフトウェアに見せかけて配布された後,システムの破壊や個人情報の詐取など悪意ある動作をする。
平成24年春期問54 トロイの木馬の特徴|ITパスポート試験ドットコム

例えば・・・パソコン内部の秘密のファイルをインターネット上に送信したり、ファイルやディスク内容を破壊したりします。
感染機能は持っていませんので、感染増殖することはありません。が、そのためにワクチンソフトの検出対象外となります。

感染増殖はしないので、ワクチンソフトでは、基本的にトロイの木馬を検出の対象外としています。信頼できないサイトに便利なツールソフトウェアとして掲載されていても、そのプログラムはむやみにダウンロードして実行しないようにしましょう。
ウイルス用語辞典:IPA 独立行政法人 情報処理推進機構

サラミ法は、発覚しない程度に少量ずつの金銭や物品を窃取します。

不正行為が表面化しない程度に,多数の資産から少しずつ詐取する方法である。
平成25年秋期問43 サラミ法はどれか|基本情報技術者試験.com

https://securityblog.jp/karuta_image/karuta_023nu-thumb.jpg
【ぬ】 盗み出す 額は少額 サラミ法 | セキュリティかるた | 日立ソリューションズの情報セキュリティブログ

銀行預金の利息を着服する
預金の利息計算時には必ず1円未満の端数が生じる。この端数は微々たるものであるが、全ての口座から端数を集めれば大金になる。
実際に1960年代後半、アメリカ・ニューヨークの銀行で、プログラムに細工をして1セント未満の端数処理を四捨五入からすべて切り捨てに変更し、切り捨てられた端数を自分の口座に振り込ませるように改鼠する事件があった。

他人の口座から毎月1万円程度を不正に引き出す
スキミングなどの不正な手段によって他人のキャッシュカードのコピーを手にした人間が、1ヶ月あたり1万円 - 2万円以下の額を不正に引き出していた。
架空の電子商店をでっちあげてクレジットカード番号を大量に集め、大勢の人から少額ずつ詐取した事例がある。不正に引き落とされた金額は一人あたりではごく少額だったため、ほとんどの人はカードが不正に使われたことに気が付かなかった。
サラミ法 - Wikipedia

スキャベンジングは、日本語でゴミを漁るです。

  • 英語 : scavenging(scavenge : ゴミを漁る)
  • 別名 : ゴミあさり、トラッシング、ダンプスターダイビング

プログラム実行後のコンピュータ内部又はその周囲に残っている情報をひそかに探索して,必要情報を入手する方法である。
平成25年秋期問43 サラミ法はどれか|基本情報技術者試験.com

https://wa3.i-3-i.info/img/data/6000/d006051-2.png
スキャベンジング (scavenging)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

https://www.latron.jp/sites/default/files/inline-images/social-engineering4.png
ソーシャルエンジニアリングとは | ITスクールらとろん

次回の勉強内容

ponsuke-tarou.hatenablog.com