๐Ÿง ATMS - CICD ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…(SSH Permission DeniedํŽธ)



์ง€๋‚œ ์‹œ๊ฐ„์— Jenkins ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋„์šฐ๊ณ , GitLab๊ณผ ๋ฐฐํฌ ์„œ๋ฒ„ ์–‘์ชฝ์— ์ธ์ฆ์„ ์—ฐ๊ฒฐํ•ด ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋ผˆ๋Œ€๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

โ–ถ ๐Ÿง ATMS - CICD ๊ตฌ์„ฑ

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ๊ทธ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹ค์ œ๋กœ ๋Œ๋ฆฌ์ž๋งˆ์ž ๋งˆ์ฃผ์นœ ์ฒซ ๋ฒˆ์งธ ๋ฒฝ โ€” SSH Permission Denied๋ฅผ ๋‹ค๋ฃจ๊ฒ ๋‹ค.



์ฆ์ƒ


Jenkinsfile์˜ Deploy ์Šคํ…Œ์ด์ง€, sshagent ๋ธ”๋ก ์•ˆ์—์„œ ๋ฐฐํฌ ์„œ๋ฒ„๋กœ ์ ‘์†ํ•˜๋Š” ์ˆœ๊ฐ„ ๋‹ค์Œ ์—๋Ÿฌ๊ฐ€ ๋–จ์–ด์กŒ๋‹ค.

deploy@10.0.20.15: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

ํ‚ค ํŽ˜์–ด๋Š” ๋ถ„๋ช…ํžˆ Jenkins ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์ƒ์„ฑํ•ด์„œ ์„œ๋ฒ„ ~/.ssh/authorized_keys์— ๋“ฑ๋กํ–ˆ๋Š”๋ฐ๋„ ๊ฑฐ๋ถ€๋‹นํ–ˆ๋‹ค.


Claude Code์™€ ํ•จ๊ป˜ ์ ‘๊ทผํ•œ ๋ฐฉ์‹

๋ฌด์ž‘์ • ์„ค์ •์„ ์ด๊ฒƒ์ €๊ฒƒ ๋ฐ”๊ฟ”๋ณด๊ธฐ ์ „์—, ssh -vvv ๋กœ ํ™•๋ณดํ•œ ์ƒ์„ธ ๋กœ๊ทธ๋ฅผ ๊ทธ๋Œ€๋กœ Claude Code์— ๋ถ™์—ฌ๋„ฃ๊ณ  "Offering public key ๋‹ค์Œ์— ๋ฐ”๋กœ ๊ฑฐ๋ถ€๋‹นํ•˜๋Š” ํŒจํ„ด์ด๋ฉด ๋ญ˜ ์˜์‹ฌํ•ด์•ผ ํ•˜๋‚˜" ๋ฅผ ๋ฌผ์œผ๋ฉฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ๋Œ์•„์˜จ ๋ฐฉํ–ฅ์€ "ํ‚ค ์ž์ฒด๋ณด๋‹ค, ์„œ๋ฒ„๊ฐ€ ํ‚ค๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ์•Š๋Š” ์กฐ๊ฑด(๊ถŒํ•œ ยท SELinux)๋ถ€ํ„ฐ ํ•˜๋‚˜์”ฉ ์†Œ๊ฑฐํ•˜์ž"์˜€๋‹ค โ€” ๊ทธ ์ˆœ์„œ๋ฅผ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ๊ฐ”๋‹ค.



๊ฐ€์„ค 1 โ€” ํ‚ค ํŽ˜์–ด๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ๊ฐ€?


๊ฐ€์žฅ ๋จผ์ € ์˜์‹ฌํ•œ ๊ฑด ๋‹จ์ˆœํ•œ ์‹ค์ˆ˜ โ€” ๋“ฑ๋กํ•œ ๊ณต๊ฐœํ‚ค์™€ ์‹ค์ œ ์‚ฌ์šฉ ์ค‘์ธ ๊ฐœ์ธํ‚ค๊ฐ€ ์„œ๋กœ ์ง์ด ์•ˆ ๋งž๋Š” ๊ฒฝ์šฐ๋‹ค.

# Jenkins ์ปจํ…Œ์ด๋„ˆ: ๊ฐœ์ธํ‚ค โ†’ ๊ณต๊ฐœํ‚ค ๋„์ถœ
ssh-keygen -y -f /var/jenkins_home/.ssh/atms_deploy_key

# ์–‘์ชฝ ํ•‘๊ฑฐํ”„๋ฆฐํŠธ ๋น„๊ต
ssh-keygen -l -f /var/jenkins_home/.ssh/atms_deploy_key
ssh-keygen -l -f /home/deploy/.ssh/authorized_keys

๋‘ SHA256 ํ•ด์‹œ๋Š” ์ •ํ™•ํžˆ ์ผ์น˜ํ–ˆ๋‹ค. ํ‚ค ์ž์ฒด๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋Š” ๋œป์ด๋‹ค.

โ†’ ๊ธฐ๊ฐ.



๊ฐ€์„ค 2 โ€” authorized_keys ์ค„๋ฐ”๊ฟˆ์ด ๊นจ์กŒ๋‚˜?


Windows ํ™˜๊ฒฝ์—์„œ ๊ณต๊ฐœํ‚ค๋ฅผ ๋ณต์‚ฌํ•ด ๋ถ™์—ฌ๋„ฃ๋Š” ๊ณผ์ •์ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์—, CRLF๊ฐ€ ์„ž์—ฌ ๋“ค์–ด๊ฐ€ ํ‚ค๊ฐ€ ๊นจ์กŒ์„ ๊ฐ€๋Šฅ์„ฑ๋„ ํ™•์ธํ–ˆ๋‹ค.

cat -A /home/deploy/.ssh/authorized_keys | grep '\^M'

^M์€ ๋ณด์ด์ง€ ์•Š์•˜๋‹ค. ์ค„๋ฐ”๊ฟˆ ์˜ค์—ผ๋„ ์•„๋‹ˆ์—ˆ๋‹ค.

โ†’ ๊ธฐ๊ฐ.


์—ฌ๊ธฐ๊นŒ์ง€ ํ™•์ธํ•˜๊ณ  ๋‚˜๋‹ˆ ์Šฌ์Šฌ ์ดˆ์กฐํ•ด์กŒ๋‹ค. ํ‚ค๋„ ๋งž๊ณ , ํŒŒ์ผ๋„ ๋ฉ€์ฉกํ•œ๋ฐ ์™œ ๊ฑฐ๋ถ€๋‹นํ•˜๋Š”๊ฐ€?



๊ฐ€์„ค 3 โ€” ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ ๊ถŒํ•œ์ด ๋„ˆ๋ฌด ์—ด๋ ค์žˆ๋‹ค


SSH๋Š” authorized_keys๋ฟ ์•„๋‹ˆ๋ผ ๊ทธ ์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋“ค์˜ ๊ถŒํ•œ๊นŒ์ง€ ๊น๊นํ•˜๊ฒŒ ๊ฒ€์‚ฌํ•œ๋‹ค. ํ™•์ธํ•ด๋ณด๋‹ˆ:

stat /home/deploy | grep Access
# (0775/drwxrwxr-x)

๊ทธ๋ฃน(Group)์— ์“ฐ๊ธฐ(w) ๊ถŒํ•œ์ด ์—ด๋ ค์žˆ์—ˆ๋‹ค. SSH ์ž…์žฅ์—์„œ๋Š” "๋‹ค๋ฅธ ๊ทธ๋ฃน ๊ณ„์ •์ด ์ด ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์šฉ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค = ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋‹ค"๊ณ  ํŒ๋‹จํ•˜๊ณ  ํ‚ค ์ธ์ฆ ์ž์ฒด๋ฅผ ๊ฑฐ๋ถ€ํ•œ๋‹ค.

chmod 755 /home/deploy
์ด chmod, ์ •๋ง ์•ˆ์ „ํ•œ๊ฐ€?
  • ์†Œ์œ ์ž(deploy)๋Š” ์›๋ž˜๋„ rwx๋ผ ๋ณ€ํ™” ์—†์Œ โ€” ๊ธฐ์กด ๋™์ž‘์— ์˜ํ–ฅ ์—†๋‹ค.
  • ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ(atms/, .ssh/ ๋“ฑ)๋Š” ๊ทธ๋Œ€๋กœ๋‹ค.
  • ์‹ค์ œ๋กœ ๋ง‰ํžˆ๋Š” ๊ฑด "๊ฐ™์€ ๊ทธ๋ฃน์˜ ๋‹ค๋ฅธ ๊ณ„์ •์ด ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ ๋ฃจํŠธ์— ํŒŒ์ผ์„ ์ง์ ‘ ์“ฐ๋Š” ๊ฒƒ" ๋ฟ์ด๊ณ , ์• ์ดˆ์— ๋ฆฌ๋ˆ…์Šค ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ‘œ์ค€ ๊ถŒํ•œ์ด 755๋‹ค. 775์˜€๋˜ ์ชฝ์ด ๋น„์ •์ƒ์ด์—ˆ๋‹ค.

๊ถŒํ•œ์„ ๊ณ ์น˜๊ณ  ๋‹ค์‹œ ์‹œ๋„ํ–ˆ๋‹ค.

...์—ฌ์ „ํžˆ Permission denied.



๊ฐ€์„ค 4 โ€” SELinux๊ฐ€ ๋ง‰๊ณ  ์žˆ๋‹ค


๋ฐฐํฌ ์„œ๋ฒ„๋Š” CentOS 7์ด์—ˆ๊ณ , SELinux๊ฐ€ Enforcing ์ƒํƒœ๋กœ ์ผœ์ ธ ์žˆ์—ˆ๋‹ค. ์ด๋ฒˆ์—” ํŒŒ์ผ ๊ถŒํ•œ(chmod)์ด ์•„๋‹ˆ๋ผ SELinux ์ปจํ…์ŠคํŠธ(๋ผ๋ฒจ) ๋ฅผ ์˜์‹ฌํ–ˆ๋‹ค.

ls -Z /home/deploy/.ssh/authorized_keys
unconfined_u:object_r:httpd_sys_content_t:s0

ssh_home_t์—ฌ์•ผ ํ•  ์ปจํ…์ŠคํŠธ๊ฐ€ httpd_sys_content_t(์›น์„œ๋ฒ„์šฉ ๋ผ๋ฒจ)๋กœ ์ง€์ •๋˜์–ด ์žˆ์—ˆ๋‹ค. SELinux๋Š” ํŒŒ์ผ ๊ถŒํ•œ๊ณผ ๋ณ„๊ฐœ๋กœ "์ด ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ด ๋ผ๋ฒจ์˜ ํŒŒ์ผ์— ์ ‘๊ทผํ•ด๋„ ๋˜๋Š”๊ฐ€"๋ฅผ ์ •์ฑ…์œผ๋กœ ํ•œ ๋ฒˆ ๋” ๊ฒ€์‚ฌํ•˜๋Š”๋ฐ, sshd ์ž…์žฅ์—์„œ๋Š” ์ด ๋ผ๋ฒจ์„ ์‹ ๋ขฐํ•˜์ง€ ์•Š์œผ๋‹ˆ ์กฐ์šฉํžˆ ์ ‘์†์„ ๊ฑฐ๋ถ€ํ•œ ๊ฒƒ์ด๋‹ค.

sudo restorecon -Rv /home/deploy/.ssh/
ls -Z /home/deploy/.ssh/authorized_keys
# โ†’ ssh_home_t ๋กœ ๋ณต์›๋จ
restorecon์ด ๊ฑด๋“œ๋ฆฌ๋Š” ๋ฒ”์œ„

SELinux ๋ผ๋ฒจ๋งŒ ์ •์ฑ… ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋˜๋Œ๋ฆด ๋ฟ, ํŒŒ์ผ ๋‚ด์šฉยท์†Œ์œ ์žยทchmod ๊ถŒํ•œ์€ ์ „ํ˜€ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. /home/deploy/.ssh/ ๋ฐ–์˜ ๋‹ค๋ฅธ ์„œ๋น„์Šค์—๋„ ์˜ํ–ฅ์ด ์—†๋‹ค.


๋‹ค์‹œ ์ ‘์†์„ ์‹œ๋„ํ–ˆ๋‹ค.

ssh -i /var/jenkins_home/.ssh/atms_deploy_key \
    -o PasswordAuthentication=no \
    deploy@10.0.20.15 "echo ์ ‘์†์„ฑ๊ณต"
์ ‘์†์„ฑ๊ณต

๋“œ๋””์–ด ๋šซ๋ ธ๋‹ค.



๊ฒฐ๋ก 

  • ํ‚ค ํŽ˜์–ด ๋ถˆ์ผ์น˜ X
  • authorized_keys ์ค„๋ฐ”๊ฟˆ ์˜ค์—ผ X
  • ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ ๊ถŒํ•œ(775) โ€” ์›์ธ O (์ผ๋ถ€)
  • SELinux ์ปจํ…์ŠคํŠธ(httpd_sys_content_t) โ€” ์ง„์งœ ์›์ธ O

ํ•˜๋‚˜์˜ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋’ค์— ์›์ธ์ด ๋„ค ๊ฐœ๋‚˜ ๊ฒน์ณ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ์ด๋ฒˆ์— ์ œ๋Œ€๋กœ ๋ฐฐ์› ๋‹ค. ํŠนํžˆ SELinux๋Š” chmod/ls -l๋งŒ ๋ด์„œ๋Š” ์ ˆ๋Œ€ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์•„์„œ, ๊ถŒํ•œ์„ ๋‹ค ๋งž์ท„๋Š”๋ฐ๋„ ์—ฌ์ „ํžˆ ๊ฑฐ๋ถ€๋‹นํ•œ๋‹ค๋ฉด ls -Z๋ถ€ํ„ฐ ํ™•์ธํ•˜๋Š” ์Šต๊ด€์„ ๋“ค์ด๊ฒŒ ๋๋‹ค.


๋‹ค์Œ์—๋Š”, ๋ฐฐํฌ์— ์„ฑ๊ณตํ•œ ํ›„ ๊ณง๋ฐ”๋กœ ๋งˆ์ฃผ์นœ ๋‘ ๋ฒˆ์งธ ๋ฏธ์Šคํ„ฐ๋ฆฌ โ€” ๋กœ๊ทธ ํ•œ ์ค„ ์—†์ด ๋œจ๋Š” CORS 403์„ ๋‹ค๋ค„๋ณด๊ฒ ๋‹ค.