일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 추가 보안 그룹
- 에이전트 유형
- clusterrolebinding
- IRSA
- saa-c03 #saa #aws certified solutions architect - associate
- ingestion
- fruition
- httpasswd
- Docker0
- 에이전트 구성
- NAT
- Terraform
- Pipeline
- route53
- Amazon CloudWatch
- s3
- instances failed to join cluster
- jenkins
- 테라폼
- Service Account
- 코드커버리지
- node group
- assumerole
- aws-loadbalacner-controller
- docker
- Gateway
- helm_release
- aws ses #aws lambda
- kubernetes
- 클러스터 보안 그룹
- Today
- Total
cloudwithbass
[Terraform] 테라폼 연습하기 5: security group 본문
지난 포스팅에서 ec2 인스턴스를 생성했습니다.
이번 포스팅에서는, ec2 구성 시 반드시 확인해야 하는 보안 그룹에 대해 알아보겠습니다.
보안 그룹의 인그레스 규칙이 설정되지 않으면, 라우팅 테이블이 제대로 구성되어 있어도 트래픽이 인스턴스에 도달할 수 없습니다.
이번 포스팅에선 테라폼으로 security group을 구성합니다.
소스 코드는 다음 github 주소에서 확인 가능합니다.
https://github.com/Dminus251/practice-terraform/tree/main/demo05-sg
목차
1. 보안 그룹 모듈 구성하기
modules/t-aws-sg/main.tf
보안 그룹 모듈입니다.
aws_security_group 테라폼 문서를 참조해 작성합니다.
'코드를 어떻게 짜야 간결성과 재사용성을 높일 수 있을까?' 생각하다가 object 타입의 변수를 사용하기로 했습니다.
2024.09.06 수정: 추후 aws_security_group_rule이라는 리소스를 알게 됐고, 이 방법이 모듈화에 더 편리해서 demo07부터 aws_security_group_rule 리소스를 사용하도록 변경했습니다.
resource "aws_security_group" "sg" {
name = var.sg-name
vpc_id = var.sg-vpc_id
ingress {
from_port = var.ingress["from_port"]
to_port = var.ingress["to_port"]
protocol = var.ingress["protocol"]
cidr_blocks = var.ingress["cidr_blocks"]
security_groups = var.ingress["security_groups"]
}
#나가는 건 딱히 제한하지 않아도 될 듯..?
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
modules/t-aws-sg/vars.tf
variable "sg-vpc_id"{
type = string
}
variable "ingress" {
type = object({
from_port = number,
to_port = number,
protocol = string,
cidr_blocks = list(string),
security_groups = list(string),
})
}
variable "sg-name" {
type = string
}
상술했듯 ingress 변수를 object 타입으로 선언했습니다.
object 타입은 map 타입 처럼 중괄호를 사용하지만, 주로 리소스의 attribute를 나타내기 위한 데이터 구조입니다.
따라서 map과 다르게 변수의 type이 하나로 강제되지 않고 number, string, list(string) 등을 사용할 수 있습니다.
modules/t-aws-sg/output.tf
output "sg-id" {
value = aws_security_group.sg.id
}
보안 그룹을 ec2 instance에 할당하기 위해 output으로 보안 그룹의 id를 내보냅니다.
2. 루트 모듈 구성하기
이해를 위해 main.tf를 보기 전에 vars.tf부터 확인하겠습니다.
vars.tf
루트 모듈의 vars.tf 중 일부입니다.
variable "sg-ingress" {
type = object({
from_port = number,
to_port = number,
protocol = string,
cidr_blocks = list(string),
security_groups = list(string),
})
default = {
from_port = 22,
to_port = 22,
protocol = "tcp",
cidr_blocks = ["0.0.0.0/0"],
security_groups = []
}
}
sg-ingress라는 변수를 선언했습니다.
security group의 ingress 값으로 사용할 변수이며, default 값으로 모든 트래픽에서 온 22번 포트의 tcp 통신을 허용합니다.
22 포트는 ssh 연결에 사용됩니다.
main.tf
먼저 달라진 부분은 ec2 instance 모듈의 ec2-sg 변수를 추가한 점입니다.
module "ec2_public" {
# other configurations ...
ec2-sg = [module.sg-public-allow_ssh.sg-id]
}
module "ec2_private" {
# other configurations ...
ec2-sg = [module.sg-private-allow_ssh.sg-id]
}
밑에 선언할 보안 그룹 모듈의 id를 사용합니다.
aws_instance의 테라폼 문서를 보면, 보안 그룹은 list(string) 타입으로 할당되어야 하기 때문에 리스트에 id를 넣습니다.
(당연히 ec2 instance 모듈에서 security group variable을 선언해야 합니다.)
다음으로
public subnet과 private subnet의 보안 그룹 내용이 다르기 때문에 보안 그룹 모듈을 두 개생성했습니다.
먼저 public subnet의 보안 그룹 모듈입니다.
#public subnet의 instance에 할당. 0.0.0.0/0에서 ssh를 허용함
module "sg-public-allow_ssh" { #0.0.0.0/0에서 ssh 허용
source = "./modules/t-aws-sg"
sg-vpc_id = module.vpc.vpc-id
ingress = var.sg-ingress
sg-name = "sg_public" #sg 이름에 하이픈('-') 사용 불가
}
ingress의 sg-ingress 변수의 default 값을 그대로 사용합니다.
public subnet에 사용할 보안 그룹이므로 default인 0.0.0.0/0에서 22번 포트의 tcp 프로토콜을 허용하도록 했습니다.
만약 default 값을 이용하고 싶지 않은 경우, 아래 private subnet의 sg 모듈처럼 코드를 구성하면 됩니다.
#private subnet의 instanec에 할당. public subnet의 cidr에서의 ssh 허용
module "sg-private-allow_ssh" { #public subnet에서의 ssh 허용
source = "./modules/t-aws-sg"
sg-vpc_id = module.vpc.vpc-id
ingress = {
from_port = var.sg-ingress.from_port
to_port = var.sg-ingress.to_port
protocol = var.sg-ingress.protocol
cidr_blocks = var.public_subnet-cidr
security_groups = var.sg-ingress.security_groups
}
sg-name = "sg_private"
}
ingress에서 cidr_block을 public subnet의 cidr로 구성했습니다.
나머지 ingress 요소들은 default 값을 사용했습니다.
따라서 이 보안 그룹을 할당 받은 ec2 instance는 public subnet의 22번 포트로 온 트래픽만 인바운드로 허용하게 됩니다.
3. 테스트
mobaXterm을 이용해 ssh 연결이 잘 되는지 테스트하겠습니다.
3-1. localhost에서 private subnet으로 접속
당연히 로컬 호스트에서 private subnet의 private ip address로 ssh 연결은 불가능합니다.
3-2. public subnet에서 private subnet으로 접속
localhost에서 public subnet의 인스턴스와 ssh 연결한 상태입니다.
private-0 인스턴스의 private ip는 10.0.0.188/24입니다.
아래 사진처럼 정상적으로 private subnet의 인스턴스와 ssh 연결에 성공한 것을 확인했습니다.
다음은 private-1 인스턴스입니다.
이 인스턴스의 ip는 10.0.2.109/24고, 마찬가지로 ssh 연결에 성공했습니다.
'Terraform' 카테고리의 다른 글
Terraform 연습하기 7: 'instances failed to join cluster' 트러블 슈팅 (3) | 2024.09.05 |
---|---|
[Terraform] ★ 테라폼 연습하기 6: eks cluster 구성과 Assume Role, kubeconfig (0) | 2024.09.01 |
[Terraform] 테라폼 연습하기 4: ec2 instance (0) | 2024.08.29 |
[Terraform] 테라폼 연습하기3: NAT gateway (0) | 2024.08.27 |
[Terraform] 모듈화 연습하기1: VPC와 Subnet, 모듈화 (0) | 2024.08.25 |