계정 보안 MFA 및 IAM 사용해보자
MFA(Multi-factor authentication)
보안 강화를 위해 멀티 팩터 인증(MFA)을 구성하여 AWS 리소스를 보호하는 것이 좋다.
MFA
- 로그인 후 - 보안자격증명 들어가기
- MFA 활성화
- 핸드폰에 GoogleAuthenticator(Google OTP) 설치
- QR 코드 스캔으로 연동하기
- 연속으로 나타나는 MFA 6자리 비밀번호 2개를 입력해서 마무리
- 이제 로그인마다 MFA 인증코드를 입력해야함
IAM(Identity and Access Management)
AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스로 IAM을 사용하여 리소스를 사용하도록 인증(로그인) 및 권한 부여(권한 있음)를 통해 제어하도록 한다. 즉, AWS 에서는 관리 작업의 경우에도 루트 사용자를 사용하지 마실 것을 강력히 권장하고 있으며 IAM 사용자를 만들어 사용할 것을 권장한다.
- IAM 메뉴로 이동
- 사용자 옵션을 선택
- 사용자 추가를 선택 후 프로그래밍 방식 액세스 옵션 선택
- 자격증명 다운로드(.csv다운로드)
- 권한 탭에서 권한 추가 후 Attach existing policies directly 선택 및 AWS 서비스 리소스의 전체 접근 권한을 제공하는 AdministratorAccess 추가
- 보안 자격증명 탭 클릭 후 콘솔 비밀번호 옵션 클릭
- MFA 디바이스 할당 클릭 후 MFA 디바이스와 연결
- 대시보드에서 IAM 메뉴 클릭
- IAM 사용자 로그인 링크로 접근(로그인 URL 로 콘솔에 로그인 시 이 링크를 사용)
AWS CLI 설치하자
터미널 창에서 'brew install awscli' 로 awscli 를 설치
1. 위에서 내려받은 csv 파일에서 엑세스키와 비밀 키를 가져오자
$ more credentials.csv
2. AWS 계정을 구성하자
$ aws configure
AWS Access Key ID [****************676F]: AI***********************
AWS Secret Access Key [****************vEwE]: UvxoLNe/EuCyjq****FSuUB**********************
Default region name [ap-northeast-2]: ap-northeast-2
Default output format [None]:
3. 이제 CLI 를 사용할 수 있게 되었다. 사용자 계정 목록을 출력해보자
$ aws iam list-users
{
"Users": [
{
"Path": "/",
"UserName": "hooneats01",
"UserId": "AI***********************",
"Arn": "arn:aws:iam::394078117217:user/hooneats01",
"CreateDate": "2022-07-20T00:45:09+00:00"
}
]
}
4. EC2 를 사용하여 가상서버 구축하자
가상서버를 시작하려면 다음의 4가지 정보가 필요하다.
- AMI ID
- 인스턴스 유형
- 보안 그룹
- SSH 키 페어
4-1 AMI 찾기
$ aws ec2 describe-images --filters "Name=description,Values=Amazon Linux AMI * x86_64 HVM GP2" --query "Images[0].ImageId" --output text
4-2 인스턴스 유형
AWS 무료 티어에 적합한 t2.micro
4-3 보안 그룹
보안 그룹은 방화벽과 유사하게 동작한다. 모든 EC2 인스턴스에는 지정된 보안 그룹 집합이 있다. 각 보안 그룹에는 인바운드(인그레스-ingress) 및 아웃바운드(이그레스-egress) 트래픽을 허용하는 규칙이 있다.
tcp/3000 포트에서 동작하는 소규모 웹을 만들어보자.
tcp/22 포트의 인바운드 접속을 허용해 SSH 로 인스턴스에 접혹해보자.
EC2 인스턴스를 보호하는 보안 그룹은 서브넷에 연결되어 있고, 서브넷은 VPC가 제공하는 네트워크에 연결되어 있다.
이를 위해, 자체적인 네트워크가 있는 가상 데이터 센터라고 볼 수 있는 가상 사설 클라우드(VPC, Virtual Private Cloud) ID 를 찾아야한다.
$ aws ec2 describe-vpcs
{
"Vpcs": [
{
"CidrBlock": "172.31.0.0/16",
"DhcpOptionsId": "dopt-56efa03d",
"State": "available",
"VpcId": "vpc-9c98*****",
"OwnerId": "394078117217",
"InstanceTenancy": "default",
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-ee4ab785",
"CidrBlock": "172.31.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": true
}
]
}
이제 VPC ID 로 새로운 보안 그룹을 생성할 수 있다.
$ aws ec2 create-security-group --group-name HelloWorld --description "Hello World Demo" --vpc-id vpc-9c98*****
{
"GroupId": "sg-02aa7a15**********"
}
기본적으로 보안 그룹은 인스턴스로부터의 모든 아웃바운드 트래픽을 허용한다.
tcp/22(SSH) 와 tcp/3000을 인바운드 트래픽으로 열자
$ aws ec2 authorize-security-group-ingress --group-name HelloWorld --protocol tcp --port 22 --cidr 0.0.0.0/0
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-0ecb245c6f70d2c8e",
"GroupId": "sg-02aa7a15a52a37229",
"GroupOwnerId": "394078117217",
"IsEgress": false,
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"CidrIpv4": "0.0.0.0/0"
}
]
}
$ aws ec2 authorize-security-group-ingress --group-name HelloWorld --protocol tcp --port 3000 --cidr 0.0.0.0/0
{
"Return": true,
"SecurityGroupRules": [
{
"SecurityGroupRuleId": "sgr-0793b694de9e1e4f7",
"GroupId": "sg-02aa7a15a52a37229",
"GroupOwnerId": "394078117217",
"IsEgress": false,
"IpProtocol": "tcp",
"FromPort": 3000,
"ToPort": 3000,
"CidrIpv4": "0.0.0.0/0"
}
]
}
확인해보자
$ aws ec2 describe-security-groups --group-name HelloWorld --output text
SECURITYGROUPS Hello World Demo sg-02aa7a15a52a37229 HelloWorld 394078117217 vpc-9c9802f7
IPPERMISSIONS 22 tcp 22
IPRANGES 0.0.0.0/0
IPPERMISSIONS 3000 tcp 3000
IPRANGES 0.0.0.0/0
IPPERMISSIONSEGRESS -1
IPRANGES 0.0.0.0/0
4-4 SSH 키 생성하기
EC2 에서 키 페어를 생성하고 캐인 키를 내려받을 수 있다.
$ aws ec2 create-key-pair --key-name EffectiveDevOpsAWS --query "KeyMaterial" --output text > ~/.ssh/EffectiveDevOpsAWS.pem
$ aws ec2 describe-key-pairs --key-name EffectiveDevOpsAWS
{
"KeyPairs": [
{
"KeyPairId": "key-0ac8813***********",
"KeyFingerprint": "2b:95:5a:9c:bd:fa:1****************",
"KeyName": "EffectiveDevOpsAWS",
"KeyType": "rsa",
"Tags": [],
"CreateTime": "2022-07-20T04:15:55+00:00"
}
]
}
$ cat ~/.ssh/EffectiveDevOpsAWS.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAowewCqDX7LhTw6NgSMGJxorxfg2UhgJvKgk4ZxWIwEjnUU9q
TbR1iX5j+Rn3iqVyf//u2YgKDAqYyny32fLwj7Lxh2LHLMz5+F6kV253l8jlxYIn
...
-----END RSA PRIVATE KEY-----
$ chmod 400 ~/.ssh/EffectiveDevOpsAWS.pem
EC2 인스턴스 띄우기
인스턴스 띄워보자
$ aws ec2 run-instances --instance-type t2.micro --key-name EffectiveDevOpsAWS --security-group-ids sg-02aa7a15********** --image-id ami-0a10b2721688ce9d2
{
"Groups": [],
"Instances": [
{
"AmiLaunchIndex": 0,
"ImageId": "ami-0a10b2721688ce9d2",
"InstanceId": "i-0abd8725************",
"InstanceType": "t2.micro",
"KeyName": "EffectiveDevOpsAWS",
"LaunchTime": "2022-07-20T04:32:14+00:00",
"Monitoring": {
"State": "disabled"
},
"Placement": {
"AvailabilityZone": "ap-northeast-2c",
"GroupName": "",
"Tenancy": "default"
},
"PrivateDnsName": "ip-172-31-46-45.ap-northeast-2.compute.internal",
"PrivateIpAddress": "172.31.46.45",
"ProductCodes": [],
"PublicDnsName": "",
"State": {
"Code": 0,
"Name": "pending"
},
"StateTransitionReason": "",
"SubnetId": "subnet-471ee608",
"VpcId": "vpc-9c9802f7",
"Architecture": "x86_64",
"BlockDeviceMappings": [],
확인해 보자
$ aws ec2 describe-instance-status --instance-ids i-0abd8725************
{
"InstanceStatuses": [
{
"AvailabilityZone": "ap-northeast-2c",
"InstanceId": "i-0abd8725************",
"InstanceState": {
"Code": 16,
"Name": "running"
},
"InstanceStatus": {
"Details": [
{
"Name": "reachability",
"Status": "passed"
}
],
"Status": "ok"
},
"SystemStatus": {
"Details": [
{
"Name": "reachability",
"Status": "passed"
}
],
"Status": "ok"
}
}
]
}
$ aws ec2 describe-instance-status --instance-ids i-0abd8725949bc6a5f --output text | grep -i SystemStatus
SYSTEMSTATUS ok
SSH 를 이용해 EC2 인스턴스에 접속하자
인스턴스에 SSH 로 접속하기 위해서는 실행 중인 인스턴스의 DNS 명을 찾아야한다.
$ aws ec2 describe-instances --instance-ids i-0abd8725949bc6a5f --query "Reservations[*].Instances[*].PublicDnsName"
[
[
"ec2-3-35-52-157.ap-northeast-2.compute.amazonaws.com"
]
]
AMI 가 아마존 리눅스이므로 기본 사용자 계정은 ec2-user이다.
$ ssh -i ~/.ssh/EffectiveDevOpsAWS.pem ec2-user@ec2-3-35-52-157.ap-northeast-2.compute.amazonaws.com
The authenticity of host 'ec2-3-35-52-157.ap-northeast-2.compute.amazonaws.com (3.35.52.157)' can't be established.
ED25519 key fingerprint is SHA256:gINBw6TUhirBHbTXwZmAuBk4K5iXBF69j3zsciPyzVE.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ec2-3-35-52-157.ap-northeast-2.compute.amazonaws.com' (ED25519) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
37 package(s) needed for security, out of 62 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-31-46-45 ~]$
Node.js 로 간단한 웹을 띄워보자
아마존 리눅스는 레드햇 엔터프라이즈 리눅스 기반이고, 패키지를 설치 및 관리하는 데 yum 이라는 도구를 사용한다. 이 운영체제에는 엔터프라이즈 리눅스를 위한 부가 패키지(EPEL-Extra Packages for Enterprise Linux)가 미리 구성되어 있고, Node.js 는 EPEL에 포함되어 있다.
[ec2-user@ip-172-31-46-45 ~]$ sudo yum install --enablerepo=epel -y nodejs
[ec2-user@ip-172-31-46-45 ~]$ node -v
/home/ec2-user/helloworld.js 파일을 만들자
pwd 하면 현재 경로가 /home/ec2-user 이다.
[ec2-user@ip-172-31-46-45 ~]$ vim helloworld.js
var http = require("http")
http.createServer(function (request, response) {
// Send the HTTP header
// HTTP Status: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'})
// Send the response body as "Hello World"
response.end('Hello World\n')
}).listen(3000)
// Console will print the message
console.log('Server running')
[ec2-user@ip-172-31-46-45 ~]$ node helloworld.js
ec2-3-35-52-157.ap-northeast-2.compute.amazonaws.com:3000
띄워진 것을 확인했다면, Ctrl+C로 웹 을 중지시키고
upstart 를 사용해 간단한 코드를 서비스로 전환해보자
- 아마존 리눅스는 표준 레드햇 기반 배포판과 달리 upstart 라는 시스템 콜을 갖고 있다.
- upstart 구성을 추가하려면 EC2 인스턴스의 /etc/init에 파일을 생성하면 된다.
/etc/init/helloworld.conf 를 만들어보자
[ec2-user@ip-172-31-46-45 ~]$ sudo vim /etc/init/helloworld.conf
description "Hello world Deamon"
# Start when the system is ready to do networking.
# 시스템의 네트워크가 준비되면 시작(AWS 네트워크가 ENI[Elastic Network Interfaces] 기반이기에)
start on started elastic-network-interfaces
# Stop when the system is on its way down.
# 시스템이 다운되면 중지
stop on shutdown
respawn
script
exec su --session-command="/usr/bin/node /home/ec2-user/helloworld.js" ec2-user
end script
실행해 보자
[ec2-user@ip-172-31-46-45 ~]$ sudo start helloworld
helloworld start/running, process 13002
종료해 보자
Stop 명령어를 이용해 서비스를 완전히 종료하고 가상 서버에서 로그아웃한 후 인스턴스를 종료할 수 있다.
ec2-user@ip-172-31-46-45 ~]$ sudo stop helloworld
helloworld stop/waiting
[ec2-user@ip-172-31-46-45 ~]$ ec2-metadata -i
instance-id: i-0abd8725949bc6a5f
[ec2-user@ip-172-31-46-45 ~]$ exit
logout
$ aws ec2 terminate-instances --instance-ids i-0abd8725949bc6a5f
{
"TerminatingInstances": [
{
"CurrentState": {
"Code": 32,
"Name": "shutting-down"
},
"InstanceId": "i-0abd8725949bc6a5f",
"PreviousState": {
"Code": 16,
"Name": "running"
}
}
]
}
추가적으로 upstart 로 jar 파일은 다음과 같이 실행하면 되는 것 같다.
'DevOps' 카테고리의 다른 글
Docker container 를 활용해 CI/CD 실습해보자 feat(Jenkin, Ansible, Minikube) (0) | 2022.09.14 |
---|---|
Kubernetes 구조 이해하기 (0) | 2022.08.10 |
최신 (k8s - 2022.07 기준) kubernetes 설치 (0) | 2022.07.31 |
Terraform 을 사용해 AWS EC2 Instance 를 올려보자 (0) | 2022.07.26 |
IaaS , PaaS , SaaS (0) | 2022.07.20 |