Policy as Codeでインフラのコンプライアンスを自動実現! 「Pulumi CrossGuard」を活用してみよう

2023年7月4日(火)
大関 研丞 (Kenneth Ozeki)
第5回となる今回は、Policy as Codeの概要を解説し、「Pulumi CrossGuard」を利用してPulumiでリソースを作成する際のポリシーチェック を行うハンズオンを実践していきます。

Pulumi Programの編集

Pulumi Programを編集して、新たにポリシーチェック対象となるリソースを追加していきます。

  1. Pulumi Project用のディレクトリに移動します。
    $ cd ../program
    
    $ pwd
    /***/test-crossguard/program
  2. Pulumi Programを以下に書き換えます。ポリシーにも記載のVPC/Subnet/EC2あたりを追加で作成します。ちなみに、書き換えたProgramは先ほどカスタマイズした全てのポリシーにあえて違反するような内容となっています。
    import pulumi
    import pulumi_aws as aws
    
    # スタックの名前を取得
    stack_name = pulumi.get_stack()
    
    # スタックの設定を読み込む
    config = pulumi.Config()
    
    # S3バケットの作成
    bucket = aws.s3.Bucket("my-bucket")
    
    # VPCの作成
    vpc = aws.ec2.Vpc(
        "my-vpc",
        cidr_block="192.168.0.0/16",
    )
    # VPC IDのoutput export
    pulumi.export("vpc_id", vpc.id)
    
    # サブネットの作成
    subnet = aws.ec2.Subnet(
        "my-subnet",
        vpc_id=vpc.id,
        cidr_block="192.168.1.0/24",
        availability_zone="us-east-1a"
    )
    
    # EC2インスタンスの作成
    ami = aws.ec2.get_ami(
        filters=[{
            "name": "name",
            "values": ["amzn2-ami-hvm-*-x86_64-gp2"],
        }],
        most_recent=True
    )
    instance = aws.ec2.Instance(
        "my-instance",
        instance_type="a1.large",
        subnet_id=subnet.id,
        ami=ami.id
    )

ポリシー適用確認②

ポリシーのカスタマイズとProgramの編集ができたので、再度ポリシーチェックの様子を確認していきます。

  1. 先ほどと同様に、リソース作成のdry-runコマンド「pulumi preview」を実行します。コマンドのオプションに「--policy-pack」を指定し、先ほどの手順で作成したポリシーが置かれているディレクトリのパスを指定します。
    $ pwd 
    /***/test-crossguard/program
    
    $ pulumi preview --policy-pack ../policypack
    以下のようなポリシー違反のメッセージが表示されました。すべてのポリシーで違反しているのが確認できます。
    Previewing update (kenneth_prv_org/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/kenneth_prv_org/test-project/dev/previews/c901afbf-f895-4bd7-9d0c-6a89f1b7ab56
    
         Type                 Name              Plan       Info
     +   pulumi:pulumi:Stack  test-project-dev  create     1 error
     +   ├─ aws:s3:Bucket     my-bucket         create     
     +   ├─ aws:ec2:Vpc       my-vpc            create     
     +   ├─ aws:ec2:Subnet    my-subnet         create     
     +   └─ aws:ec2:Instance  my-instance       create     
    
    
    Diagnostics:
      pulumi:pulumi:Stack (test-project-dev):
        error: preview failed
    
    Policy Violations:
        [mandatory]  aws-python v0.0.1  ec2_instance_type (aws:ec2/instance:Instance: my-instance)
        Check EC2 instance type
        EC2 instance my-instance uses restricted instance type
        Please use in any type of ['t2.nano', 't2.micro', 't2.small']
        
        [mandatory]  aws-python v0.0.1  name_prefix (aws:ec2/instance:Instance: my-instance)
        Check resource prefix
        Resource name my-instance should have prefix 'dev-'
        
        [mandatory]  aws-python v0.0.1  name_prefix (aws:ec2/subnet:Subnet: my-subnet)
        Check resource prefix
        Resource name my-subnet should have prefix 'dev-'
        
        [mandatory]  aws-python v0.0.1  name_prefix (aws:s3/bucket:Bucket: my-bucket)
        Check resource prefix
        Resource name my-bucket should have prefix 'dev-'
        
        [mandatory]  aws-python v0.0.1  network_cidr_block (aws:ec2/subnet:Subnet: my-subnet)
        Check VPC/Subnet CIDR block
        aws:ec2/subnet:Subnet my-subnet uses restricted CIDR block
        Please use in ip range of 10.0.0.0/16
        
        [mandatory]  aws-python v0.0.1  network_cidr_block (aws:ec2/vpc:Vpc: my-vpc)
        Check VPC/Subnet CIDR block
        aws:ec2/vpc:Vpc my-vpc uses restricted CIDR block
        Please use in ip range of 10.0.0.0/16
        
        [mandatory]  aws-python v0.0.1  subnet_availability_zone (aws:ec2/subnet:Subnet: my-subnet)
        Check subnet availability zone
        Subnet my-subnet uses restricted availability zone
        Please use in any az of ['ap-northeast-1a', 'ap-northeast-1c']
        
    Outputs:
        vpc_id: output<string>
  2. ここでポリシーに適合するように再度programを編集します。最終的に、programは以下のようになります。
    import pulumi
    import pulumi_aws as aws
    
    # スタックの名前を取得
    stack_name = pulumi.get_stack()
    
    # スタックの設定を読み込む
    config = pulumi.Config()
    
    # S3バケットの作成
    bucket = aws.s3.Bucket(f"{stack_name}-my-bucket")
    
    # VPCの作成
    vpc = aws.ec2.Vpc(
        "my-vpc",
        cidr_block="10.0.0.0/16",
    )
    # VPC IDのoutput export
    pulumi.export("vpc_id", vpc.id)
    
    # サブネットの作成
    subnet = aws.ec2.Subnet(
        f"{stack_name}-my-subnet",
        vpc_id=vpc.id,
        cidr_block="10.0.1.0/24",
        availability_zone="ap-northeast-1a"
    )
    
    # EC2インスタンスの作成
    ami = aws.ec2.get_ami(
        filters=[{
            "name": "name",
            "values": ["amzn2-ami-hvm-*-x86_64-gp2"],
        }],
        most_recent=True
    )
    instance = aws.ec2.Instance(
        f"{stack_name}-my-instance",
        instance_type="t2.micro",
        subnet_id=subnet.id,
        ami=ami.id
    )
  3. 再度リソース作成のdry-runコマンド「pulumi preview」を実行します。
    $ pulumi preview --policy-pack ../policypack
    先ほどとは異なり、ポリシー違反とならずにリソースをデプロイすることが可能になりました。
    Previewing update (kenneth_prv_org/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/kenneth_prv_org/test-project/dev/previews/7dd3e462-713e-44f0-a259-1333c1684cfb
    
         Type                 Name              Plan       
     +   pulumi:pulumi:Stack  test-project-dev  create     
     +   ├─ aws:s3:Bucket     dev-my-bucket     create     
     +   ├─ aws:ec2:Vpc       my-vpc            create     
     +   ├─ aws:ec2:Subnet    dev-my-subnet     create     
     +   └─ aws:ec2:Instance  dev-my-instance   create     
    
    
    Outputs:
        vpc_id: output<string>
    
    Resources:
        + 5 to create
    
    Policy Packs run:
        Name              Version
         (../policypack)  (local)

ハンズオンは以上です。ハンズオンではリソース作成前のdry-run(pulumi preview)のみ実施しているため、特にAWS上にリソースは作成していません。実際にリソースを作成したい場合は「pulumi up」コマンドを実施してください。

おわりに

今回は、Policy as Codeの概要とPulumiのPolicy as Code「CrossGuard」について解説しました。

自動的にポリシーチェックができる最大の利点は、リソースの更新頻度が増えても「自動的にポリシーをチェックしてくれている」という、心理的に安心できる点にあると個人的には考えています。PulumiのようなIaCとCrossGuardのようなPaCをCI/CDで組み合わせてみて、インフラ構築をより加速させてみるのも良さそうです。次回もお楽しみに!

【参考】Pulumi公式ホームページ(英語)

著者
大関 研丞 (Kenneth Ozeki)
クリエーションライン株式会社 Data Platform Team
前職では保険や金融エンタープライズのミッションクリティカルシステム(オンプレミス、仮想サーバー、CDN等のインフラ系業務)の設計/構築を経験。クリエーションラインに転職後はクラウドエンジニアとしてGCP関連の案件でインフラの設計/構築、IaCやCI/CDを用いたDevOpsの導入、コンテナ(Kubernetes)基盤の構築、運用自動化ツールの作成などを担当。
クリエーションラインの技術ブログをチェック

連載バックナンバー

システム運用技術解説
第10回

Pulumiの最新機能「Pulumi ESC」を使ってみよう

2023/12/26
最終回となる今回は、2023年12月時点でリリースされている新機能の紹介と、その新機能の中から「Pulumi ESC」を用いたハンズオンを実践していきます。
システム運用技術解説
第9回

TerraformからPulumiへの移行

2023/11/28
第9回となる今回は、既にTerraformでAWS環境に作成されているリソースをPulumiへ移行するケースを想定して、CoexistenceとConversionのハンズオンを実践していきます
システム運用技術解説
第8回

既に存在するリソースをPulumiで管理してみよう

2023/10/19
第8回となる今回は、既にクラウド環境にデプロイされているリソースをPulumiで管理(import)する方法について、ハンズオンで実践していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています