[AWS] 보안, 자동화, 비용 최적화

궁금하면 500원·2024년 6월 1일

데브옵스

목록 보기
6/37

AWS CloudFormation 보안, 자동화

1. CloudFormation 보안 아키텍처

1.1 IAM Role 기반의 권한 관리

CloudFormation의 가장 중요한 보안 측면은 IAM Role 관리입니다.

iam:PassRole을 통한 권한 위임은 편리하지만, 보안 위험도 존재합니다.

다음은 안전한 CloudFormation 실행 Role의 예시입니다.

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  CloudFormationExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      RoleName: 'CloudFormation-Execution-Role'
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSCloudFormationFullAccess'
      Policies:
        - PolicyName: 'RestrictedResourceCreation'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'ec2:*'
                  - 's3:*'
                  - 'elasticloadbalancing:*'
                Resource: '*'
              - Effect: Deny
                Action:
                  - 'iam:CreateUser'
                  - 'iam:DeleteUser'
                  - 'iam:CreateRole'
                  - 'iam:DeleteRole'
                Resource: '*'

1.2 스택 정책 구현

민감한 리소스를 보호하기 위한 스택 정책

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "Update:*",
      "Principal": "*",
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": "Update:Delete",
      "Principal": "*",
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ResourceType": [
            "AWS::RDS::DBInstance",
            "AWS::S3::Bucket"
          ]
        }
      }
    }
  ]
}

2. 자동화 파이프라인 구축

2.1 Jenkins와 CloudFormation 연동

pipeline {
    agent any
    environment {
        AWS_DEFAULT_REGION = 'ap-northeast-2'
        STACK_NAME = 'production-stack'
    }
    stages {
        stage('Validate Template') {
            steps {
                sh '''
                    aws cloudformation validate-template \
                        --template-body file://template.yaml
                '''
            }
        }
        stage('Deploy Stack') {
            steps {
                sh '''
                    aws cloudformation deploy \
                        --template-file template.yaml \
                        --stack-name ${STACK_NAME} \
                        --parameter-overrides \
                            Environment=production \
                            InstanceType=t3.micro \
                        --capabilities CAPABILITY_NAMED_IAM
                '''
            }
        }
    }
}

2.2 시간 기반 자동 스케일링

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  AutoScalingGroup:
    Type: 'AWS::AutoScaling::AutoScalingGroup'
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MinSize: '2'
      MaxSize: '10'
      DesiredCapacity: '2'
      VPCZoneIdentifier: 
        - !Ref Subnet1
        - !Ref Subnet2

  ScaleUpSchedule:
    Type: 'AWS::AutoScaling::ScheduledAction'
    Properties:
      AutoScalingGroupName: !Ref AutoScalingGroup
      DesiredCapacity: '4'
      RecurrenceTime: '0 8 * * 1-5'  # 평일 오전 8시
      TimeZone: 'Asia/Seoul'

  ScaleDownSchedule:
    Type: 'AWS::AutoScaling::ScheduledAction'
    Properties:
      AutoScalingGroupName: !Ref AutoScalingGroup
      DesiredCapacity: '2'
      RecurrenceTime: '0 17 * * 1-5'  # 평일 오후 5시
      TimeZone: 'Asia/Seoul'

3. 비용 최적화 전략

3.1 리소스 태깅 자동화

Resources:
  EC2Instance:
    Type: 'AWS::EC2::Instance'
    Properties:
      ImageId: !Ref AMIId
      InstanceType: !Ref InstanceType
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-instance'
        - Key: Environment
          Value: !Ref Environment
        - Key: CostCenter
          Value: !Ref CostCenter
        - Key: AutoShutdown
          Value: 'true'

  TagBasedShutdownLambda:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import boto3
          def handler(event, context):
              ec2 = boto3.client('ec2')
              instances = ec2.describe_instances(
                  Filters=[{'Name': 'tag:AutoShutdown', 'Values': ['true']}]
              )
              for reservation in instances['Reservations']:
                  for instance in reservation['Instances']:
                      ec2.stop_instances(InstanceIds=[instance['InstanceId']])

4. 실전 템플릿 코드

4.1 고가용성 웹 애플리케이션 스택

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
  InstanceType:
    Type: String
    Default: t3.micro
  KeyName:
    Type: AWS::EC2::KeyPair::KeyName

Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Enable HTTP access via port 80
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  ApplicationLoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Subnets: !Ref SubnetIds
      SecurityGroups:
        - !Ref WebServerSecurityGroup

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Port: 80
      Protocol: HTTP
      VpcId: !Ref VpcId
      HealthCheckPath: /health
      HealthCheckIntervalSeconds: 30

  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup
      LoadBalancerArn: !Ref ApplicationLoadBalancer
      Port: 80
      Protocol: HTTP

  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        ImageId: ami-0c55b159cbfafe1f0
        InstanceType: !Ref InstanceType
        SecurityGroupIds:
          - !Ref WebServerSecurityGroup
        KeyName: !Ref KeyName
        UserData:
          Fn::Base64: !Sub |
            #!/bin/bash
            yum update -y
            yum install -y httpd
            systemctl start httpd
            systemctl enable httpd

  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      MinSize: '2'
      MaxSize: '4'
      DesiredCapacity: '2'
      TargetGroupARNs:
        - !Ref TargetGroup
      HealthCheckType: ELB
      HealthCheckGracePeriod: 300
      Tags:
        - Key: Name
          Value: !Sub ${AWS::StackName}-instance
          PropagateAtLaunch: true

Outputs:
  LoadBalancerDNS:
    Description: DNS Name of the Application Load Balancer
    Value: !GetAtt ApplicationLoadBalancer.DNSName

5. 모범 사례와 안티 패턴

5.1 모범 사례

1. 변수화와 파라미터 사용

  • 환경별 설정을 파라미터로 관리
  • 민감한 정보는 AWS Secrets Manager 사용

2 중첩 스택 활용

  • 재사용 가능한 컴포넌트 분리
  • 모듈화를 통한 유지보수성 향상

3 드리프트 감지 활성화

  • 정기적인 드리프트 검사 수행
  • 변경 사항 자동 알림 설정

5.2 안티 패턴

1. 하드코딩된 값 사용

  • 환경 변수나 파라미터 대신 직접 값을 입력
  • 유지보수와 재사용성 저하

2. 과도한 권한 부여

  • 필요 이상의 IAM 권한 설정
  • 보안 위험 증가

3. 수동 변경 허용

  • CloudFormation 외부에서 리소스 직접 수정
  • 일관성 저하와 관리 어려움

결론

CloudFormation은 단순한 인프라 관리 도구를 넘어 조직의 DevOps 문화를 혁신할 수 있는 강력한 도구입니다.

보안, 자동화, 비용 최적화를 고려한 전략적 접근이 중요하며, 이를 통해 안정적이고 효율적인 인프라 관리가 가능합니다.

profile
에러가 나도 괜찮아 — 그건 내가 배우고 있다는 증거야.

0개의 댓글