Squid Proxyの汎用化デプロイ戦略:AWS AppConfig による設定管理

はじめに

L7レイヤーのプロキシサーバーであるSquid Proxyは、VPC環境でアウトバウンド通信を厳格に制限を行いたいユースケースで活用されることが多くあります。ただし、どのドメインのアウトバウンド通信を許可するかはプロジェクト毎に異なり、Dockerfile 内に Squid Proxy の設定を保持すると、プロジェクト毎にイメージのビルドとデプロイが必要になり運用が冗長になります。

AWS AppConfig の活用は、この課題を解決するための一つの方法です。本記事では、Squid Proxyの設定の効率的な管理を実現するための方法を紹介します。

補足:
本記事は Squid Proxyを用いたドメインリスト制御はAWS Network Firewallで代替可能か? で、AWS Network Firewall を用いてドメインリスト制御を試みるも挫折し、Squid Proxy を効率よく運用したい筆者の試行錯誤の記録です 🐣


1. 現状の課題の理解とアプローチの設定

現在の課題

  • 個別設定の必要性: 各プロジェクトが独自の Squid Proxy の設定を必要とし、Squid Proxy をコンテナ(ECS + Fargate 等)で運用する際に、個別に Docker イメージを作成する手間がかかる。
  • 設定管理の複雑性: 設定の変更時には新たなイメージビルドが必要で、どのタイミングでどの設定が有効になっているかを管理するのが難しい。

解決策としての AWS AppConfig

AWS AppConfig は、AWS 環境における設定管理を効率化するツールです。導入により、以下のメリットが期待されます:

  • リアルタイムでの設定変更: プロジェクトごとの異なる設定を外部管理し、リアルタイムに適用可能。
  • バージョン管理の容易化: 各設定のバージョン管理が可能で、バックアップや変更履歴の追跡が簡単。

2. AWS AppConfigを用いたデプロイの実装

アーキテクチャの概要

AWS AppConfig を用いることで、設定を外部から管理し、起動時に適切な構成を取得して適用する手法を取ります。この方法により、共通のベースイメージを使用しつつ、各環境に適した設定を柔軟に注入できます。

サンプル CloudFormation

以下は CloudFormation による ECS Task Definition と AWS AppConfig リソースの定義例です。

SquidProxyTaskDefinition:
  Type: AWS::ECS::TaskDefinition
  Properties:
    Cpu: '256'
    TaskRoleArn: !GetAtt SquidProxyECSTaskRole.Arn
    ExecutionRoleArn: !GetAtt SquidProxyECSTaskExecRole.Arn
    Family: !Sub ${AWS::StackName}-squid-proxy-task
    Memory: '512'
    NetworkMode: awsvpc
    RequiresCompatibilities:
      - FARGATE
    ContainerDefinitions:
      - Name: squid-proxy
        Image: !Sub
          - ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${ContainerName}:latest
          - ContainerName: "squid-proxy"
        LogConfiguration:
          LogDriver: awslogs
          Options:
            awslogs-group: !Ref SquidProxyLogGroup
            awslogs-region: !Ref AWS::Region
            awslogs-stream-prefix: ecs
        MemoryReservation: 512
        PortMappings:
          - HostPort: 3128
            Protocol: tcp
            ContainerPort: 3128
        Environment:
          - Name: APPLICATION_ID
            Value: !Ref SquidProxyApp
          - Name: ENVIRONMENT_ID
            Value: !Ref SquidProxyEnvironment
          - Name: CONFIGURATION_PROFILE_ID
            Value: !Ref SquidProxyAppConfig
          - Name: CONFIGURATION_VERSION
            Value: !Ref SquidProxyAppConfigVersion
            
SquidProxyApp:
    Type: AWS::AppConfig::Application
    Properties:
        Name: !Sub ${AWS::StackName}-squid-proxy-app
        Description: 'Application for Squid Proxy configuration'
        Tags:
            - Key: Name
              Value: !Sub ${AWS::StackName}-squid-proxy-app

SquidProxyAppConfig:
    Type: AWS::AppConfig::ConfigurationProfile
    Properties:
        ApplicationId: !Ref SquidProxyApp
        LocationUri: 'hosted'
        Name: !Sub ${AWS::StackName}-squid-proxy-config
        Description: 'Configuration for Squid Proxy'

SquidProxyEnvironment:
    Type: AWS::AppConfig::Environment
    Properties:
        ApplicationId: !Ref SquidProxyApp
        Name: !Sub ${AWS::StackName}-squid-proxy-env
        Description: 'Environment for Squid Proxy'
        Monitors: []

SquidProxyAppConfigVersion:
    Type: AWS::AppConfig::HostedConfigurationVersion
    Properties:
        ApplicationId: !Ref SquidProxyApp
        ConfigurationProfileId: !Ref SquidProxyAppConfig
        ContentType: 'text/plain'
        Content: !Sub |
            // NOTE: squid.conf の設定を記述する

SquidProxyDeploymentStrategy:
    Type: AWS::AppConfig::DeploymentStrategy
    Properties:
        Name: !Sub ${AWS::StackName}-squid-proxy-deployment-strategy
        Description: 'Deployment strategy for Squid Proxy configuration'
        DeploymentDurationInMinutes: 0
        GrowthFactor: 100
        FinalBakeTimeInMinutes: 0
        ReplicateTo: NONE

SquidProxyDeployment:
    Type: AWS::AppConfig::Deployment
    Properties:
        ApplicationId: !Ref SquidProxyApp
        ConfigurationProfileId: !Ref SquidProxyAppConfig
        ConfigurationVersion: !Ref SquidProxyAppConfigVersion
        DeploymentStrategyId: !Ref SquidProxyDeploymentStrategy
        EnvironmentId: !Ref SquidProxyEnvironment

サンプル Dockerfile

以下は Squid Proxy の Docker コンテナを構成するための基本的な Dockerfile です。

FROM amazonlinux:2023

ENV AWS_REGION=ap-northeast-1

RUN dnf update -y \
    && dnf install -y squid aws-cli sudo \
    && dnf clean all

RUN mkdir -p /var/log/squid \
    && chown squid:squid /var/log/squid \
    && chown squid:squid /etc/squid

RUN chown squid:squid /etc/squid/squid.conf \
    && chmod 664 /etc/squid/squid.conf

COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

USER squid
EXPOSE 3128
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["squid", "-N", "-d", "1"]

サンプル entrypoint.sh (AppConfig版)

以下のスクリプトは、コンテナ起動時に AWS AppConfig から設定を取得し、Squid を起動するものです。

#!/usr/bin/env bash

set -e

# 環境変数のチェック
if [ -z "$APPLICATION_ID" ] || [ -z "$ENVIRONMENT_ID" ] || [ -z "$CONFIGURATION_PROFILE_ID" ] || [ -z "$CONFIGURATION_VERSION" ]; then
  echo "ERROR: 必要な環境変数が設定されていません。"
  exit 1
fi

echo "AWS AppConfig とのセッションを開始..."
SESSION_TOKEN=$(aws appconfigdata start-configuration-session \
  --application-identifier $APPLICATION_ID \
  --environment-identifier $ENVIRONMENT_ID \
  --configuration-profile-identifier $CONFIGURATION_PROFILE_ID \
  --region $AWS_REGION \
  --query 'InitialConfigurationToken' \
  --output text)

echo "AWS AppConfig から設定を取得..."
aws appconfigdata get-latest-configuration \
  --configuration-token $SESSION_TOKEN \
  --region $AWS_REGION \
  > /etc/squid/squid.conf

echo "squid を開始..."
exec "$@"

3. AWS AppConfigのメリットとデメリット

メリット

  1. 設定管理の効率化: 設定情報をベースイメージに含めず、都度デプロイ可能。
  2. バージョン管理: 設定のロールバックが容易。
  3. セキュリティの強化: IAM によるアクセス制御や CloudTrail での監査が可能。
  4. インフラのコード化: CloudFormation や Terraform による管理が容易。

デメリット

  1. 導入と学習コスト: AppConfig の理解やオペレーション統合に時間がかかる。

4. まとめ

AWS AppConfig を活用することで、Squid Proxy の設定管理を効率化できます。アプリケーションコードと設定情報のライフサイクルを分離し、柔軟な運用が可能になるユースケースがあるため、ぜひ参考にしてください。