IaC/Ansible 실습

sudo | sudo를 사용할 수 있는 사용자, Passwordless Sudo 설정 방법

Greta Lee 2021. 8. 6. 04:25
SMALL

1. sudo를 사용할 수 있는 사용자는?

정답 : 배포판마다 다릅니다.

(RedHat 계열은 wheel 그룹의 사용자, Debian 계열은 /etc/sudoers에 등록된 사용자)


근본적인 이야기부터 해 봅시다. sudo를 왜 사용하나요?

일반 사용자가 root 권한을 얻기 위해서입니다. 그러면 왜 root 권한을 얻어야 하나요?

대부분의 시스템 관리 작업은 root 권한이 아니면 할 수가 없기 때문입니다. 가령 패키지를 설치하거나, 서비스를 start/restart/stop 하거나, etc/의 대부분의 설정 파일을 변경하는 등의 작업은 root 권한이 없으면 할 수 없습니다. 이처럼 사용자들이 임의적으로 접근 제어(Access Control)를 세팅하는 임의 접근 통제(DAC; Discretionary Access Control) 방식의 가장 큰 문제는, root라는 슈퍼유저 관리자는 permission의 영향을 받지 않는다는 것입니다.


vagrant 사용자가 a 라는 파일을 만들어, 소유자만 읽을 수 있도록 권한을 부여했습니다. 말 그대로 vagrant 사용자가 임의적으로 파일 a에 대한 접근 제어를 자기 자신으로 제한을 걸었고, 자기 자신조차도 '읽기만' 하도록 되어 있습니다. 그런데 root 권한으로는 a 파일에 '쓰기'가 가능합니다. 이는 슈퍼 유저(root)가 permission에 아무 영향을 받지 않기 때문입니다. 슈퍼 유저는 시스템에 있는 모든 작업을 다 할 수 있다는 점에서 슈퍼 유저는 매우 위험합니다. 이것이 DAC의 가장 큰 약점입니다.

◆ 이런 DAC의 약점을 보완하기 위해, 슈퍼 유저의 권한을 떼어 유저에게 역할을 부여하는 역할 기반 접근 제어(RBAC; Role-Based Access Control)는 방식을 일반적으로 사용합니다. RBAC는 컴퓨터 시스템 보안에서 권한이 있는 사용자들에게 시스템 접근을 통제하는 한 방법입니다.


대부분의 시스템 관리 작업은 root 권한이 필요합니다. 그러면 ssh 접속을 처음부터 root로 접속하면 안 되나요?

SSH 프로토콜은 암호화 프로토콜이기 때문에 패스워드를 네트워크 패킷 자체에서 볼 수 있는 것은 아닙니다. 그렇지만 모든 암호화는 MITM 형태의 중간자 공격에 취약합니다. 즉 중간에서 누군가가 암호화를 Decrypt(복호화) 할 수 있다면 아무리 암호화를 해도 문제가 생길 것입니다. 그래서 다이렉트하게 root로 ssh 접속하는 것은 보안상 좋지 못합니다. 최소한 일반 사용자로 접속을 하는 것이 안전하기에 이를 권장합니다. (그런데 사실 클라이언트 입장에서 서버의 일반 사용자의 이름은 잘 알 수가 없습니다. root라고 하는 사용자는 무조건 정해져 있기 때문에 알 수 있지만요.) 만약 중간자 공격에 의해 패스워드가 노출된다 하더라도, 해당되는 일반 사용자 계정의 패스워드가 노출되는 것이지 root의 패스워드가 노출되는 것은 아니기 때문에 보안 측면에서 훨씬 안전합니다.

요약하면, root로 다이렉트로 ssh 접속하는 것은 보안상 위험한 방법이라는 것입니다. 그래서 일반 사용자로 ssh 접속을 합니다. 그런데 일반 사용자 권한을 가지고서는 시스템을 구성 관리, 운영하지 못합니다. 그렇기 때문에 일반 사용자는 슈퍼 유저 관리자 권한을 취득할 필요가 있습니다.


su와 sudo

관리자 권한을 얻기 위해 사용할 수 있는 방법은 2가지가 있습니다.

  • su
  • sudo


결론부터 이야기하면 su는 웬만하면 절대로 사용하지 말아야 합니다. 그래서 반드시 sudo의 사용을 적극 권장합니다.

vagrant라는 일반 유저가 root 권한을 얻으려면 su와 sudo를 사용할 수 있습니다. su와 sudo는 둘 다 기본적으로 패스워드가 필요하다는 점에서 공통적입니다. 그런데 누구의 패스워드를 요구하냐는 점에서는 차이가 있습니다.

su는 로그인하려는 대상의 패스워드를 입력합니다. 그래서 root로 접속하려면 로그인 대상인 root의 패스워드를 알아야 합니다. a, b, c라는 사용자가 시스템 구성 관리 및 운영을 위해 su를 사용해 root로 접속한다는 것은 a, b, c 세 사용자가 root의 패스워드를 공유한다는 의미이기도 합니다. 그러나 패스워드를 공유하는 것은 그리 좋은 방법이 아닙니다. 만약 어떤 작업으로 인해 시스템에 문제가 발생했거나 누군가가 데이터를 유출했을 때, su로 root 권한을 얻어 작업을 하고 log까지 지워버렸다면, a, b, c 중 어떤 사용자로 인해 문제가 발생했는지 알기가 어렵습니다. 시스템 입장에서는 다 root가 한 작업이 되어버리기 때문에 책임 추적성을 추적하는 방법이 없다고는 할 수 없지만 어렵습니다. 따라서 su는 정말로 대안이 없지 않는 한 사용해서는 안 됩니다.

한편 sudo는 접속하려고 하는 자기 자신의 패스워드를 입력합니다. 그런데 자기 자신의 패스워드를 사용하여 root에 접속하는 것이 과연 보안 강화에 도움이 될까요? 잊어버리지 않는 한 자기 자신의 패스워드를 모르는 사람은 없는데, 자기 자신의 패스워드를 알기만 하면 다 root로 접속할 수 있을까요? 당연히 그렇지 않습니다.

sudo는 사용할 수 있는 사용자가 정해져 있습니다. 다시 말해 아무나 sudo를 사용할 수 있는 것이 아니며, sudo를 사용할 수 있는 사용자는 ubuntu의 경우 /etc/sudoers 파일에 정의되어 있습니다.

su라고 하면, Switch User의 줄임말로 알고 있는 사람들이 많습니다. 그런데 이는 잘못된 정보입니다. 정식 명칭은 Substitute user입니다.


/etc/sudoers

/etc/sudoers 파일은 root 사용자와 root 그룹만 읽기가 가능합니다. root 사용자만 읽을 수 있다는 것은, root 사용자가 쓰기가 불가능하다는 뜻으로 해석해서는 안됩니다. 앞서 말했듯 root 사용자는 permissioin의 제한을 받지 않기 때문입니다.


파일의 내용을 살펴봅시다.

cat /etc/sudoers

%는 그룹을 의미합니다. 해당 그룹에 포함된 사용자는 sudo를 사용할 수 있습니다.

  • root ALL=(ALL:ALL) ALL : root가 root로 sudo 사용 가능
  • %admin ALL=(ALL) ALL : admin 그룹이 sudo 사용 가능
  • %sudo ALL=(ALL:ALL) ALL : sudo 그룹이 sudo 사용 가능

사용자/&그룹 ALL=(ALL) ALL

- 첫 번째 필드 : 사용자 or %그룹
- 두 번째 필드 : ALL=(ALL) or ALL=(ALL:ALL)
→ 괄호 안의 ALLALL:ALL은 동일한 표현입니다. =(등호)를 기준으로 왼쪽 ALL은 Host이고, 오른쪽 ALL은 User입니다.
- 세 번째 필드 : ALL → Command

이를 바꿔 표현하면 다음과 같습니다. 특정 사용자 또는 그룹이 특정 Host에서만

사용자/%그룹 Host=(User) Command


* HOST : sudo를 사용할 수 있는 특정 호스트 지정
클라이언트가 서버에 ssh로 접속해서 sudo를 사용하는데, 이 때 특정 호스트를 지정한다는 것은 특정 클라이언트 시스템에서만 sudo 사용을 가능하도록 한다는 의미입니다. 다른 호스트(클라이언트)에서는 sudo 사용을 제한합니다. 심지어 localhost를 Host로 지정할 수도 있습니다. localhost에서 접속할 때만 sudo를 사용할 수 있고, ssh로 다른 원격 호스트에서 접속했을 경우에는 sudo를 사용할 수 없습니다. 또는 잘 사용하지는 않지만, Host에 특정 IP를 지정하게 되면, 그 IP를 가진 시스템에서만 sudo를 사용할 수 있습니다. Host를 ALL로 지정했다는 것은 어떤 호스트에서나 sudo를 사용할 수 있다는 의미입니다.

* (USER) : sudo를 누구의 권한으로 실행할 것인지 지정
괄호 안을 비워놓거나 / ALL로 지정하거나 / root로 지정하면 root로 지정됩니다. 만약 다른 사용자로 지정하면, sudo를 실행할 때 해당 사용자의 권한으로 실행됩니다. 그러나 sudo를 사용하는 이유는 관리자 권한을 얻기 위함이므로 일반적으로는 root 권한으로 지정합니다.

* Command : sudo를 실행할 수 있는 명령어

ALL로 지정하면 모든 명령어에서 sudo를 실행할 수 있습니다. 만약 ls라고 지정한다면, ls 명령어에만 sudo를 실행할 수 있습니다.


그런데 sudoers 파일에 vagrant 사용자를 따로 등록해주지 않았는데 vagrant 사용자는 sudo를 사용할 수 있습니다. 이것은 어떻게 된 일일까요?


id -a를 실행하면 로그인된 사용자가 속해 있는 모든 그룹을 볼 수 있습니다. vagrant 사용자는 vagrant 그룹에 속해 있습니다.


sudoers 파일의 맨 마지막 라인을 보면 includedir /etc/sudoers.d 라는 주석이 있습니다. 이는 /etc/sudoers.d 디렉토리에도 설정이 추가로 되어 있다는 의미입니다.


해당 디렉토리를 확인해보겠습니다. /etc/sudoers.d/ 밑에 90-cloud-init-user 파일에는 ubuntu 사용자가 등록되어 있고, vagrant 파일에는 vagrant 사용자가 등록되어 있습니다. 이 때문에 지금까지 vagrant 사용자가 sudo를 사용할 수 있었던 것입니다.

ls /etc/sudoers.d/


◆ /etc/sudoers.d 디렉토리는 추가된 것이고, /etc/sudoers 파일이 운영체제에 기본적으로 세팅된 설정 파일입니다.


주의할 점이 있습니다. /etc/sudoers 파일을 실수로 잘못 수정하게 되면 sudo를 사용할 수 없습니다. /etc/sudoers 파일은 보안에 정말 중요한 파일이기 때문에 오타 하나라도 잘못 치면 sudo를 사용할 수 없습니다. 다음은 오타로 인해 sudoers 파일에 syntax error가 발생한 예제입니다.


오타를 수정하기 위해 sudoers 파일을 수정하려 해도, 이미 오류가 발생한 sudoers 파일은 수정할 수가 없습니다.


이렇게 sudo가 막힌 상태에서, root 패스워드가 세팅되어 있지 않다면 su도 사용할 수가 없습니다. su로 root 접속을 하려면 root의 패스워드를 알아야 하는데 root 패스워드가 세팅되어 있지 않기 때문입니다.


이렇게 sudo와 su가 막히게 되면, root의 권한을 취득할 수 있는 방법은 없습니다. 해결할 수 있는 방법은 없습니다. 더 이상 해당 계정은 root로 접속할 수 없습니다.

◆ ssh 접속시 root로의 접속을 방지하기 위해서는, 설정으로도 방지할 수 있지만 애초에 root의 패스워드를 세팅해놓지 않는 방법이 있습니다. 그렇게 되면 su를 사용하여 root로 접속할 수 없어지기 때문입니다. 그래서 퍼블릭 클라우드의 경우 root의 패스워드가 세팅되어 있지 않습니다. 즉 퍼블릭 클라우드에서는 su를 사용하여 root 접속을 할 수 없습니다.


visudo

따라서 vi 에디터를 사용해서 /etc/sudoers 파일을 수정하는 것은 권장하지 않습니다. 다른 안전한 방법이 있는데 그것이 바로 visudo입니다. visudo는 나노 에디터를 사용합니다.

  • Ctrl + O : 파일 저장(Write Out)
  • Ctrl + X : 나가기(Exit)


마찬가지로 visudo에서 일부러 오타를 내었습니다.

sudo visudo


Ctrl+O, Ctrol+X로 저장하고 나오면 syntax error가 발생했다는 메세지와 함께 3가지 옵션을 물어봅니다.

  • e : 다시 수정
  • x : 저장하지 않음
  • Q : 무시하고 저장


이처럼 visudo는 단순히 /etc/sudoers 파일을 수정해주는 것뿐만 아니라, 수정 후 저장하고 나올 때 문법 체크까지 해 줍니다. 아까처럼 vi 에디터로 수정했을 때는 문법 체크를 해주지 않아 잘못 수정하면 root의 통제권을 잃어버리는 경우가 발생할 위험이 있습니다. 따라서 vi /etc/sudoers 보다는 visudo를 사용하여 수정하는 것을 권장합니다.


2. Passwordless Sudo 설정 방법?


앞서 살펴봤던 /etc/sudoers.d/vagrant 파일을 다시 확인해봅시다. 세 번째 Command 지정 필드에 그냥 ALL이 아닌, NOPASSWD:ALL로 지정되어 있는 것을 볼 수 있습니다.


이는 Passwordless Sudo를 의미합니다. 말 그대로 패스워드를 사용하지 않는 sudo 방식입니다. vagrant 사용자가 sudo를 사용할 때 패스워드를 물어보지 않는 이유는 바로 sudoers 파일에 NOPASSWD:ALL로 세팅되어 있기 때문입니다.


Passwordless Sudo를 사용하는 이유는 매번 sudo를 사용할 때마다 패스워드를 입력하는 것이 번거롭기 때문이기도 하지만, 근본적인 이유는 애초에 패스워드가 없는 계정(패스워드가 세팅되어 있지 않고 ssh 키 기반 인증만 되어 있는 계정)도 있기 때문입니다. 다시 말해, 자신의 패스워드가 세팅되어 있지 않는 사용자의 경우 sudo를 사용할 때 입력할 패스워드가 없기 때문에 sudo를 사용할 수 없는 문제가 발생합니다. 이러한 경우 반드시 Passwordless Sudo가 세팅되어 있어야 하며, 이것이 Passwordless Sudo가 필요한 이유입니다.

◆ AWS 클라우드 환경에서 아마존 리눅스의 경우, root 패스워드가 설정되어 있지 않을 뿐더러 ec2-user 사용자의 패스워드도 세팅되어 있지 않습니다. 이런 경우 Passwordless Sudo를 설정해놓지 않으면 ec2-user에서 sudo를 사용할 수 없습니다.


3. 실습

1) VM마다 devops 사용자 생성
2) devops 사용자가 SSH 키 기반 인증으로 VM끼리 SSH 접속(Passphrase 사용)
3) Passwordless Sudo 설정


Vagrantfile에 블록 처리된 부분을 추가하여 /etc/ssh/sshd_config 파일에서 패스워드 인증을 허용하도록 설정합니다. 이로써 모든 노드에 패스워드 구성이 되었습니다.


1) VM마다 devops 사용자 생성

모든 시스템에 devops 사용자를 생성합니다. debian 계열의 경우 adduser 명령어를 사용합니다. adduser는 사용자 생성, 홈 디렉토리 생성, 패스워드 세팅이 한 번에 이루어집니다.

sudo adduser devops


devops 유저로 전환합니다.

sudo -i -u devops

2) devops 사용자가 SSH 키 기반 인증으로 VM끼리 SSH 접속(Passphrase 사용)

키 페어를 생성합니다. 보안 강화를 위해 passphrase를 세팅합니다.

ssh-keygen


ssh-keyscan으로 control 시스템에서 자기 자신과 각 vm 노드의 퍼블릭 키를 ~/.ssh/known_hosts 파일에 추가합니다.

ssh-keyscan -t rsa 192.168.200.100 >> ~/.ssh/known_hosts ssh-keyscan -t rsa 192.168.200.101 >> ~/.ssh/known_hosts ssh-keyscan -t rsa 192.168.200.102 >> ~/.ssh/known_hosts


ssh-copy-id로 서버의 ~/.ssh/authorized_keys 파일에 클라이언트의 퍼블릭 키를 등록합니다.

ssh-copy-id 192.168.200.100 ssh-copy-id 192.168.200.101 ssh-copy-id 192.168.200.102


ssh 접속시 passphrase를 입력하지 않고 접속이 가능하도록 설정합니다.

ssh-agent bash ssh-add

3) Passwordless Sudo 설정

devops 사용자는 아직 sudo 권한이 없으므로 vagrant 사용자로 전환한 후 작업합니다. (devops 사용자를 나갔기 때문에 devops 사용자로 재접속시 다시 ssh-agent, ssh-add를 실행해주어야 passphrase를 입력하지 않고 ssh 접속을 간편하게 사용할 수 있습니다.)

devops 사용자에게 Passwordless Sudo를 세팅하기 위해 -f 옵션을 사용하여 별도로 /etc/sudoers.d/devops 파일을 생성합니다. 파일명은 어떤 것으로 해도 상관없지만 보통은 해당 계정이나 그룹명으로 지정하는 것이 일반적인 형태입니다. (그냥 sudo visudo 명령어로 /etc/sudoers 파일을 수정해도 됩니다.)

sudo visudo -f /etc/sudoers.d/devops


모든 시스템에 동일한 작업을 해줍니다.

SMALL