
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: '*'
민감한 리소스를 보호하기 위한 스택 정책
{
"Statement": [
{
"Effect": "Allow",
"Action": "Update:*",
"Principal": "*",
"Resource": "*"
},
{
"Effect": "Deny",
"Action": "Update:Delete",
"Principal": "*",
"Resource": "*",
"Condition": {
"StringEquals": {
"ResourceType": [
"AWS::RDS::DBInstance",
"AWS::S3::Bucket"
]
}
}
}
]
}
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
'''
}
}
}
}
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'
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']])
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
CloudFormation은 단순한 인프라 관리 도구를 넘어 조직의 DevOps 문화를 혁신할 수 있는 강력한 도구입니다.
보안, 자동화, 비용 최적화를 고려한 전략적 접근이 중요하며, 이를 통해 안정적이고 효율적인 인프라 관리가 가능합니다.