Skip to main content

TerraformとPyTestを使ったクラウドインフラの自動テストツールの作成

2020年3月27日

0 分で読めます

最近、Fugue向けの自動テストツールを作成する仕事を任されました。Fugueはクラウドリソースのコンプライアンスとセキュリティを監視するサービスです。Fugueのスキャン結果全体が正しいことを検証する方法が必要でした。ローカル環境またはCIで実行でき、構成可能なインフラをデプロイし、Fugueでスキャンして、その結果を検証する自動システムの作成が目標でした。この記事では、社内自動テストツールとなったautotestの設計と実装のプロセスを紹介します。

ここではTerraformとFugue APIを使用しますが、フィクスチャの設計はあらゆるCLIコマンドやAPIに応用できます。そのため、ここで紹介する考え方は、ほかのユースケースにも簡単に適用できます。

設計

本格的にプロジェクトに着手する前に、数日かけて調査し、課題を理解しようとしました。Google検索でいくつか調べた結果、このツールの基盤にpytestフレームワークを採用することにしました。以前、pytestをユニットテストで使ったことはありましたが、今回はその仕組みを詳しく調べ、機能テストの基盤として活用する方法を学ぶ絶好の機会でした。

テスト手順は、次の3つのステップに分けられます。

  1. Terraformでモジュール式のインフラをデプロイする

  2. このインフラを参照するFugue環境を作成してスキャンする

  3. スキャン結果を取得して検証する

ステップ1にはTerraformを使うと決めていました。既存のインフラテスト用Terraform構成がいくつかあり、TerraformはAWS、Azureをはじめ、多数のクラウドサービスプロバイダーに対応しているためです。ステップ2では、Fugue APIを使って環境を作成し、スキャンを開始できます。最後に、ステップ3でもFugue APIを使い、スキャン結果全体を取得して検証できます。

大まかな設計が固まったので、pytestを調べ、設計を実装するための使い方を確認しました。

Terraformによるインフラストラクチャの作成、Fugue APIクライアントと環境のセットアップ、リソースIDの検証、ワークスペースの破棄を示すワークフロー図。

PyTest

pytestは、テストの検出、Python組み込みの<code>assert</code>文を使ったアサーション、依存関係を管理するフィクスチャを備えたPython用のテストフレームワークです。

フィクスチャはpytestの真価を発揮する機能です。テスト依存関係のライフサイクルを管理するデコレートされた関数です。従来ならsetUp()やtearDown()メソッドに記述していたセットアップとクリーンアップのコードを、フィクスチャに記述します。フィクスチャのスコープを指定すると、その出力をクラス、モジュール、セッション間で再利用できます。

例を見てみましょう。ここでは、APIにアクセスするフィクスチャを定義して使用します。ユニットテストではモックAPIオブジェクトを使いますが、機能テストでは実際のAPIを使う必要があります。

@pytest.fixture(scope="session")
def api_client(creds):
  api_client = api.initialize_client(creds)
  return api_client

def test_api_client_username(api_client):
  assert api_client.username == "mike"

def test_api_client_host(api_client):
  assert api_client.host == "https://api.fugue.co"

api_clientフィクスチャは@pytest.fixtureデコレーターで宣言します。また、デコレーターのscope引数を使って、フィクスチャのscopeを設定できます。APIクライアントはすべてのテストで安全に再利用できるため、sessionスコープにしました。フィクスチャはテスト関数やクラスと同じモジュール内に定義することも、conftest.pyに記述してすべてのテストモジュールから使用できるようにすることもできます。

テスト関数の引数にフィクスチャ名を指定するだけで、フィクスチャを使えます。この例では、2つのテストでapi_clientフィクスチャを使用しています。フィクスチャのスコープをsessionにしたため、pytestは各テストセッション中にフィクスチャが一度だけ呼び出されるようにします。

api_clientフィクスチャが入力パラメーターcredsを受け取っていることに気づいたかもしれません。fugue_api関数を直接呼び出してはいないのに、credsにはどのように値が設定されるのでしょうか。

creds自体がフィクスチャだと思った方には、金星を差し上げます。⭐️ フィクスチャから別のフィクスチャを呼び出せるため、複雑な依存関係もフィクスチャを連鎖させて構築できます。credsの定義を見てみましょう。

def pytest_addoption(parser):
         parser.addoption(
             "--api-secret", action="store",
             help="name of credstash secret to use when 
initializing the API"
        )

@pytest.fixture(scope="session")
def creds(request):
  """returns API credentials"""
  secret_name = request.config.getoption("--api-secret")
  return credstash.getSecret(secret_name)

セキュリティの基本を守るため、credsではcredstashを使ってシークレット値を保存、取得しています。シークレット名はpytestのコマンドラインオプションとして渡します。オプションはpytest_addoptionで定義し、requestフィクスチャを介して参照します。credsフィクスチャを使うことで、認証情報を取得する実装を簡単に抽象化し、各テストやフィクスチャに必要な入力に集中できます。認証情報の取得方法を後で変更しても、修正が必要なのはcredsだけです。

pytestフィクスチャの基本を理解したところで、フィクスチャを使って設計を実装する方法を見ていきましょう。

ステップ1:Terraformを使ったインフラのデプロイ

ツールの最初のステップでは、スキャン対象となるインフラを作成し、ステップ2と3で検証の基盤として使用します。Terraformでインフラをデプロイすることは決めていましたが、具体的にどう実現すればよいでしょうか。

設計

├── aws
| ├── api_gateway
│ │ ├── aws_api_gateway.tf
│ │ ├── aws_api_gateway_client_certificate.tf
│ ├── autoscaling
│ │ ├── aws_autoscaling_group.tf
│ │ ├── aws_autoscaling_lifecycle_hook.tf
│ │ ├── ...

このコード例は、既存のテスト構成の構造を示しています。これらの構成は、aws/ルートからterraform applyを実行するか、aws/api_gatewayなどのサービスサブディレクトリから実行して、手動でデプロイできます。テストするサービスを選べるよう、このモジュール性は維持したいと考えました。既存の構造でTerraformを実行することもできますが、それは避けるべきです。ファイルシステム上の処理はすべて固有の一時ディレクトリで実行し、テストを制御された環境で行う必要があります。そのため、一時的なワークスペースを管理する方法が必要です。また、Terraformを呼び出して出力を記録し、エラーを確認する方法も必要です。Terraformは実際の(高額な)インフラを作成するため、問題が起きた場合にインフラを削除するエラー処理が不可欠です。

まとめると、最初のステップで必要なことは次のとおりです。

  1. 一時的なワークスペースを作成、管理する

  2. テスト構成をワークスペースにコピーする

  3. Terraformを呼び出し、エラー時には作成済みのインフラを削除する

1と2はフィクスチャで処理できそうですが、Terraformを使ったインフラ作成のように複雑でエラーが起きやすい処理も、フィクスチャにできるのでしょうか。

「できる」と答えた方にも、金星を差し上げます。⭐️ ワークスペースとTerraformのフィクスチャを定義する方法を詳しく見てみましょう。

ワークスペースのフィクスチャ

@pytest.yield_fixture(scope="class")
def workspace(tmpdir_factory, provider, services):
    """returns an initialized workspace that closes after 
it's finished"""
    working_dir = tmpdir_factory.mktemp("autotest_tf")

    with Workspace(working_dir, provider, services) as w: 
         yield w
class Workspace:
    def __init__(self, base_dir: str, provider: str, services: List[str]) -> 
 'Workspace':
          self.provider = provider
          self.base_dir = base_dir
          self.working_dir = os.path.join(base_dir, provider)
          self.services = services

    def __enter__(self):
       return self._initialize_workspace(self.base_dir, self.provider, self.services)

    def __exit__(self, typ, value, traceback):
        pass

6行のworkspaceには多くの処理が詰まっています。まず、workspaceがyield_fixtureとして定義されている点に注目してください。これは、関数がreturnではなくyieldを使って呼び出し元に制御を戻すという意味です。その間、フィクスチャの実行は一時停止し、コンテキストマネージャーは開いたままになります。制御がフィクスチャに戻ると、yield文の後にあるコードが実行されます。この例ではWorkspaceコンテキストマネージャーが終了します。pytestはyield_fixtureから返された値を処理するため、通常のフィクスチャと同じように扱えます。workspaceはクラススコープのフィクスチャなので、テストクラスごとに新しいワークスペースが作成されます。これにより、AWSとAzureのテストをクラスごとに分け、プロバイダーごとに新しいワークスペースを確実に作成できます。

次に、workspaceが3つのフィクスチャ、tmpdir_factory、provider、servicesに依存していることがわかります。tmpdir_factoryは、一意の一時ディレクトリを返す組み込みフィクスチャです。--basetemp=DIRECTORYオプションでベースディレクトリを手動設定でき、デバッグに便利です。providerとservices は独自に定義したフィクスチャで、現在のテスト対象プロバイダーと、入力で指定されたサービスのリストを返します。

フィクスチャの気に入っている点の一つは、明確な抽象化を促してくれることです。テストやフィクスチャへの入力は関数定義というインターフェースを通じて指定され、実装はフィクスチャの定義内に隠されます。フィクスチャのモジュール性のおかげで、workspaceの入力ごとに個別のフィクスチャをすばやく簡単に作成できます。そのため、workspace内で値を組み立てる誘惑にかられずに済みます。

最後に、Workspaceがコンテキストマネージャークラスである点にも注目してください。これにより、フィクスチャ自体の終了時にワークスペースが自動的にクローズされます。前述のとおり、yield文を使うと、フィクスチャの終了時に制御が戻るまでコンテキストマネージャーは終了しません。autotestの設計全体を通じて、この強力なパターンを採用しました。使用するTerraform構成のワークスペースへのコピーはinitialize_workspaceで行います。ここでは読者への課題として残しておきます。

Terraformのフィクスチャ

@pytest.fixture(scope="class") 
def terraform(workspace): 
     """initialize Terraform in workspace""" 
     return initialize_terraform(workspace.working_dir) 

@pytest.yield_fixture(scope="class") 
def infra(request, terraform, services):
    """returns a Terraform instance associated with created resources""" 
    with build_infra(terraform, services): 
         yield terraform

@pytest.yield_fixture(scope="class") 
def terraform_resources(infra): 
    """returns the Terraform resources map""" 
    yield infra.tfstate.modules[0]['resources']

Terraformのフィクスチャは、terraform、infra、terraform_resourcesの3つで構成されます。フィクスチャの連鎖によって、Terraformのstateファイルから読み取ったTerraformリソースの辞書が得られます。terraformはワークスペース内でTerraformを初期化し、infraはterraform planとterraform applyを実行してインフラを構築し、terraform_resourcesはリソースマップを取り出します。

初期化とリソースマップの抽出は簡単ですが、terraform_resourcesをyield_fixtureにする必要がある点に注意してください。infraがyield_fixtureだからです。terraform_resourcesが値を返すと、infraが開いたままにしているコンテキストが閉じられ、クリーンアップコードが実行されてしまいます。

コンテキストマネージャークラスの代わりに、infraでは関数ベースのコンテキストマネージャーbuild_infraを使います。定義は次のとおりです。

 @contextmanager
 def build_infra(t: Terraform, services: List[str]):
    try:
       code, out, err = t.plan(out='temp.plan')
       if code == 1:
             raise TerraformPlanError(out, err)
       code, out, err = t.apply(dir_or_plan='temp.plan')
       if code == 1:
            raise TerraformApplyError(out, err)
    except TerraformApplyError:
         code, out, err = t.destroy()
         if code != 0:
             raise TerraformDestroyError(out, err)
         raise

 try:
    yield t
 finally:
    code, out, err = t.destroy()
    if code != 0:
        raise TerraformDestroyError(out, err)

build_infraはpython-terraformパッケージを使ってTerraformを呼び出し、出力を収集します。すべての操作でエラーコードを確認し、エラーがあれば独自の例外を発生させます。t.planとt.applyは、それぞれterraform planとterraform applyを呼び出してインフラを計画、作成します。terraform applyは、インフラの作成が一部完了した状態で失敗することがあります。terraformは作成済みのインフラを自動で削除しないため、TerraformApplyErrorを捕捉し、t.destroyを手動で呼び出してから、元の例外を再度発生させます。

build_infraはジェネレーターです。returnの代わりにyieldを呼び出すことで、@contextmanagerデコレーターを使ってコンテキストマネージャーに変換できます。yieldを囲むtry...finallyブロックにより、呼び出し元のコンテキストで例外が発生してもクリーンアップコードが実行されます。

最後に、exceptブロックとfinallyブロックのコードが似ている点に注目してください。どちらも、実行中に何が起きてもインフラを削除する処理です。finallyブロック内のコードは、例外が発生した場合も、発生しなかった場合も実行されるため、tryブロックをまとめられます。

さらに、t.planはリソースを作成しないため、tryブロックの外に移動できます。一般に、tryブロックの範囲はできるだけ狭く保つのがよい習慣です。最終的なbuild_infraコンテキストマネージャーは次のようになります。

 @contextmanager
 def build_infra(t: Terraform, services: List[str]):
    code, out, err = t.plan(out='temp.plan')
    if code == 1:
       raise TerraformPlanError(out, err)
    try:
        code, out, err = t.apply(dir_or_plan='temp.plan')
        if code == 1:
            raise TerraformApplyError(out, err)
        yield t
    finally:
         code, out, err = t.destroy()
         if code != 0:
              raise TerraformDestroyError(out, err)

ステップ2:Fugue環境の作成とスキャン

大まかな設計の次のステップでは、Fugue APIを使って、ステップ1でインフラを作成したアカウント内に環境を作成し、スキャンします。

設計

Fugue APIはSwaggerを使って定義されたREST APIです。そのため、HTTP呼び出しではなくネイティブの関数や型を使ってAPIにアクセスできるクライアントを簡単に生成できます。クライアントが動作するようになれば、環境を作成してスキャンできます。この処理は3つのステップに分けられます。

  1. Fugue APIのクライアントを生成して設定する

  2. クライアントを使って環境を作成する

  3. クライアントを使ってスキャンを開始し、完了を待つ

Swagger APIクライアント

swagger-codegenを使い、Fugue API定義に基づいてクライアントを生成しました。

swagger-codegen generate -i swagger.yaml -l python -o .

APIクライアント用のPythonパッケージ全体が生成されましたが、必要なかったので、クライアントコードをそのままautotestにコピーしました。次に、以下のようにクライアントを初期化しました。

 def initialize_client(creds: dict) - ApiClient:
    c = Configuration()
    c.host = os.environ["FUGUE_API_URL"] + os.environ.get("FUGUE_API_VERSION", "v0")
    c.username = creds["username"]
    c.password = creds["password"]

    client = ApiClient(configuration=c)
    return client

ここでcredsはフィクスチャではなく、単なる入力パラメーターです。initialize_clientはフィクスチャでもテストでもないためです。initialize_clientは、credsフィクスチャに依存するフィクスチャから呼び出されることを思い出してください。

 @pytest.fixture(scope="session")
 def api_client(creds):
     """returns a Fugue API client"""
     return api.initialize_client(creds)
@pytest.fixture(scope="session")
def environments_api(api_client):
     """returns a Fugue Environment API instance"""
     return api.environments_api(api_client)
 @pytest.fixture(scope="session")
 def scans_api(api_client):
     """returns a Fugue Scans API instance"""
     return api.scans_api(api_client)

APIクライアントは終了処理が不要なので、environments APIのフィクスチャ定義は簡単です。Swaggerで生成されたクライアントには、APIへの接続を管理するベースAPIクライアントと、APIの各トップレベルの区分に対応する個別のクラスがあります。各クラスのメソッドとして、API操作を利用できます。

抽象化について:apiモジュールを介して、Swaggerクライアントの詳細を抽象化しています。これはインターフェースの両側を抽象化するという原則に沿ったもので、クライアントのインターフェースに変更が生じた場合にも柔軟に対応できます。APIを使った環境の作成について説明する際に、これをさらに詳しく見ていきます。

環境の作成とスキャン

最初に作成した環境フィクスチャは、次のようなものでした。

 @pytest.yield_fixture(scope="class")
  def environment(environments_api, aws_creds,
 survey_resource_types, services):
     environment = 
 environments_api.create_environment(CreateEnvironmentInput
 (
          name="autotest-123",
          provider="aws",
          provider_options=ProviderOptions(
              aws=ProviderOptionsAws(
                  region="us-east-2",
                  role_arn=aws_creds
              )
         ),
        survey_resource_types=survey_resource_types,
        compliance_families=["FBP"]
    ))
   yield environment
   environments_api.delete_environment(environment.id)

これは、environments APIのcreate_environmentメソッドをそのまま適用したものです。aws_creds、survey_resource_types、servicesの各フィクスチャから認証情報と入力パラメーターを取得します。クラウドプロバイダーごとにクラスを分けてテストを整理しているため、このフィクスチャのスコープはクラス単位です。最後に、テスト終了時に環境を自動的に削除できるよう、環境をyieldします。

このフィクスチャは設計がシンプルで、必要なことを実行できます。このままにして先に進むこともできました。しかし、このシンプルなアプローチにはデメリットがあります。create_environmentへの入力には多数のフィールドがあり、一部はプロバイダーによって異なるため、扱いが煩雑です。フィクスチャ内でenvironments APIを直接使うと、巨大で読みにくい関数を作らずにcreate_environmentの入力パラメーターを準備する柔軟性が限られます。読みやすさと再利用性を両立させるのが難しかったため、再利用性をあきらめ、プロバイダーをハードコードしたうえで、Azure環境用にenvironmentフィクスチャを複製しましたが、これは良い解決策ではありませんでした。本当に必要なのは、フィクスチャのコードとenvironments APIの間にもう一つのレイヤーを設け、扱いにくい入力の準備をカプセル化し、フィクスチャとAPIの関係を管理することです。幸い、apiモジュールがまさにその役割を果たします。

入力の準備とAPIの呼び出しを切り分け、apiモジュール内の関数にまとめました。

 # api.py
 def create_environment(
     environments_api: EnvironmentsApi,
     provider: str,
     creds,
     services: List[str],
     compliance_families: List[str] = None,
     survey_resource_types: List[str] = None,
     survey_resource_groups: List[str] = None
 ) -> Environment:
   if provider == "aws":
       provider_options = ProviderOptions(
           aws=ProviderOptionsAws(
               region="us-east-2",
               role_arn=creds
           )
       )
   elif provider == "azure":
      provider_options = ProviderOptions(
          azure=ProviderOptionsAzure(
              tenant_id=creds["ARM_TENANT_ID"],
              subscription_id=creds["ARM_SUBSCRIPTION_ID"],
              application_id=creds["ARM_CLIENT_ID"],
              client_secret=creds["ARM_CLIENT_SECRET"],
              survey_resource_groups=survey_resource_groups,
           )
     )
     survey_resource_types = []
  else:
      raise AttributeError("invalid provider")

 environments_api.create_environment(CreateEnvironmentInput( 
      name=f"autotest-{provider}", 
      provider=provider, 
      provider_options=provider_options, 
      survey_resource_types=survey_resource_types, 
      compliance_families=compliance_families 
  ))  
  return environment 

この関数は長いものの、AWSとAzureの両方に対応しており、environmentフィクスチャを基本的な処理だけに絞れます。

 @pytest.yield_fixture(scope="class")
 def environment(
     environments_api,
     provider: str,
     aws_creds: str,
     azure_creds: dict,
     survey_resource_types: List[str],
     survey_resource_groups: List[str],
     services: List[str],
 ):

     """creates a Fugue Environment and deletes it automatically"""
     if provider == "aws":
         creds = aws_creds
         compliance_families = ["FBP"]
     elif provider == "azure":
         creds = azure_creds
         compliance_families = ["CISAZURE"]

     environment = api.create_environment(
         environments_api,
         provider,
         creds,
         services,
         compliance_families,
         survey_resource_types,
         survey_resource_groups
  ) 
  yield environment  
  api.delete_environment(environments_api, environment)

同じアプローチで、環境内のスキャンを開始できます。

 @pytest.fixture(scope="class")
 def scan
    terraform_resources: dict, #terraform resources must exist before scan
    environment: Environment,
    scans_api: ScansApi
 )-> Scan:
    """creates a Fugue Scan and waits for it to finish"""
    return api.create_scan(
         scans_api,
         environment
  ) 

出力を使わなくてもterraform_resourcesフィクスチャを含めることで、スキャン開始前にリソースが作成されていることを保証できます。次に、apiモジュールでは次のようにします。

  def create_scan(scans_api: ScansApi, environment: Environment) -> Scan:
      scan: Scan = scans_api.create_scan(environment.id)

      while scan.status not in ["ERROR", "SUCCESS", "CANCELLED"]:
          time.sleep(1)
          scan = scans_api.get_scan(scan.id)
      if scan.status != "SUCCESS":
          print(scan.message)
      assert scan.status == "SUCCESS"

      return scan

Terraformを使ったリソースの作成と、Fugue環境の作成およびスキャンを行うフィクスチャが揃いました。これで、テストを書く準備はほぼ完了です。

ステップ3:スキャン結果の取得と検証

テストを書く前に、Fugue APIからスキャン結果を取得できるようにする必要があります。スキャン結果は、APIのカスタムルールテスト入力エンドポイントから取得できます。このフィクスチャの作成には、上で使った概念をそのまま適用できます。

 @pytest.fixture(scope="class")
 def scan_resources(scan: Scan, custom_rules_api: CustomRulesApi) -> dict:
      """returns the results from scan Scan"""
      return api.get_scan_resources(custom_rules_api, scan.id)

get_scan_resourcesは、単に呼び出しをそのまま受け渡すだけです。

 def get_scan_resources(custom_rules_api: CustomRulesApi, scan_id: str) -> dict:
     scan_resources: ScanResources = custom_rules_api.test_custom_rule_input(scan_id)
     return scan_resources.resources

このような単純な関数では、抽象化レイヤーを省略してAPI呼び出しをフィクスチャに直接記述したくなるかもしれません。実際、この関数の最初のバージョンではそうしていました。しかし、これはリーキーな抽象化、つまり隠すはずの基盤機能を一部露出させてしまう抽象化を生み出します。リーキーな抽象化は、抽象化を使う際の認知負荷を増大させ、軽減するどころではありません。

scan_resourcesフィクスチャができたので、テストに必要な入力はすべて揃いました。前のセクションで説明した準備や抽象化をすべて経て、テスト自体はわずか数行のコードで済みます。

  # test_aws.py
  class TestAWS:
     def test_verify_resource_ids(self, terraform_resources, scan_resources, check):
          for tf_id, tf_resource in terraform_resources.items():
              check.is_true(verify.verify_resource_id(tf_id, tf_resource, scan_resources))

checkは、失敗として扱われないアサーションを提供するpytestプラグインのフィクスチャです。verify_resource_idは、2つのリソースを比較し、リソースIDが同じ場合にtrueを返す単純な検証関数です。

  def verify_resource_id(tf_id: str, tf_resource: dict, scan_resources: dict) -> bool:
      """verify that a resource in the terraform state file is in the scan output"""
      # skip data sources
      if tf_id.startswith('data.'):
          return True
      print(f"verifying {tf_resource['type']} {tf_resource['primary']['id']}...", end="")
      for resource in scan_resources.values():
          if tf_resource['primary']['id'] == resource['_skeleton']['primary'] ['id']:
               print("✅")
               return True
       print("❌")
       return False 

より複雑なテストを書きたい場合は、リソースの詳細情報をすべて利用できますが、今のところはインフラを立ち上げ、正しくスキャンされることを検証するだけで十分です。テストを実行すると、次の出力が得られます。

 ) pytest autotest --services sns
 ============================ test session starts ============================
 platform darwin -- Python 3.6.5, pytest-5.3.5, py-1.7.0, pluggy-0.13.1
 plugins: cov-2.6.1, check-0.3.7
 collected 1 item / 1 selected

 autotest/test_aws.py building infrastructure in sns
 creating environment
 environment abcdef12-abcdef12-abcdef12-abcdef12-abcdef12 created
 creating scan
 scan abcdef12-abcdef12-abcdef12-abcdef12-abcdef12 created
 scan started...
 ...
 scan 588f8ded-c219-468b-821e-9b11ee06ef17 successful!
 verifying aws_default_security_group sg-abcdef12...✅
 verifying aws_default_vpc vpc-abcdef12...✅
 verifying aws_kms_key abcdef12-abcdef12-abcdef12-abcdef12-abcdef12...✅
 verifying aws_sns_topic arn:aws:sns:us-east-2:123456789012:example-topic...✅
 .
 deleting environment
 environment deleted
 tearing down infrastructure
 infrastructure successfully torn down

 =========== 1 passed in 280.80s (0:04:40) ===========

まとめ

この記事では、pytestを使って、自動インフラテストツールautotestを作成する方法を紹介しました。クリーンで強力な抽象化を簡単に構築できる、pytestのモジュール式フィクスチャの威力について説明しました。また、Fugue APIを使って環境とスキャンを作成し、それらの処理をフィクスチャにカプセル化する方法も取り上げました。さらに、Fugue APIのカスタムルールテスト入力エンドポイントを使って、スキャン内のリソースの詳細情報を取得する方法を説明しました。最後に、これらをすべて組み合わせてテストを作成しました。

最後にもうひとつ…

Fugueは、エンジニアのためにエンジニアが作った、クラウドセキュリティとコンプライアンスのソリューションです。Fugueを使うと、次のことができます。

  1. 動的な可視化とコンプライアンスレポートにより、クラウドインフラ環境とセキュリティ態勢を包括的に可視化できます。

  2. CIS Foundations Benchmark、HIPAA、PCI、SOC 2、NIST 800-53、ISO 27001、GDPR、および独自のポリシーについて、ソフトウェア開発ライフサイクルのあらゆる段階でコンプライアンスを検証できます。

  3. ベースラインの適用によりクラウドの設定ミスを防ぎ、セキュリティ上重要なクラウドインフラを自己修復できるようにします。

開発者のために設計されたIaCセキュリティ

Snykは、統合されたポリシー・アズ・コードエンジンにより、SDLCからクラウドでの実行時までInfrastructure as Codeを保護します。すべてのチームが安全に開発、デプロイ、運用できるよう支援します。

続きを読む

feature customer snowflake
Article

開発初期からセキュリティを確保:Snowflake Cortex Code向けSnyk Studioインテグレーションを発表

Snyk StudioがSnowflake Cortex Codeと連携し、開発中にAI生成コード、依存関係、コンテナの脆弱性をスキャンします。

Article

Miasmaサプライチェーン攻撃:@redhat-cloud-servicesのnpmパッケージで悪意あるコードを確認

Miasmaと呼ばれるサプライチェーンワームが、@redhat-cloud-servicesの数十件のnpmリリースで見つかりました。悪意あるpreinstallフックは認証情報を窃取し、クラウドIDを調査して、他のパッケージを再公開する可能性があります。

Blog

QinglongタスクスケジューラーのRCE脆弱性が悪用され、暗号資産マイニングに利用

Qinglongタスクスケジューリングパネルに存在する2つの認証バイパス脆弱性(CVE-2026-3965、CVE-2026-4047)が実際に悪用され、暗号資産マイニングマルウェアが展開されました。何が起きたのか、攻撃の手口、そしてセルフホスト型アプリケーションの運用者がこのインシデントから学ぶべきことを解説します。