infra
Platform

모듈 맵

[Linux] 사용자·그룹 관리와 권한 분리 실무

0 / 20 완료

펼치기

Linux-master · 02 / 20

[Linux] 사용자·그룹 관리와 권한 분리 실무

/etc/passwd, /etc/shadow, /etc/group 구조를 이해하고 useradd/usermod/userdel로 계정을 관리합니다

🚨INCIDENT ALERT
HIGH

신입 개발자에게 서버 접근 권한을 줬더니 실수로 /etc/passwd를 잘못 건드려 다른 계정들의 로그인이 안 되는 사태가 벌어졌습니다. 퇴사한 직원 계정이 6개월째 살아 있었고, 특정 서비스가 root 권한으로 돌아가고 있었습니다. 계정과 권한을 제대로 관리하는 것은 보안의 시작이자 시스템 안정성의 기반입니다.

사용자와 그룹 관리

리눅스는 멀티유저 운영체제입니다. 시스템의 모든 리소스는 사용자와 그룹 단위로 관리되며, 이 정보는 /etc/passwd, /etc/shadow, /etc/group 파일에 저장됩니다. 리눅스마스터 1급 시험에서 계정 관리는 매회 다수 문제가 출제되는 핵심 영역입니다.


이번 챕터에서 배울 것

사용자·그룹 관리는 리눅스 운영 및 관리 영역의 핵심입니다. /etc/passwd와 /etc/shadow 파일 구조, useradd 옵션, su와 sudo의 차이는 시험에 반드시 출제됩니다.

  • 1/etc/passwd 7개 필드 — 각 필드의 의미와 시스템 계정 특성
  • 2/etc/shadow 9개 필드 — 패스워드 해시와 만료 정책
  • 3useradd / usermod / userdel — 계정 생명주기 관리
  • 4groupadd / groupmod / gpasswd — 그룹 생성과 멤버 관리
  • 5su / sudo — 권한 전환 방식의 차이와 보안 고려사항
  • 6PAM — 플러그인 방식의 인증 모듈 구조
실습 환경 준비

사용자 관리 명령어는 대부분 root 권한이 필요합니다. 실습 시 sudo를 활용하거나 root 계정으로 진행하세요.

passwd 파일 구조 확인
cat /etc/passwd | head -5
shadow 파일 확인 (root 필요)
sudo cat /etc/shadow | head -3
현재 사용자 정보 확인
id && groups
💡개념

/etc/passwd와 /etc/shadow 파일 구조

/etc/passwd — 사용자 계정 데이터베이스

사용자명 : 패스워드 : UID : GID : GECOS : 홈디렉토리 : 기본셸
   1         2        3     4      5          6           7

실제 예시:

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
john:x:1001:1001:John Doe,Room 101:/home/john:/bin/bash
필드설명특이값
사용자명로그인 이름 (최대 32자)
패스워드x=shadow 사용, *=비활성화
UID사용자 고유 번호0=root, 1-999=시스템계정, 1000+=일반사용자
GID기본 그룹 번호/etc/group과 연결
GECOS사용자 설명 (풀네임, 전화번호 등)
홈 디렉토리로그인 시 이동할 디렉토리없는 경우 / 또는 /var/empty
기본 셸로그인 셸/sbin/nologin=로그인 비활성화

시스템 계정 vs 일반 계정

로컬 터미널
# 시스템 계정 (UID 0-999): 서비스 실행용
cat /etc/passwd | awk -F: '$3 < 1000 {print $1, $3}'
# root 0
# daemon 1
# bin 2
# nginx 998

# 일반 사용자 계정 (UID 1000+)
cat /etc/passwd | awk -F: '$3 >= 1000 {print $1, $3}'
# john 1001
# jane 1002

/etc/shadow — 패스워드 보안 데이터베이스

사용자명:해시패스워드:최종변경일:최소:최대:경고:비활성:만료:예약
   1         2           3        4    5    6    7     8    9

실제 예시:

root:$6$rounds=5000$salt$hashedpassword...:19450:0:99999:7:::
john:$6$xyz$abc...:19450:7:90:7:30:20000:
locked_user:!$6$abc...:19400:0:99999:7:::
필드설명
해시패스워드$알고리즘$솔트$해시 형태. $6=SHA-512, $5=SHA-256, $1=MD5
최종변경일1970-01-01 기준 일수
최소 사용 기간패스워드 변경 후 최소 유지 일수 (0=제한없음)
최대 사용 기간패스워드 강제 변경 주기 (99999=무제한)
경고 기간만료 전 경고 시작 일수
비활성 기간만료 후 계정 비활성화까지의 유예 기간
계정 만료일절대적인 계정 만료일 (1970-01-01 기준 일수)

💡개념

계정 관리 명령어

useradd — 사용자 계정 생성

로컬 터미널
# 기본 사용법
useradd username

# 주요 옵션
useradd -m -s /bin/bash -u 1500 -g developers -G sudo,docker -c "John Doe" john

# 옵션 설명
# -m : 홈 디렉토리 생성 (/home/john)
# -s : 기본 셸 지정
# -u : UID 직접 지정
# -g : 기본 그룹(primary group) 지정
# -G : 보조 그룹(supplementary groups) 지정 (쉼표 구분)
# -c : GECOS 설명 필드
# -d : 홈 디렉토리 경로 지정 (기본값과 다른 경로 사용 시)
# -e : 계정 만료일 (YYYY-MM-DD)
# -r : 시스템 계정 생성 (UID < 1000, 홈 디렉토리 없음)

# 패스워드 설정 (useradd 후 반드시 실행)
passwd john
# 또는
echo "john:secretpassword" | chpasswd  # 스크립트에서 사용

usermod — 사용자 계정 수정

로컬 터미널
# 셸 변경
usermod -s /bin/zsh john

# 보조 그룹 추가 (-aG: append + Groups)
usermod -aG docker john
# ⚠️ -G만 쓰면 기존 보조 그룹이 모두 교체됨!
usermod -G docker,sudo john  # 기존 그룹 모두 교체

# 계정 잠금/해제
usermod -L john    # Lock (shadow에 ! 추가)
usermod -U john    # Unlock (! 제거)

# 사용자명 변경
usermod -l newname oldname

# 홈 디렉토리 변경 및 이동
usermod -d /new/home -m john  # -m: 파일도 함께 이동

userdel — 사용자 계정 삭제

로컬 터미널
# 계정만 삭제 (홈 디렉토리 유지)
userdel john

# 홈 디렉토리와 메일 스풀까지 삭제
userdel -r john
# 주의: /home/john 디렉토리가 삭제됨

# 삭제된 사용자가 소유한 파일 찾기
find / -nouser -o -nogroup 2>/dev/null

그룹 관리 명령어

로컬 터미널
# 그룹 생성
groupadd developers
groupadd -g 2000 dbteam  # GID 직접 지정

# 그룹에 사용자 추가/삭제
gpasswd -a john developers   # 추가
gpasswd -d john developers   # 삭제

# 그룹 관리자 지정
gpasswd -A john developers

# 그룹 삭제
groupdel developers  # 해당 그룹이 기본 그룹인 사용자 있으면 삭제 불가

# 현재 사용자의 그룹 확인
groups john
# john : john developers sudo docker
id john
# uid=1001(john) gid=1001(john) groups=1001(john),27(sudo),998(docker),2000(developers)

/etc/group 파일 구조

그룹명:패스워드:GID:멤버목록
developers:x:2000:john,jane,bob
sudo:x:27:john

💡개념

su와 sudo — 권한 전환

su (Switch User)

로컬 터미널
# root로 전환 (root 패스워드 필요)
su
su -    # 로그인 셸로 전환 (환경변수, PATH도 root 것으로 교체)

# 특정 사용자로 전환
su john           # john의 환경변수 미적용
su - john         # john으로 완전 전환 (홈 디렉토리, 환경변수 적용)

# 단일 명령어 실행 후 복귀
su -c "cat /etc/shadow" root

sudo (SuperUser Do)

로컬 터미널
# 단일 명령어를 root 권한으로 실행 (자신의 패스워드로 인증)
sudo apt-get update
sudo systemctl restart nginx

# root 셸로 전환
sudo -i   # 로그인 셸 (-i: interactive)
sudo su -

# 다른 사용자로 명령 실행
sudo -u nginx nginx -t

# sudo 가능한 명령어 목록 확인
sudo -l

/etc/sudoers 구조 (visudo로 편집)

로컬 터미널
# visudo 사용 (문법 검사 포함)
visudo

# 주요 설정 예시
# 사용자에게 모든 명령어 허용
john ALL=(ALL:ALL) ALL

# 패스워드 없이 특정 명령어 허용
deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp

# 그룹에 sudo 권한 부여 (%는 그룹 표시)
%developers ALL=(ALL:ALL) ALL

# 특정 명령어만 허용
john ALL=(ALL) /usr/bin/apt-get, /usr/bin/systemctl

su vs sudo 비교

항목susudo
인증대상 사용자 패스워드자신의 패스워드
범위셸 전체 전환명령어 단위
감사 로그기록 약함/var/log/auth.log에 모두 기록
권한 설정불가 (전부 or 없음)세밀한 명령어 단위 제어
보안root 패스워드 공유 위험root 패스워드 불필요

💡개념

PAM (Pluggable Authentication Modules)

PAM이란?

PAM은 인증 메커니즘을 애플리케이션에서 분리하여 모듈로 관리하는 프레임워크입니다. 애플리케이션을 수정하지 않고도 인증 방식을 변경할 수 있습니다.

PAM 설정 파일 구조

로컬 터미널
ls /etc/pam.d/
# login  sudo  sshd  su  passwd  system-auth  ...

설정 파일 형식:

모듈타입   제어플래그   모듈경로   모듈인자
auth       required    pam_unix.so  nullok
account    required    pam_nologin.so

모듈 타입

타입역할
auth사용자 인증 (패스워드 확인)
account계정 유효성 검사 (만료, 잠금 등)
password패스워드 변경 처리
session세션 설정/해제 (홈 디렉토리 마운트 등)

제어 플래그

플래그동작
required실패해도 계속 실행, 최종 결과는 실패
requisite실패 시 즉시 중단하고 실패 반환
sufficient성공 시 이전 required 실패 없으면 즉시 성공
optional결과가 전체 인증에 영향 없음

자주 사용되는 PAM 모듈

로컬 터미널
# /etc/pam.d/system-auth 예시
auth     required    pam_env.so
auth     required    pam_faildelay.so delay=2000000  # 실패 시 2초 지연
auth     sufficient  pam_unix.so nullok
auth     required    pam_deny.so

account  required    pam_unix.so
account  sufficient  pam_localuser.so
account  required    pam_permit.so

password required    pam_pwquality.so try_first_pass  # 패스워드 복잡도 검사
password sufficient  pam_unix.so sha512 shadow nullok

session  required    pam_limits.so   # /etc/security/limits.conf 적용
session  required    pam_unix.so

사용자와 그룹 생성 실습

계정 생명주기 전체 과정을 실습합니다.

로컬 터미널
mkdir -p /tmp/linux-master/part1/user-mgmt && cd /tmp/linux-master/part1/user-mgmt
# 실습용 사용자/그룹 관리 기록 파일
cat > user_plan.txt << 'EOF'
# 생성할 사용자 목록
# username:group:shell:comment
webuser:www-data:/sbin/nologin:Web service account
appuser:appgroup:/bin/bash:Application user
deployer:deployers:/bin/bash:Deployment user
EOF
cat > group_plan.txt << 'EOF'
# 생성할 그룹 목록
appgroup
deployers
developers
EOF

1단계: 사용자 생성 전 현재 상태 확인

로컬 터미널
# 현재 최대 UID 확인
cat /etc/passwd | awk -F: '{print $3}' | sort -n | tail -5
# 1001
# 1002

# 사용 중인 그룹 확인
getent group | grep -v "^[a-z]" | head -5

2단계: 그룹과 사용자 생성

로컬 터미널
# 개발팀 그룹 생성
sudo groupadd -g 2000 devteam

# 사용자 생성 (홈 디렉토리 포함, bash 셸)
sudo useradd -m -s /bin/bash -u 1500 -g devteam -G sudo -c "개발자 김철수" devkim

# 패스워드 설정
sudo passwd devkim
# New password:
# Retype new password:
# passwd: password updated successfully

# 생성 결과 확인
grep devkim /etc/passwd
# devkim:x:1500:2000:개발자 김철수:/home/devkim:/bin/bash

grep devkim /etc/shadow
# devkim:$6$...:19450:0:99999:7:::

ls -la /home/devkim/
# drwx------ 2 devkim devteam 62 Mar 28 .
# -rw-r--r-- 1 devkim devteam 18 .bash_logout
# -rw-r--r-- 1 devkim devteam 141 .bash_profile
# -rw-r--r-- 1 devkim devteam 376 .bashrc

3단계: 계정 수정

로컬 터미널
# docker 그룹에 추가 (기존 그룹 유지)
sudo usermod -aG docker devkim

# 그룹 확인
id devkim
# uid=1500(devkim) gid=2000(devteam) groups=2000(devteam),27(sudo),998(docker)

# 패스워드 만료 정책 설정
sudo chage -M 90 -m 7 -W 14 devkim
# -M 90: 최대 사용 기간 90일
# -m 7: 최소 사용 기간 7일
# -W 14: 만료 14일 전 경고

sudo chage -l devkim
# Last password change          : Mar 28, 2026
# Password expires              : Jun 26, 2026
# Password inactive             : never
# Account expires               : never
# Minimum number of days between password change : 7
# Maximum number of days between password change : 90
# Number of days of warning before password expires : 14

4단계: 계정 잠금과 해제

로컬 터미널
# 계정 잠금
sudo usermod -L devkim
# 또는
sudo passwd -l devkim

# 잠금 상태 확인 (! 확인)
sudo grep devkim /etc/shadow | cut -d: -f2 | cut -c1-2
# !$  ← ! 가 패스워드 앞에 추가됨

# 계정 해제
sudo usermod -U devkim
sudo passwd -u devkim

5단계: 계정 삭제

로컬 터미널
# 홈 디렉토리와 함께 삭제
sudo userdel -r devkim

# 삭제 확인
grep devkim /etc/passwd
# (출력 없음)

ls /home/devkim
# ls: cannot access '/home/devkim': No such file or directory

sudo 권한 설정 실습

visudo를 사용하여 세밀한 sudo 권한을 설정합니다.

로컬 터미널
mkdir -p /tmp/linux-master/part1/user-mgmt && cd /tmp/linux-master/part1/user-mgmt
# 실습용 사용자/그룹 관리 기록 파일
cat > user_plan.txt << 'EOF'
# 생성할 사용자 목록
# username:group:shell:comment
webuser:www-data:/sbin/nologin:Web service account
appuser:appgroup:/bin/bash:Application user
deployer:deployers:/bin/bash:Deployment user
EOF
cat > group_plan.txt << 'EOF'
# 생성할 그룹 목록
appgroup
deployers
developers
EOF

1단계: 현재 sudo 설정 확인

로컬 터미널
sudo cat /etc/sudoers
# Defaults   env_reset
# Defaults   mail_badpass
# Defaults   secure_path="/usr/local/sbin:..."
#
# root    ALL=(ALL:ALL) ALL
# %sudo   ALL=(ALL:ALL) ALL

2단계: 사용자별 sudo 권한 부여

로컬 터미널
# visudo로 안전하게 편집 (문법 오류 방지)
sudo visudo

# 추가할 내용:
# 웹마스터는 nginx 재시작만 가능 (패스워드 없이)
webmaster ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

# 개발자 그룹은 패키지 설치 가능
%devteam ALL=(ALL) /usr/bin/apt-get install *, /usr/bin/yum install *

3단계: /etc/sudoers.d/ 활용

로컬 터미널
# 별도 파일로 관리 (권장 방식)
sudo visudo -f /etc/sudoers.d/devteam

# 파일 내용:
%devteam ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp

# 권한 설정
sudo chmod 440 /etc/sudoers.d/devteam

4단계: sudo 로그 확인

로컬 터미널
# Ubuntu/Debian
sudo grep sudo /var/log/auth.log | tail -5
# Mar 28 10:00:00 server sudo: devkim : TTY=pts/0 ; PWD=/home/devkim ; USER=root ; COMMAND=/usr/bin/apt-get update

# CentOS/RHEL
sudo grep sudo /var/log/secure | tail -5

증상

로컬 터미널
sudo useradd newuser
su - newuser
# su: warning: cannot change directory to /home/newuser: No such file or directory
# 또는
ssh newuser@localhost
# Permission denied, please try again.

원인 1: 홈 디렉토리 미생성

로컬 터미널
# 확인
ls /home/newuser
# ls: cannot access '/home/newuser': No such file or directory

grep newuser /etc/passwd
# newuser:x:1003:1003::/home/newuser:/bin/bash
# 홈 디렉토리 경로는 있지만 실제로 없음

해결:

로컬 터미널
# 홈 디렉토리 생성 및 기본 파일 복사
sudo mkdir /home/newuser
sudo cp -r /etc/skel/. /home/newuser/
sudo chown -R newuser:newuser /home/newuser
sudo chmod 700 /home/newuser

원인 2: 패스워드 미설정

로컬 터미널
# shadow 파일 확인
sudo grep newuser /etc/shadow
# newuser:!!:19450:0:99999:7:::
# !! = 패스워드 미설정 상태

해결:

로컬 터미널
sudo passwd newuser

원인 3: 셸이 /sbin/nologin으로 설정

로컬 터미널
grep newuser /etc/passwd
# newuser:x:1003:1003::/home/newuser:/sbin/nologin

해결:

로컬 터미널
sudo usermod -s /bin/bash newuser

증상

로컬 터미널
sudo usermod -aG docker john
docker ps
# permission denied while trying to connect to the Docker daemon socket

원인

그룹 변경은 현재 로그인 세션에 즉시 반영되지 않습니다. 그룹 정보는 로그인 시 로드됩니다.

확인

로컬 터미널
# 현재 세션의 그룹 (아직 docker 없음)
groups
# john sudo

# 실제 /etc/group 확인 (이미 추가됨)
grep docker /etc/group
# docker:x:998:john

해결

로컬 터미널
# 방법 1: 재로그인 (가장 확실)
exit
# 다시 로그인

# 방법 2: 현재 세션에서 그룹 새로고침
newgrp docker
# 단, 이 방법은 서브셸을 열어 docker 그룹으로 전환

# 방법 3: sudo로 그룹 적용 확인
sudo -u john groups
# john sudo docker  ← 이미 적용됨 (새 프로세스이므로)

💼
실무 맥락
현업 패턴

최소 권한 원칙 적용

실무에서 계정 관리의 핵심은 **최소 권한 원칙(Principle of Least Privilege)**입니다.

로컬 터미널
# 서비스 전용 시스템 계정 생성 (로그인 불가)
sudo useradd -r -s /sbin/nologin -d /var/lib/myapp myapp
# -r: 시스템 계정 (UID < 1000)
# -s /sbin/nologin: 로그인 불가
# 서비스 프로세스 실행에만 사용

# 계정 만료 정책 일괄 설정
for user in $(awk -F: '$3>=1000 {print $1}' /etc/passwd); do
    sudo chage -M 90 -W 14 $user
done

비활성 계정 점검

로컬 터미널
# 90일 이상 로그인 없는 계정 찾기
lastlog | awk '$4 != "**Never" {print}' | awk '{print $1, $4, $5, $6, $7, $8, $9}'

# 패스워드 만료된 계정 확인
sudo passwd -S -a | grep " P " | awk '{print $1}'
# (P: 패스워드 있음, L: 잠금, NP: 패스워드 없음)

감사 추적을 위한 로그 모니터링

로컬 터미널
# 실패한 로그인 시도 확인
sudo grep "Failed password" /var/log/auth.log | tail -10
# Mar 28 09:00:00 server sshd[1234]: Failed password for root from 1.2.3.4 port 22

# sudo 사용 기록 확인
sudo grep "sudo" /var/log/auth.log | grep -v "sudo:" | tail -10

# 계정 생성/삭제 이벤트 확인
sudo grep -E "useradd|userdel|usermod" /var/log/auth.log

지식 확인

퀴즈 — 5문제

Q1

/etc/passwd 파일의 7개 필드를 콜론(:)으로 구분할 때, 4번째 필드가 의미하는 것은?

Q2

/etc/shadow 파일에서 패스워드 필드가 '!'로 시작하는 경우의 의미는?

Q3

useradd 명령어에서 사용자의 기본 그룹을 지정하는 옵션은?

Q4

su 명령과 sudo 명령의 차이를 올바르게 설명한 것은?

Q5

PAM(Pluggable Authentication Modules)의 /etc/pam.d/login 파일에서 'required' 제어 플래그의 동작은?

0 / 5 답변

이것도 배워보세요

linux-master중급 · 60
[Linux] 프로세스 관리와 작업 제어
Linux-master 트랙 계속