つぶやきテック

日々のつぶやきアウトプット

Djangoでのテスト実施

Djangoのテスト

Djangoにおけるテストについての勉強記録です。 誤記や不足はコメントで指摘いただければ幸いです!

テスト実行コマンド

python manage.py test [[アプリケーション名]]

testコマンドを実行すると・・・

  • Djangoは "test" ではじまるモジュールを見つける
  • そのモジュール内でdjango.test.TestCaseクラスを継承したクラスを見つける
  • その後、TestCaseクラスに定義されているメソッドを実行

TestCaseクラスのメソッド

  • setUp → テストメソッドが呼ばれるたびに実行される
  • tearDown → テストメソッド終了後、結果が記録された後に呼ばれる
  • test○○ → アサーションメソッドを用いてテスト実行するメソッド
from django.test import TestCase
from myapp.models import Animal

class AnimalTestCase(TestCase):
    def setUp(self):
        Animal.objects.create(name="lion", sound="roar")
        Animal.objects.create(name="cat", sound="meow")

    def test_animals_can_speak(self):
        """Animals that can speak are correctly identified"""
        lion = Animal.objects.get(name="li——on")
        cat = Animal.objects.get(name="cat")

        self.assertEqual(lion.speak(), 'The lion says "roar"')
        self.assertEqual(cat.speak(), 'The cat says "meow"')

Pythonユニットテストでのモック作成

  • バージョン3.3で追加されたunittest.mockライブラリを使えばいけそうです。

実装例:

from unittest.mock import MagicMock

thing = ProductionClass()
thing.method = MagicMock(return_value=3)
thing.method(3, 4, 5, key='value')
thing.method.assert_called_with(3, 4, 5, key='value')

内部でAPI呼び出しを行う関数の単体テスト【Python】

pytest勉強中

以下のような、「内部でAPI呼び出ししている関数」の単体テストを 書くというケースに最近はじめて出会ったので、備忘メモを残します。

テスト対象コード

import requests

def get_info(**kwargs):
    node = kwargs['auth']
    app = node.get_information('sample')

    app_id = app.get_app_id()

    if app_id is None:
        raise requests.exceptions.HTTPError()

    url = 'https://sample.com/v1/app/' + str(app_id)
    headers = {'Authorization': 'Bearer ' + app.get_sample_key()}
    response = requests.get(url, headers=headers)

    try:
        response.raise_for_status()
    except requests.exceptions.RequestException as e:
        raise e

    data = response.json()
    return {'data': {'id': app.id, 'type': data} # 'type': 'sample-status'

テストコード

今回学びになったのは、mock.patchにside_effectという属性があり、 それとモック用の関数を使ってAPI呼び出しの振る舞いを再現できること。

読む人は少ないかもしれませんが、下のような感じでAPI呼び出しを モックしてテストできるようです。

def mocked_requests_get(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code):
            self.json_data = json_data
            self.status_code = status_code

        def raise_for_status(self):
            response = requests.Response()
            response.status_code = self.status_code
            try:
                response.raise_for_status()
            except requests.exceptions.HTTPError as e:
                raise e

        def json(self):
            return self.json_data

    if kwargs['headers']['Authorization'] == 'Bearer valid':
        return MockResponse('sample-status', 200)

    return MockResponse('null', 410)

class TestGetInfo(unittest.TestCase)
    @mock.patch('requests.get', side_effect=mocked_requests_get)
    def test_get_info(self, mock_get):
        expected_res = {'data': {'id': app.id, 'type': 'sample-status'}}

        res = get_info(url=url, auth=app.auth)
        assert_equals(res.status_code, 200)
        assert_equals(res.json, expected_res)

    # 異常系は省略

参考サイト

つぶやきpybabel

pybabelとは

  • Djangoなど、Pythonベースのアプリケーションで国際化のロケール別カタログを管理するツールです。
  • 言い換えるなら、「アプリケーションのこの部分は英語ではこう、日本語ではこう表示するよ」ということをあれこれやってくれるという感じです。
  • 登場人物はPOTファイル・POファイル・MOファイルの3人。ざっくりいうと、Pythonファイル(.py)からPOTファイル(.pot)をつくり、POTからPO(.po)を、POからMO(.mo)を、という流れです。

pybabelコマンド

$ pybabel (コマンド) [オプション] [引数]

extract

  • .pyファイルから.potファイルを生成するためのコマンドです。
  • 指定したディレクトリ以下を再帰的に検索し、.pyファイルに含まれる "_(...)"の内容を抽出します。
  • 例えば以下の例では、.potファイルには "ABCDE" という文字列が記載されます。
_('ABCDE')

使用例:

# -o オプションで.potファイル名を指定(デフォルトはmessages.pot)
$ pybabel extract --input-dirs=sample/src -o hoge.pot

init

  • .potファイルから.poファイルを生成するためのコマンドです。
  • オプションでドメイン名、ロケール名(言語名)、入力ファイルパス、出力ディレクトリなどを指定できます。
# -lオプション:ロケール名
# -iオプション:入力ファイルパス
# -dオプション:出力ディレクトリ
$ pybabel init -l ja -i hoge.pot -d ./sample_app/translations

compile

  • 国際化定義情報をバイナリファイルにコンパイルします。
  • ファイル拡張子で言うと、.poファイルを基にして .moファイルを生成します。
# -dオプションでコンパイル元のファイルがあるディレクトリを指定します
$ pybabel compile -d ./sample_app/translations

update

  • .potファイルの変更内容を .poファイルに反映します。
  • イメージとしては "init" で初回の.poファイル生成、それ以降の更新は "update" で、という感じです。
# -iオプションで .potファイルのパスを指定します
$ pybabel update -i hoge.pot -d ./website/translations

参考

つぶやきIPsecパススルー

IPsecパススルーとは?

  • ESPによってIPパケットのカプセル化を行って通信するとき、ちょっとした問題が起こることがあります。
  • というのも、ESPヘッダにはポート番号のフィールドがないので、そのままだとNAPT環境(変換のため、ポート番号もチェックされる!)において通信することができないのです。
  • そんな時に、NAPT環境でもIPsecを行うための技術がIPsecパススルーです。
  • NAPT機能をもったブロードバンドルータ上などで動作します。

IPsecパススルーの機能と先着一名問題

  • ざっくり言うと、ESPでカプセル化されたパケットを特別扱いして、IPアドレスだけを変換します。
  • この時に、そのパケットの送信元IPアドレスを覚えておいて、戻りのパケットが送り主にちゃんと戻るように中継します。
  • しかしNAPT装置においてはセッションを識別できない(各パケットの関係性を知ることができない)ことから、1つのVPN先(IPsecでの通信先)に対しては一度に1つの送信元からしか通信できないという制限があります*1
  • この制約は先着一名問題と呼ばれます。

つぶやきLDAP

LDAP(Lightweight Directory Access Protocol) とは?

  • 情報を一元管理し情報提供を行う「ディレクトリサービス」を提供するサーバへアクセスする際に使うプロトコルです。
  • 複雑で処理が重いX.500シリーズ*1のDAP(Directory Access Protocol)を軽量化し(だから "Lightweight")、TCP/IPを用いるインターネットで使えるようにしたものです。

LDAPのキーワード

LDAP識別名(DN:Distributed Name)

  • LDAPによりディレクトリサービスにアクセスする際に、その対象を指定する手段です。
  • 複数のLDAP相対識別名(RDN) をカンマで区切って並べたものです。
  cn=poodle, cn=Dog, dc=sample, dc=com
  # ドメイン「sample.com」のコンテナ「Dog」に配置したデータ「poodle」を示すDN。
  # 因みにcnは "Common-Name", dcは "Domain-Component" のことです。

LDAP認証・LDAP連携

  • Apacheなどのグループウェアサーバで、LDAP連携の設定をしておくとグループウェアサーバ側にアカウント情報を入力しなくとも、LDAPに登録されたアカウント情報をもとに自動でアカウント作成できる機能です。

設定例*2

// sample-serverの設定を表示
# show running-config sample-server LDAP 
aaa-server LDAP protocol ldap
aaa-server LDAP (dmz) host 192.168.10.50
  ldap-base-dn dc=example,dc=com
  ldap-scope subtree
  ldap-naming-attribute sAMAccountName
  ldap-login-password *****
  ldap-login-dn cn=Administrator,cn=Users,dc=example,dc=com
  server-type microsoft
  ldap-attribute-map CSC

// LDAP Attribute Map の設定
# show running-config ldap attribute-map CSC
map-name memberOf Group-Policy
map-value memberOf CN=CSCO_VPN,OU=ENGINEERING,DC=example,DC=com GroupPolicy-CSC

// Connection Profile と Group Policy の設定
# show running-config tunnel-group TunnelGroup-CSC
tunnel-group TunnelGroup-CSC type remote-access
tunnel-group TunnelGroup-CSC general-attributes
authentication-server-group LDAP

つぶやきLACP

LACP(Link Aggregation Control Protocol)

  • リンクアグリゲーションを自動構成するためのプロトコルです。
  • IEEE802.3ad で規格化されていて、さまざまなベンダが混在したネットワーク環境で使用します。

2つのモード

Activeモード

  • いわば「肉食系」モードです。
  • PAgP(シスコ独自のLACP)のDesirableモードに相当します。
  • 自分からLACPDU(LACP Data Unit)を送信し、積極的に論理リンクをつくろうとします。

Passiveモード

  • 「草食系」モードです。
  • PAgPのAutoモードに相当します。
  • 自分からはLACPDUを送信しませんが、受け取ったら論理リンクをつくります。

◆一般的なネットワーク設定ではどちらもActiveにすることが多いです。*1

SWでの設定例

    (config)# vlan 300                               // ポートVLAN(ID300)を定義
      [vlan 300]
    (config)# untagged-port 0/0-6          // ポート0/0~0/6をUntaggedポートに設定
      [vlan 300]
    (config)# router-interface VLAN300  // VLAN名称 "VLAN300" を設定
      [vlan 300]
    (config)# ip 192.168.3.2/24                // VLAN300のIPアドレスを設定
      [vlan 300]
    (config)# exit
    (config)# link-aggregation 10            // LAG IDに10を定義
      [link-aggregation 10]
    (config)# mode lacp                           // LACPを使ったLAGだと設定
      [link-aggregation 10]
    (config)# lacp-activity passive            // Passiveモードを選択
      [link-aggregation 10]
    (config)# key 10                                 // LAGグループが所属するポートのkeyを10に設定
      [link-aggregation 10]
    (config)# aggregated-port 0/3-6       // 0/3~0/6をLAGグループに属するポートに指定
      [link-aggregation 10]
    (config)# exit

LACPリンクアグリゲーションの設定(レイヤ2&レイヤ3機能) より)

*1:みやたひろし『ネットワーク技術&設計入門』(SB Creative)

つぶやきIPsec

「属性」:IPsecとは?

  • IP Security Architecture、もしくはSecurity Architecture for IPの略です。
  • IETF(Internet Engineer Task Force)が中心となって標準化を行ったネットワークセキュリティ技術で、仮想プライベートネットワーク(VPN)の通信プロトコルなどとして幅広く採用されています。(https://www.otsuka-shokai.co.jp/words/ipsec.html)

「機能」:IPsecは何をするのか?

  • インターネットなどのTCP/IPネットワークで暗号通信を行います。
  • 暗号化や認証方法が複数用意されていることから、通信の用途や必要なセキュリティポリシーによって、自分の環境に合わせた設定が行えます。

「要素」:IPsecを支える概念・技術とは?

SA (Security Association)

  • IPsecピア間で確立される単方向のコネクションです。
  • 双方向通信の場合は2つのSAが確立されます。

SPI (Security Parameters Index)

  • 32ビットで構成されます。
  • IPsec通信の各パケットに挿入され、そのパケットに適用されたSAの識別キーとなります。

SP (Security Policy)

  • IPsecルータが選択する、パケット処理のポリシーです。
  • セレクタと呼ばれるキーを使ってポリシーを選びます。セレクタにはIPアドレス、プロトコル、ポート番号などが使われます。
  • ポリシーは下に示す3種類です。

  • PROTECT: IPsecを適用して送信

  • BYPASS: IPsecを適用せずに送信
  • DISCARD: パケットを廃棄する

IKE (Internet Key Exchange)

  • 共通鍵のもとになる値を交換するプロトコルです
  • DH鍵交換方式を改良しました
  • UDPのポート500番を使用します

ESP (Encapsulating Security Protocol)

  • IPsecにおいて暗号化・メッセージ認証を担うプロトコルです
  • 運用モードによって暗号化範囲は異なります

AH (Authentication Header)

  • データのメッセージ認証を行います
  • 暗号化通信が禁止されている国では、ESPの代わりにこのAHが使われます

つぶやきSSO【ユーザ認証】

SSOとは

  • Single Sign-On の略で、一度ユーザ認証をするだけで関連するサーバへのアクセスについても認証する技術です。
  • ユーザの利便性の向上が期待できます。

SSOの実装方式

Cookie型

  • 認証情報を含めたCookie情報を使ってSSOを行います。

リバースプロキシ型

  • リバースプロキシにアクセスを集約します。
  • リバースプロキシで認証に成功すると、プロキシはサーバに代理アクセスし、結果をユーザに返します。

SAML(Security Assertion Markup Language)型

  • 認証情報に加え、属性情報とアクセス制御情報を異なるドメインに伝達します。
  • 同一ドメインに留まらない大規模なサイトにおいてもSSOの仕組みを導入できます。

SAMLコードの例

こちらからお借りしました。

 1: <saml:Assertion
 2:   xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
 3:   Version="2.0" IssueInstant="2005-01-31T12:00:00Z">

 4:   <saml:Issuer Format=urn:oasis:names:SAML:2.0:nameid-format:entity> ... Nature of the assertion.
 5:     http://idp.example.org
 6:   </saml:Issuer>

 7:   <saml:Subject> ... Subject of the assertion.
 8:     <saml:NameID
 9:       Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
10:       j.doe@example.com
11:     </saml:NameID>
12:   </saml:Subject>

13:   <saml:Conditions ... Additional conditions of period.
14:     NotBefore="2005-01-31T12:00:00Z"
15:     NotOnOrAfter="2005-01-31T12:10:00Z">
16:   </saml:Conditions>

17:   <saml:AuthnStatement ... Authentication statement
18:     AuthnInstant="2005-01-31T12:00:00Z" SessionIndex="67775277772">

19:     <saml:AuthnContext>
20:       <saml:AuthnContextClassRef>
21:         urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
22:       </saml:AuthnContextClassRef>
23:     </saml:AuthnContext>

24:   </saml:AuthnStatement>
25: </saml:Assertion>

つぶやきCookie

属性:Cookieとは?

  • WebブラウザとWebサーバとの間で、セッション管理を行うための情報です
  • 1994年にネットスケープコミュニケーションズ社によって提案されました

機能:Cookieは何をする?

  • ステートレス(それぞれの通信の内容をいちいち持っておかない)なプロトコルであるHTTPの上で、前回通信した状態を保持し、次のセッションに引き継ぎます
  • Webサーバは、Cookieの情報によってどのブラウザからのアクセスか識別できるようになります

要素:Cookieを支える概念・技術

Set-Cookieフィールド

  • サーバからのHTTPレスポンスヘッダ中のフィールドです
  • ブラウザを識別するためのセッションIDなどを記述します

例:

Set-Cookie: Session_id=xxx, Expires=yyy, Domain=aaa.com, Path=bbb

Cookieフィールド

  • サーバへのHTTPリクエストヘッダ中のフィールドです
  • Set-Cookieフィールドの情報を記述して返します

Secure属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • 記述されていると、HTTPS通信の場合のみCookie情報をブラウザからサーバへ送信します

Domain属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieを送信するドメインを指定します。ここで指定したドメインのサブドメインも送信範囲に含まれます

Path属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieを送信するURLディレクトリを指定します

Expires属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookieの有効期限を指定します。未指定のとき、有効期限はブラウザ終了時までです

HttpOnly属性

  • Set-Cookieヘッダ、Cookieヘッダに記述できる情報です
  • Cookie情報をJavaScriptコードが利用することを禁止します

つぶやきOSPF

OSPF(Open Shortest Path First)

  • LSA(Link State Advertisement)という情報をもとに、ルーティング情報を作成していくプロトコルです。
  • ネットワークに接続されたリンクをコストに換算し、そのコストが最小になるようにルーティングテーブルを作成していきます。
  • このルーティングアルゴリズムはリンクステートアルゴリズムと呼ばれます。

ルーティングテーブルの例*1

Router#show ip ospf route
============ OSPF network routing table ============
N     10.1.1.0/24         [10] area: 0.0.0.1
                          directly attached to port-channel0
N     20.1.1.0/24         [20] area: 0.0.0.1
                          via 10.1.1.2, port-channel0
N     30.1.1.0/24         [20] area: 0.0.0.1
                          via 10.1.1.2, port-channel0
N IA  40.1.1.0/24         [10] area: 0.0.0.1
                          via 10.1.1.3, port-channel0
N IA  40.1.2.0/24         [10] area: 0.0.0.1
                          via 10.1.1.3, port-channel0

============ OSPF router  routing table =============
R    192.168.30.4         [10] area: 0.0.0.1, ABR, ASBR
                          via 10.1.1.3, port-channel0

============ OSPF external routing table ===========
N E1  50.1.1.0/24         [20] tag: 0
                          via 10.1.1.3, port-channel0

DR, BDR

  • OSPFを適用するネットワークでは、そのセグメントの中で最も高いプライオリティ値をもつルータがDR(Designated Router: 指名ルータ、代表ルータ)として選出されます。
  • 次に高いプライオリティ値をもつルータはBDR(Backup DR)となります。
  • ネットワーク内の各ルータは、代表ルータに対してルータLSAを送信し、代表ルータはそれをもとにネットワーク全体の情報(ネットワークLSA)を作成します。

エリア

  • OSPFにおいて、LSAを交換する範囲をエリアと呼びます。
  • エリア0はとくにバックボーンエリアと呼ばれます。

5種類のパケット*2

タイプ1:Hello

  • ネイバー(論理的に隣接したルータ)を検出するためのパケットです。
  • ネイバー検出後、キープアライブ(生存確認)にも使われます。
  • マルチキャストで送信されます(224.0.0.5)*3
  • このHelloパケットを出さないように設定された機器はパッシブインターフェースと呼ばれます。

タイプ2:DBD

  • 自身のLSDB(Link State DataBase)に含まれているLSAのリスト一覧が載っています。
  • ネイバーとこのパケットを交換することで、自身のLSDBに不足しているLSAを認識します。

タイプ3:LSR

  • 自身のLSDBに不足があった場合、ネイバーにそのLSAを要求するために使用されます。

タイプ4:LSU

  • LSRによりネイバーから要求されたLSAを送信するために使用されます。

タイプ5:LSAck

  • LSUを受信したことを通知する確認応答として利用されます。

5種類のLSA

エリア内部のみに伝播するLSA

Router-LSA

  • そのルータがどのネットワークに接続されているかを表します。
  • IPアドレス、リンクの種類、ルータID、コストなどが含まれます。

Network-LSA

  • そのネットワークにはどのルータが接続されているかを表します。
  • 同一リンク内にあるルータの内DR(代表ルータ)が生成します。

ASBR-Summary-LSA

  • AS境界ルータのIDとそこに到達するためのコスト情報を表します。
  • ABR(エリア境界ルータ)が作成します。

エリア内部とバックボーンエリアに伝播するLSA

Network-Summary-LSA

  • 他のエリアの情報を要約したものです。
  • ABR(エリア境界ルータ)が作成します。

OSPFドメイン全体に伝播するLSA

AS-External-LSA

  • ASの外側にあるネットワーク情報を表します。
  • ASBR(AS境界ルータ)が作成します。

*1:https://www.furukawa.co.jp/fitelnet/f/man/60/command-show/show/show_ip_ospf_route.htm

*2:https://www.infraexpert.com/study/ospfz5.html

*3:過去のネスペ試験で、「OSPFはマルチキャスト通信だからIPsecでカプセル化できないよ。GRE over IPsecを使おうね」という問題が出てました^^