Skip to main content

Pythonとfaker-securityでセキュリティデータを生成する

著者

Michael Aquilina

feature python code purple

2022年4月26日

0 分で読めます

Snykは最近、セキュリティデータを扱うすべての方を支援するため、Pythonパッケージfaker-securityをオープンソース化しました。このブログでは、このPythonパッケージの概要と使い方を簡単に紹介します。まずは、Pythonパッケージfactory_boyをfaker-securityと組み合わせて、開発時のテスト作成をより快適にする方法を理解するため、背景を見ていきましょう。

注:この記事を最大限に活用するには、Pythonの基本的な知識が役立ちます。

Fakerとfactory_boyを使ったテスト

faker-securityの説明に入る前に、factory_boyとFakerとは何か、そしてSnykでどのように活用しているかを見ていきましょう。

Snykは、自動テストがコードの保守性を高めると強く信じています。テストがあれば、機能の反復開発をすばやく進められ、既存の機能を誤って壊してしまう心配なく、自信を持ってコードを変更できます。

テストへの取り組みを通じて、チーム内でテストを書く人と読む人の双方にとって、テストをより簡単にする方法を探しています。Fakerとfactory_boyは、Pythonプロジェクトのテストに愛用しているパッケージです。組み合わせて使うことで、テスト対象のモデルのダミーインスタンスを生成できます。

Fakerは、ユーザー名、日付、URLなど、さまざまな種類のフィールドのダミーデータを生成できるPythonパッケージです。factory_boyは、ファクトリークラスを定義することで、Fakerのデータ生成機能をコードに組み込めるPythonパッケージです。

特にfactory_boyの優れた点は、テスト作成者がテストで重要なデータの指定に集中でき、それ以外のテストに関係しないデータはFakerに生成させられることです。これにより、必要なコード行数を減らし、気にする必要のないフィールドを取り除けるため、テストの可読性が大きく向上します。

次の例では、factory_boyを使ったテストと使っていないテストを比較して、その違いを確認しましょう。

ファクトリーを使わない場合:

from django.contrib.auth.models import User

def test_correct_email_address():
    user = User(
        first_name="Sherlock",
        last_name="Holmes", 
        username="sherlock.holmes",
        email="sherlock.holmes@baker.street",
        is_admin=False,
    )

    assert has_valid_email(user) is True

ファクトリーを使う場合:

from tests.factories import UserFactory

def test_correct_email_address():
    user = UserFactory(email="sherlock.holmes@baker.street")
    assert has_valid_email(user) is True

UserFactoryをインポートするテストは、インポートしないテストとまったく同じ動作をします。ただし、より短く読みやすく、テストに関係するフィールドが明確に示されています。一方、ファクトリーを使わないテストは長く、テストで実際に重要なフィールドが分かりにくくなります。これは比較的シンプルな例ですが、テストが複雑になるほど違いは顕著になります。

UserFactoryクラスはtests/factories.pyで一度定義すれば、すべてのテストで再利用できます:

import factory
from django.contrib.auth.models import User
from factory.django import DjangoModelFactory

class UserFactory(DjangoModelFactory):
    class Meta:
        model = User

    username = factory.Faker("slug")
    first_name = factory.Faker("first_name")
    last_name = factory.Faker("last_name")
    email = factory.Faker("email")
    is_admin = False

セキュリティデータを扱う場合、CVSSv3ベクターやCVE識別子など、セキュリティ関連フィールドのデータを生成する必要がよくあります。Fakerには、こうしたデータを標準で直接生成する方法はありませんが、独自のプロバイダーを追加できます。そこで活躍するのがfaker-securityです。

faker-securityとは?

faker-securityはFakerプロバイダーとして機能するPythonパッケージで、プロジェクト向けにセキュリティ関連データをランダムに生成できます。現在、faker-securityは次のデータ生成に対応しています:

  • CVSSv3ベクター

  • CVSSv2ベクター

  • semverバージョン

  • NPM semverバージョン範囲

  • CVE

  • CWE

今後は、Mavenのsemverのように、さらに多くの生成方法やバージョン範囲に対応したいと考えています。

ここまでの例を応用し、ダミーデータを生成するVulnerabilityFactoryを作成する場合は、次のように定義します:

import factory
from factory.django import DjangoModelFactory
from faker_security.providers import SecurityProvider
from myproject.models import Vulnerability

factory.Faker.add_provider(SecurityProvider)

class VulnerabilityFactory(DjangoModelFatory):
    class Meta:
        model = Vulnerability

    cvss_v3_vector = factory.Faker("cvssv3")
    cve_id = factory.Faker("cve")
    cwe_id = factory.Faker("cwe")

faker-securityの使い方

faker-securityはpipでインストールできます:

pip install faker-security

プロジェクトで使用する場合は、任意の依存関係ファイルに追加してください。通常は、プロジェクトのrequirements.txtファイルです。poetryやpipenvなどの上位レベルのパッケージマネージャーを使っている場合は、新しいパッケージの追加方法に関する各ツールの手順に従ってください。

インストールしたら、Fakerまたはfactory_boyを設定して、faker-securityを使えるようにします。

pytestでテストを実行している場合は、次のようにconftest.pyファイルでfactory_boyにfaker-securityを設定することをおすすめします:

import factory
from faker_security.providers import SecurityProvider

def pytest_configure():
    factory.Faker.add_provider(SecurityProvider)

今後のfaker-security

factory_boyとFakerは、テストをシンプルにするのに最適です。さらにfaker-securityを使えば、すべてのプロジェクトでセキュリティデータのダミーをすばやく簡単に生成できます。

このパッケージを私たちと同じように便利だと感じていただけたらうれしいです。ぜひコントリビューションにもご参加ください!GitHubリポジトリにスターを付け、プルリクエストやコントリビューションをお寄せください。テストを楽しみましょう!

カテゴリー: