
AWSTemplateFormatVersion: '2010-09-09'
Description: 'SSM 기본 인프라 설정'
Resources:
SSMInstanceRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore'
- 'arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy'
SSMInstanceProfile:
Type: 'AWS::IAM::InstanceProfile'
Properties:
Roles:
- !Ref SSMInstanceRole
SSMLogGroup:
Type: 'AWS::Logs::LogGroup'
Properties:
LogGroupName: '/ssm/automation/logs'
RetentionInDays: 30
SSMVPCEndpoint:
Type: 'AWS::EC2::VPCEndpoint'
Properties:
VpcId: !Ref VPC
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
VpcEndpointType: Interface
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroupIds:
- !Ref SSMEndpointSecurityGroup
PrivateDnsEnabled: true
SSMEndpointSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupDescription: 'Security group for SSM VPC Endpoint'
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !GetAtt VPC.CidrBlock
import boto3
import json
def create_automation_document():
ssm = boto3.client('ssm')
document_content = {
"schemaVersion": "0.3",
"description": "애플리케이션 배포 자동화",
"parameters": {
"InstanceIds": {
"type": "StringList",
"description": "대상 인스턴스 ID"
},
"S3BucketName": {
"type": "String",
"description": "배포 파일이 있는 S3 버킷"
},
"ArtifactPath": {
"type": "String",
"description": "배포 파일 경로"
}
},
"mainSteps": [
{
"name": "downloadArtifact",
"action": "aws:runShellScript",
"inputs": {
"runCommand": [
"aws s3 cp s3://{{S3BucketName}}/{{ArtifactPath}} /tmp/",
"cd /tmp && unzip -o *.zip",
"./deploy.sh"
]
}
},
{
"name": "validateDeployment",
"action": "aws:runShellScript",
"inputs": {
"runCommand": [
"curl -f http://localhost/health || exit 1"
]
}
}
]
}
response = ssm.create_document(
Content=json.dumps(document_content),
Name='ApplicationDeployment',
DocumentType='Automation',
DocumentFormat='JSON'
)
return response
def execute_deployment():
ssm = boto3.client('ssm')
response = ssm.start_automation_execution(
DocumentName='ApplicationDeployment',
Parameters={
'InstanceIds': ['i-1234567890abcdef0'],
'S3BucketName': 'deployment-artifacts',
'ArtifactPath': 'releases/app-1.0.0.zip'
}
)
return response['AutomationExecutionId']
def check_execution_status(execution_id):
ssm = boto3.client('ssm')
response = ssm.get_automation_execution(
AutomationExecutionId=execution_id
)
return response['AutomationExecution']['Status']
def create_patch_baseline():
ssm = boto3.client('ssm')
response = ssm.create_patch_baseline(
Name='CustomPatchBaseline',
OperatingSystem='AMAZON_LINUX_2',
ApprovalRules={
'PatchRules': [
{
'PatchFilterGroup': {
'PatchFilters': [
{
'Key': 'PRODUCT',
'Values': ['AmazonLinux2.0']
},
{
'Key': 'CLASSIFICATION',
'Values': ['Security', 'Bugfix']
},
{
'Key': 'SEVERITY',
'Values': ['Critical', 'Important']
}
]
},
'ApproveAfterDays': 7,
'ComplianceLevel': 'CRITICAL'
}
]
},
Description='보안 패치 자동 승인 베이스라인'
)
return response['BaselineId']
def setup_maintenance_window():
ssm = boto3.client('ssm')
# 유지보수 기간 생성
window_id = ssm.create_maintenance_window(
Name='WeeklyPatchWindow',
Schedule='cron(0 0 ? * SUN *)', # 매주 일요일 00:00
Duration=3, # 3시간
Cutoff=2, # 2시간 전에 새 작업 중지
AllowUnassociatedTargets=False
)['WindowId']
# 대상 등록
target_id = ssm.register_target_with_maintenance_window(
WindowId=window_id,
ResourceType='INSTANCE',
Targets=[
{
'Key': 'tag:Environment',
'Values': ['Production']
}
]
)['WindowTargetId']
# 패치 작업 등록
ssm.register_task_with_maintenance_window(
WindowId=window_id,
TaskArn='AWS-RunPatchBaseline',
ServiceRoleArn='arn:aws:iam::account-id:role/service-role/SSM-MaintenanceWindowRole',
TaskType='RUN_COMMAND',
TaskParameters={
'Operation': {'Values': ['Install']}
},
MaxConcurrency='50%',
MaxErrors='25%'
)
def emergency_patch_deployment():
ssm = boto3.client('ssm')
# 긴급 패치 명령 실행
response = ssm.send_command(
Targets=[{'Key': 'tag:Environment', 'Values': ['Production']}],
DocumentName='AWS-RunPatchBaseline',
Parameters={
'Operation': ['Install'],
'SnapshotId': [''],
'RebootOption': ['RebootIfNeeded']
},
TimeoutSeconds=3600,
Comment='긴급 보안 패치 적용',
CloudWatchOutputConfig={
'CloudWatchLogGroupName': '/ssm/patch-management/emergency',
'CloudWatchOutputEnabled': True
}
)
command_id = response['Command']['CommandId']
return command_id
def create_rollback_automation():
ssm = boto3.client('ssm')
document_content = {
"schemaVersion": "0.3",
"description": "애플리케이션 롤백 자동화",
"parameters": {
"PreviousVersion": {
"type": "String",
"description": "롤백할 버전"
}
},
"mainSteps": [
{
"name": "stopApplication",
"action": "aws:runShellScript",
"inputs": {
"runCommand": [
"systemctl stop application"
]
}
},
{
"name": "restorePreviousVersion",
"action": "aws:runShellScript",
"inputs": {
"runCommand": [
"aws s3 cp s3://backup/{{PreviousVersion}} /opt/application/",
"cd /opt/application && tar -xzf {{PreviousVersion}}"
]
}
},
{
"name": "startApplication",
"action": "aws:runShellScript",
"inputs": {
"runCommand": [
"systemctl start application"
]
}
}
]
}
ssm.create_document(
Content=json.dumps(document_content),
Name='ApplicationRollback',
DocumentType='Automation',
DocumentFormat='JSON'
)
def setup_monitoring_dashboard():
cloudwatch = boto3.client('cloudwatch')
dashboard_body = {
"widgets": [
{
"type": "metric",
"properties": {
"metrics": [
["AWS/SSM", "CommandSuccess", "DocumentName", "AWS-RunPatchBaseline"],
[".", "CommandFailed", ".", "."]
],
"period": 300,
"stat": "Sum",
"region": "ap-northeast-2",
"title": "패치 명령 실행 현황"
}
},
{
"type": "metric",
"properties": {
"metrics": [
["AWS/SSM", "MaintenanceWindowExecution", "Status", "SUCCESS"],
[".", ".", ".", "FAILED"]
],
"period": 3600,
"stat": "Sum",
"region": "ap-northeast-2",
"title": "유지보수 기간 실행 현황"
}
}
]
}
cloudwatch.put_dashboard(
DashboardName='SSMOperations',
DashboardBody=json.dumps(dashboard_body)
)
def setup_audit_logging():
# CloudTrail 설정
cloudtrail = boto3.client('cloudtrail')
response = cloudtrail.create_trail(
Name='SSMAuditTrail',
S3BucketName='your-audit-bucket',
IsMultiRegionTrail=True,
EnableLogFileValidation=True
)
# CloudWatch Logs 설정
logs = boto3.client('logs')
logs.create_log_group(
logGroupName='/aws/ssm/audit'
)
# 메트릭 필터 생성
logs.put_metric_filter(
logGroupName='/aws/ssm/audit',
filterName='UnauthorizedSSMAccess',
filterPattern='{ $.eventName = SendCommand && $.errorMessage = *UnauthorizedOperation* }',
metricTransformations=[
{
'metricName': 'UnauthorizedSSMAccess',
'metricNamespace': 'SSMAudit',
'metricValue': '1'
}
]
)
# 경보 설정
cloudwatch = boto3.client('cloudwatch')
cloudwatch.put_metric_alarm(
AlarmName='UnauthorizedSSMAccessAlarm',
MetricName='UnauthorizedSSMAccess',
Namespace='SSMAudit',
Statistic='Sum',
Period=300,
EvaluationPeriods=1,
Threshold=1,
ComparisonOperator='GreaterThanOrEqualToThreshold',
AlarmActions=['arn:aws:sns:region:account-id:security-alerts']
)
AWS Systems Manager는 서버 관리와 자동화를 위한 강력한 도구입니다.
적절한 설정과 자동화를 통해 다음과 같은 이점을 얻을 수 있습니다.
1. 보안 강화: VPC 엔드포인트와 최소 권한 원칙 적용
2. 운영 자동화: 패치 관리와 배포 자동화
3. 감사 및 모니터링: 실시간 모니터링과 감사 로그 관리
4. 장애 대응: 롤백 자동화와 긴급 패치 배포
이러한 기능들을 적절히 활용하면 안전하고 효율적인 서버 관리가 가능합니다.