Skip to content

fix: SSH PEM 키 의존성 제거 → SSM RunCommand 방식으로 전환#42

Merged
Hexeong merged 2 commits into
mainfrom
fix/41-ssh-command-to-ssm-command
Jun 13, 2026
Merged

fix: SSH PEM 키 의존성 제거 → SSM RunCommand 방식으로 전환#42
Hexeong merged 2 commits into
mainfrom
fix/41-ssh-command-to-ssm-command

Conversation

@Hexeong

@Hexeong Hexeong commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

작업 내용

null_resource의 EC2 원격 실행 방식을 SSH + PEM 키에서 AWS SSM RunCommand로 전환합니다.

변경 파일: modules/app_stack/ec2.tf, modules/app_stack/variables.tf, environment/prod/main.tf, environment/prod/variables.tf, environment/stage/main.tf, environment/stage/variables.tf

  • null_resource.update_nginx, null_resource.update_side_infra 두 리소스의 SSH connection 블록 및 file / remote-exec provisioner 제거
  • local-exec provisioner로 교체 — aws ssm send-command(AWS-RunShellScript)로 스크립트 전송 및 실행
  • 스크립트 내용은 base64encode(templatefile(...)) 후 EC2에서 base64 -d | sudo bash로 실행
  • SSM 명령 완료를 10초 간격 폴링(최대 3600초)으로 대기하며, 실패 시 StandardErrorContent 출력 후 종료
  • locals 블록을 단계별로 분리 (alloy_config*_script_b64*_ssm_params) 하여 가독성 확보
  • var.ssh_key_path 변수 전 계층(모듈, prod, stage)에서 제거

특이 사항

  • 근본 원인: GitHub Actions 러너에 PEM 키 파일(../../solid-connection-server-2.pem)이 존재하지 않아 file() 함수 자체가 실패. PR refactor: upstream config 파일로 nginx 블루-그린 배포 환경 세팅 #37 머지 시 null_resource.update_nginxtriggers.script_hash가 변경되어 처음 표면화됨
  • IAM 변경 불필요: aws ssm send-command는 GitHub Actions 러너(OIDC role)가 호출하며, Apply role에 연결된 GitHubActionsTerraformInfraPolicyssm:SendCommand / ssm:GetCommandInvocation이 이미 포함되어 있음. EC2 SSM Agent 수신 측은 bootstrap에서 AmazonSSMManagedInstanceCore가 이미 부착되어 있음
  • key_name(AWS Key Pair 등록명)은 EC2 인스턴스 생성 시 필요하므로 유지, PEM 파일 경로(ssh_key_path)만 제거

리뷰 요구사항 (선택)

  • SSM RunCommand 폴링 로직(10초 간격 × 360회 = 최대 3600초)이 nginx 초기 설치(certbot 포함) 및 side infra 설정에 충분한지 확인 부탁드립니다

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Terraform 프로비저닝에서 GitHub Actions 환경의 SSH PEM 키 파일 부재 문제를 해결하기 위해, SSH 기반 remote-exec 방식을 AWS SSM send-command 폴링 방식으로 전환하고 ssh_key_path 변수를 모든 환경에서 제거.

Changes

SSH 키 의존성 제거 및 SSM 기반 프로비저닝 전환

Layer / File(s) Summary
환경 전반에서 SSH 키 변수 제거
environment/prod/main.tf, environment/prod/variables.tf, environment/stage/main.tf, environment/stage/variables.tf, modules/app_stack/variables.tf
prod와 stage 환경 설정 파일의 module 블록에서 ssh_key_path 입력을 제거하고, 모든 환경 정의 및 모듈 변수에서 ssh_key_path 변수 선언을 삭제하여 SSH 키 파일 의존성 제거.
AWS SSM 기반 프로비저닝 구현
modules/app_stack/ec2.tf
locals 블록에서 Nginx와 side infra 셸 스크립트를 base64로 인코딩하고 Alloy 설정을 모니터링 서버 IP로 렌더링. null_resource.update_nginxnull_resource.update_side_infra의 SSH 기반 connection/file/remote-exec 프로비저너를 제거하고, local-exec을 통해 aws ssm send-command로 명령을 전송한 후 get-command-invocation을 최대 60회 폴링(10초 간격)하여 실행 결과 추적.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • solid-connection/solid-connection-infra#11: modules/app_stack/ec2.tfnull_resource.update_nginxnull_resource.update_side_infra 자체를 처음 도입한 변경과 직접적으로 연결되어 있으며, 이 PR은 그 구현 방식을 SSH에서 SSM으로 전환하는 후속 수정.

Suggested labels

인프라

Suggested reviewers

  • wibaek
  • whqtker
  • JAEHEE25
  • lsy1307
  • sukangpunch
  • Gyuhyeok99

Poem

🐰 SSH 키 없이도 구름 위로 날아,
SSM의 손 잡고 EC2에 도착해,
GitHub Actions의 제약 넘어
안전한 IAM 권한으로 서버를 깨워내네! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항(SSH PEM 키 의존성 제거 및 SSM RunCommand 방식 전환)을 명확하고 간결하게 요약하고 있습니다.
Linked Issues check ✅ Passed 이슈 #41의 모든 기술 요구사항이 충족되었습니다: SSH/PEM 제거, SSM RunCommand 전환, 스크립트 base64 인코딩, 폴링 로직 구현, 변수 제거 완료.
Out of Scope Changes check ✅ Passed 모든 변경사항이 이슈 #41의 요구사항 범위 내에 있으며, SSH 제거와 SSM 전환에 필요한 파일들만 수정되었습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed PR 설명이 대부분 완전하며 필수 섹션을 모두 포함하고 있습니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/41-ssh-command-to-ssm-command

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown

Terraform Plan: stage

Plan: 1 to add, 0 to change, 1 to destroy.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown

Terraform Plan: prod

Plan: 1 to add, 0 to change, 1 to destroy.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modules/app_stack/rds.tf (1)

20-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

AWS 리소스에 필수 태그 추가 필요.

코딩 가이드라인에 따라 모든 AWS 리소스에 Project = "solid-connection"Env = "<환경명>" 태그를 적용해야 합니다. 현재 aws_db_instance.defaultName 태그만 정의되어 있습니다.

변수 var.env_name이 모듈 입력으로 제공되므로, 다음과 같이 태그 블록을 확장해주세요.

🏷️ 필수 태그 추가 제안
   tags = {
     Name    = var.rds_identifier
+    Project = "solid-connection"
+    Env     = var.env_name
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modules/app_stack/rds.tf` around lines 20 - 22, The aws_db_instance.default
resource currently only sets Name; update its tags block to include the required
Project and Env tags by adding Project = "solid-connection" and Env =
var.env_name while preserving the existing Name = var.rds_identifier entry so
the tags map contains all three keys.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modules/app_stack/ec2.tf`:
- Around line 78-85: The SSM executionTimeout is set to 3600s (in
nginx_ssm_params and side_infra_ssm_params) but the Terraform polling loop times
out much earlier; update the polling timeout to match the SSM 3600s window (or
reduce executionTimeout to the polling window) so apply doesn't fail while SSM
is still running — change the polling configuration used by the resource that
invokes nginx_ssm_params and side_infra_ssm_params and make the identical change
for update_side_infra so all three locations use the same 3600s-aligned timeout.

---

Outside diff comments:
In `@modules/app_stack/rds.tf`:
- Around line 20-22: The aws_db_instance.default resource currently only sets
Name; update its tags block to include the required Project and Env tags by
adding Project = "solid-connection" and Env = var.env_name while preserving the
existing Name = var.rds_identifier entry so the tags map contains all three
keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a580b233-02dd-4679-8598-1de9bf6d2813

📥 Commits

Reviewing files that changed from the base of the PR and between 5ab67c4 and 94fbdcf.

📒 Files selected for processing (7)
  • environment/prod/main.tf
  • environment/prod/variables.tf
  • environment/stage/main.tf
  • environment/stage/variables.tf
  • modules/app_stack/ec2.tf
  • modules/app_stack/rds.tf
  • modules/app_stack/variables.tf
💤 Files with no reviewable changes (4)
  • environment/stage/variables.tf
  • environment/prod/variables.tf
  • modules/app_stack/variables.tf
  • environment/stage/main.tf

Comment thread modules/app_stack/ec2.tf

@lsy1307 lsy1307 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 의견입니다.

GitHub Actions apply role에도 SSM RunCommand 권한이 필요합니다.

이번 변경은 EC2가 SSM 명령을 받을 수 있게 하는 것뿐 아니라, Terraform 실행 주체가 직접 아래 명령을 호출하는 구조입니다.

aws ssm send-command
aws ssm get-command-invocation

따라서 EC2 IAM Instance Profile의 AmazonSSMManagedInstanceCore 권한만으로는 충분하지 않고, GitHub Actions에서 assume하는 apply role에도 최소한 아래 권한이 필요합니다.

ssm:SendCommand
ssm:GetCommandInvocation

현재 bootstrap 코드에서는 GitHubActionsTerraformInfraPolicy를 수동 관리 policy로 참조만 하고 있어서, 해당 policy에 위 권한이 이미 포함되어 있는지 코드상 확인이 어렵습니다. 포함되어 있지 않으면 merge 후 apply에서 AccessDeniedException으로 실패할 수 있습니다.

PR 본문에 “GitHub Actions apply role에 SSM RunCommand 호출 권한 확인 완료”를 명시하거나, 실제 관리 policy에 권한이 반영되어 있는지 확인이 필요해 보입니다.

SSM RunCommand 전환 방향 자체는 좋습니다. PEM 파일 의존성을 제거하는 목적에도 잘 맞고, timeout도 현재 head 기준 360 * 10s = 3600s로 SSM executionTimeout과 맞춰져 있습니다.

@lsy1307 lsy1307 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

라인별로 확인해야 할 부분만 남깁니다.

Comment thread modules/app_stack/ec2.tf
command = <<-EOT
set -euo pipefail
INSTANCE_ID='${aws_instance.api_server.id}'
COMMAND_ID=$(aws ssm send-command \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서 Terraform 실행 주체가 직접 aws ssm send-command를 호출합니다.

EC2 IAM Instance Profile의 AmazonSSMManagedInstanceCore는 명령을 받는 managed instance 권한이고, 명령을 보내는 GitHub Actions apply role에는 별도로 최소 아래 권한이 필요합니다.

ssm:SendCommand
ssm:GetCommandInvocation

현재 bootstrap 코드에서는 GitHubActionsTerraformInfraPolicy를 수동 관리 policy로 참조만 해서, 해당 권한 포함 여부가 코드상 확인되지 않습니다. 포함되어 있지 않으면 merge 후 apply에서 AccessDeniedException으로 실패할 수 있으니, 실제 policy 반영 여부를 확인하거나 PR 본문에 확인 완료를 명시하는 게 좋겠습니다.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 권한은 이미 확인했습니다. PR 설명에 오해가 있었네요;; 해당 설명 수정하였습니다!

Comment thread modules/app_stack/ec2.tf
"rm /tmp/update_nginx.sh"
]
provisioner "local-exec" {
interpreter = ["bash", "-c"]

@Hexeong Hexeong Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미 저희 운영 방칙 상 액션 러너(우분투)로 진행하도록 합의를 했었기에 괜찮다고 생각합니다. 이미 로컬 apply를 막게 정했기에 문제가 없을 것 같습니다! 해당 부분은 협업 워크플로우 wiki 문서에 문서화되어 있으니 확인부탁드립니다~

Comment thread modules/app_stack/ec2.tf
"rm /tmp/update_nginx.sh"
]
provisioner "local-exec" {
interpreter = ["bash", "-c"]

@Hexeong Hexeong Jun 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미 저희 운영 방칙 상 액션 러너(우분투)로 진행하도록 합의를 했었기에 괜찮다고 생각합니다. 이미 로컬 apply를 막게 정했기에 문제가 없을 것 같습니다! 해당 부분은 협업 워크플로우 wiki 문서에 문서화되어 있으니 확인부탁드립니다~

@lsy1307 lsy1307 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다!

@Hexeong Hexeong merged commit c68bdbd into main Jun 13, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: null_resource SSH PEM 키 의존성 제거 → SSM RunCommand 방식으로 전환

2 participants