Przejdź do treści
Lekcja 78 z 117

Kurs › Moduł 9 › Lekcja 78

Użytkownicy i grupy

⏱ ok. 13 min czytania· moduł 9: Użytkownicy i bezpieczeństwo

Po tej lekcji: kursant zakłada, zmienia i usuwa konta oraz grupy (useradd, usermod, userdel, groupadd, gpasswd), ustawia hasła i ich ważność (passwd, chage) i rozumie, co zapisuje się w /etc/passwd, /etc/shadow, /etc/group, /etc/skel i /etc/login.defs.

Wstęp

Typowy poniedziałek admina. Dwa zdania w mailu, a za nimi: nowe konto, hasło, które trzeba zmienić przy pierwszym logowaniu, dostęp do folderu księgowości, a z drugiej strony konto do zamknięcia tak, żeby nie zostały po nim śmieci ani otwarte drzwi.

Dziś robimy to wszystko z terminala. I zaglądamy do trzech plików, w których Linux trzyma całą kadrę firmy.

Kim jesteś dla systemu

Wyobraź sobie biurowiec. Na portierni nikt nie pamięta Twojego imienia. Ochroniarz patrzy na numer na przepustce. Linux działa tak samo. Dla jądra nie ma „Ani”. Jest UID, czyli User ID, numer użytkownika. Imię jest tylko dla ludzi.

id
id anna
uid=1001(anna) gid=1002(anna) groups=1002(anna)

Trzy rzeczy. uid to numer osoby. gid to grupa podstawowa, czyli dział, do którego przypisano Cię na start. groups to wszystkie grupy, do których należysz. Grupa to taka przepustka do działu: kto ma przepustkę „księgowość”, wejdzie do pokoju księgowości. Pamiętasz klucze do pokojów z lekcji o uprawnieniach? Grupa to pęk kluczy wydawany całemu działowi naraz.

Root ma zawsze UID 0. Konta systemowe, jak www-data czy sshd, mają małe numery. Zwykli ludzie zaczynają od 1000. Skąd system wie, gdzie kończą się maszyny, a zaczynają ludzie? Za chwilę, w regulaminie.

Księga meldunkowa: /etc/passwd

getent passwd anna
anna:x:1001:1002:Anna Nowak:/home/anna:/bin/bash

Siedem pól oddzielonych dwukropkiem. Po kolei: login, x, UID, GID grupy podstawowej, opis (zwykle imię i nazwisko), folder domowy, powłoka na start. To ostatnie pole znasz z lekcji 9.

A czemu w miejscu hasła jest x? Bo kiedyś hasło, a dokładniej jego skrót, leżało właśnie tu. A /etc/passwd musi być czytelny dla wszystkich, bo każdy program, który chce zamienić numer na nazwę, tam zagląda. Hasła na tablicy ogłoszeń na korytarzu. Nawet zaszyfrowane, to zły pomysł. Więc je przeniesiono.

Czemu getent, a nie cat albo grep? Bo getent pyta system tak, jak pyta go każdy program. Dziś to dokładnie to samo co plik. Ale w lekcji 81 podłączymy konta z firmowego katalogu i wtedy grep w pliku nic nie znajdzie, a getent znajdzie. Przyzwyczajaj się od teraz.

Sejf: /etc/shadow

ls -l /etc/passwd /etc/shadow
sudo getent shadow anna
-rw-r--r-- 1 root root   4809 Nov  3 16:35 /etc/passwd
-rw-r----- 1 root shadow 2345 Nov  3 16:35 /etc/shadow
anna:$y$j9T$rQ931MOP5Imq07RPSwzcr.$y5.u...:20760:0:99999:7:::

Księgę meldunkową czyta każdy. Sejf tylko root i grupa shadow. [RHEL] Tam /etc/shadow ma zwykle w ogóle zero uprawnień, ----------, a i tak root go czyta, bo root uprawnień nie pyta.

Pola sejfu: login, skrót hasła, data ostatniej zmiany hasła, minimum dni między zmianami, maksimum, ile dni wcześniej ostrzegać, potem dni łaski po wygaśnięciu, data wygaśnięcia konta i pole zapasowe.

Data zapisana jest dziwnie: 20760. To liczba dni od 1 stycznia 1970. Sprawdźmy:

date -u -d @$((20760*86400)) +%F
2026-11-03

Czyli dziś. Linux liczy czas jak więzień kreski na ścianie, od jednego dnia w 1970 roku.

Skrót hasła zaczyna się od $y$. To znaczy yescrypt, sposób mieszania hasła, którego Ubuntu 24.04 używa domyślnie. [RHEL] Na RHEL 9 zobaczysz zwykle $6$, czyli SHA-512. Ważne, że w sejfie nie ma hasła. Jest jego odcisk. Przy logowaniu system miesza to, co wpisałeś, tak samo i porównuje odciski.

A jeśli zamiast skrótu jest ! albo *? To znaczy: hasłem się na to konto nie wejdzie.

Działy: /etc/group i /etc/gshadow

getent group ksiegowosc
ksiegowosc:x:1001:anna,marek

Nazwa grupy, x, GID i lista członków. Uwaga, pułapka: na tej liście są tylko członkowie dodatkowi. Ania ma grupę podstawową anna i tam jej na liście nie zobaczysz. Ona jest wpisana w czwartym polu /etc/passwd. Jak pracownik, który nie figuruje na liście działu, bo ma etat bezpośrednio w nim.

Jest też /etc/gshadow, sejf grup. Trzyma hasła grup (rzadko używane) i listę administratorów grupy.

Zakładamy konto

sudo groupadd ksiegowosc
sudo useradd -m -s /bin/bash -c "Anna Nowak" anna
sudo passwd anna

-m to „make home”, załóż folder domowy. -s powłoka. -c komentarz, czyli imię i nazwisko. passwd ustawia hasło: wpisujesz je dwa razy i nic nie widać, nawet gwiazdek. To nie zawieszenie, to dyskrecja.

A co, jeśli zapomnisz -m? Na Ubuntu:

sudo useradd test1
getent passwd test1
ls -d /home/test1
test1:x:1004:1004::/home/test1:/bin/sh
ls: cannot access '/home/test1': No such file or directory

Dwie niespodzianki. W księdze adres jest, ale budynku nie postawiono. A powłoka to /bin/sh, czyli dash z lekcji 9. Pracownik dostał klucz do mieszkania, którego nie ma, i tłumacza, który zna tylko łacinę. Domyślne ustawienia useradd pokazuje:

useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/sh
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no

[Ubuntu] Dlatego na Ubuntu wiele osób używa adduser. To gadatliwy pomocnik, który sam zakłada folder, pyta o hasło i imię. Wygodny przy biurku, ale w skryptach lepszy jest useradd z jasnymi flagami.

[RHEL] Na RHEL useradd sam zakłada folder domowy, bo w /etc/login.defs jest CREATE_HOME yes, a domyślną powłoką jest Bash. adduser to tam po prostu inna nazwa na useradd. Dlatego zawsze pisz -m -s /bin/bash. Działa tak samo wszędzie i nie musisz pamiętać, gdzie jesteś.

Wyprawka dla nowego: /etc/skel

Każdy nowy pracownik dostaje na start wyprawkę: smycz, kubek, regulamin. W Linuksie wyprawka leży w /etc/skel, od „skeleton”, szkielet. Wszystko, co tam włożysz, zostanie skopiowane do folderu domowego nowego konta.

echo "Witaj w firmie! Regulamin w /srv/regulamin.txt" | sudo tee /etc/skel/CZYTAJ_MNIE.txt
sudo useradd -m -s /bin/bash marek
ls /home/marek
ls /home/anna
CZYTAJ_MNIE.txt

Marek dostał plik, a folder Ani wygląda na pusty. ls bez -a nie pokazuje plików z kropką, a resztę wyprawki, czyli .bashrc, .profile i .bash_logout, Ania dostała. Pliku z regulaminem nie, bo włożyliśmy go do skel po jej przyjęciu. Wyprawka działa tylko przy zakładaniu konta. Nikt nie dosyła kubków starym pracownikom.

Regulamin: /etc/login.defs

grep -E '^(UID_MIN|UID_MAX|PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE|HOME_MODE|ENCRYPT_METHOD)' /etc/login.defs
HOME_MODE       0750
PASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_WARN_AGE   7
UID_MIN                  1000
UID_MAX                 60000
ENCRYPT_METHOD SHA512

To regulamin kadr. UID_MIN 1000 to odpowiedź na pytanie sprzed chwili: od tego numeru zaczynają się ludzie. HOME_MODE 0750 to uprawnienia nowego folderu domowego, czyli właściciel wszystko, grupa zagląda, reszta świata nic. PASS_MAX_DAYS 99999 to ważność hasła: 99999 dni, czyli około 273 lata. Hasło przeżyje firmę, serwer i prawdopodobnie admina.

Ważne: te ustawienia działają dla nowych kont. Zmiana regulaminu nie zmienia umów już podpisanych. Dla istniejących kont jest chage.

Grupy: dopisywanie i wypisywanie

sudo usermod -aG ksiegowosc anna
id anna
uid=1001(anna) gid=1002(anna) groups=1002(anna),1001(ksiegowosc)

-G to grupy dodatkowe, -a to „append”, dopisz. Te dwie litery zawsze razem. Za chwilę, w typowym błędzie, zobaczysz, co się dzieje bez -a.

Drugie narzędzie to gpasswd, czyli zarządzanie grupą od strony grupy:

sudo gpasswd -a marek ksiegowosc        # dopisz
sudo gpasswd -d marek ksiegowosc        # wypisz
sudo gpasswd -M anna,marek ksiegowosc   # ustaw całą listę naraz
sudo gpasswd -A anna ksiegowosc         # Ania zostaje kierowniczką grupy
Adding user marek to group ksiegowosc
Removing user marek from group ksiegowosc

Kierowniczka grupy, czyli administrator zapisany w /etc/gshadow, może sama dopisywać ludzi do swojej grupy przez gpasswd -a, bez roota. Taka delegacja na poziomie działu.

Uwaga: nowa grupa zaczyna działać po ponownym zalogowaniu. Przepustkę drukuje się przy wejściu do budynku. Jeśli dopisałeś się do grupy, a id bez nazwy użytkownika jej nie pokazuje, wyloguj się i zaloguj. Albo, na szybko, newgrp ksiegowosc, które otwiera nową powłokę z tą grupą.

Hasło z terminem ważności: chage

sudo chage -l anna
Last password change                                    : Nov 03, 2026
Password expires                                        : never
Password inactive                                       : never
Account expires                                         : never
Minimum number of days between password change          : 0
Maximum number of days between password change          : 99999
Number of days of warning before password expires       : 7

chage to „change age”, zmiana wieku hasła. Teraz ustawiamy Ani porządek:

sudo chage -d 0 anna                          # zmiana hasła przy pierwszym logowaniu
sudo chage -M 90 -W 14 -E 2027-03-31 anna     # hasło na 90 dni, ostrzeżenie 14 dni wcześniej, konto do końca marca
sudo chage -l anna
Last password change                                    : password must be changed
Password expires                                        : password must be changed
Password inactive                                       : password must be changed
Account expires                                         : Mar 31, 2027
Minimum number of days between password change          : 0
Maximum number of days between password change          : 90
Number of days of warning before password expires       : 14

-d 0 ustawia datę ostatniej zmiany hasła na dzień zero, czyli 1 stycznia 1970. System patrzy i mówi: to hasło jest starsze niż Twoja babcia, zmień je. Dokładnie tego chcesz przy nowym koncie: Ty znasz hasło startowe tylko przez chwilę.

-E to data wygaśnięcia całego konta. Idealne dla stażystów i umów na czas określony. Konto samo się zamknie, nawet jeśli wszyscy zapomną.

Stan konta w jednej linijce:

sudo passwd -S anna
anna P 1970-01-01 0 90 14 -1

P znaczy, że hasło jest ustawione. L znaczyłoby zablokowane, NP brak hasła. O blokowaniu kont szerzej w lekcji 80.

Usuwamy konto

Marek odchodzi.

sudo userdel -r marek
userdel: marek mail spool (/var/mail/marek) not found

-r usuwa też folder domowy i skrzynkę pocztową. Komunikat o braku skrzynki jest niegroźny, po prostu nie miał lokalnej poczty, jak większość ludzi po 2005 roku.

Ale uwaga. -r sprząta tylko dom. Pliki Marka porozrzucane po innych miejscach zostają. I robią się dziwne:

ls -l /tmp/plik_marka
-rw-r--r-- 1 1003 1003 0 Nov  3 16:25 /tmp/plik_marka

Zamiast nazwy jest numer. Pamiętasz: dla jądra właścicielem zawsze był numer. Nazwę dopisywał ls, zaglądając do księgi meldunkowej. Marka w księdze już nie ma, więc zostaje goły numer. To tak zwane pliki osierocone. A jak za miesiąc założysz nowe konto i dostanie ono ten sam wolny numer? Nowa osoba odziedziczy pliki Marka. Z raportami i zdjęciami z imprezy firmowej włącznie.

Dlatego przed usunięciem konta, albo zaraz po, szukasz sierot:

sudo find / -xdev \( -nouser -o -nogroup \) 2>/dev/null

-xdev nie wchodzi na inne systemy plików, żeby nie przekopywać udziałów sieciowych. W prawdziwej firmie konto byłego pracownika często najpierw się blokuje, a usuwa dopiero po przejrzeniu jego plików. Ale to temat na lekcja 80.

Grupę usuwasz przez groupdel ksiegowosc. Nie da się usunąć grupy, która jest czyjąś grupą podstawową. Najpierw trzeba przenieść ludzi.

Jak to działa pod spodem

Jądro zna tylko liczby. Każdy proces ma przypięty UID i listę GID-ów. Każdy plik na dysku ma w i-węźle numer właściciela i numer grupy. Sprawdzenie uprawnień to porównanie liczb, bez żadnych nazw.

Nazwy dokleja przestrzeń użytkownika. Kiedy ls chce wypisać właściciela, woła funkcję biblioteki C getpwuid(). Biblioteka zagląda do /etc/nsswitch.conf, gdzie jest napisane, skąd brać konta: na razie files, czyli z plików. Tę samą drogę idzie getent. Za trzy lekcje dopiszemy tam drugie źródło.

Logowanie wygląda tak: program logowania, na przykład sshd albo login, sprawdza hasło przez PAM, który porównuje skrót z /etc/shadow. Jeśli się zgadza, program bierze z /etc/passwd UID, GID i folder domowy, z /etc/group dodatkowe grupy, ustawia je swojemu procesowi i zamienia się w Twoją powłokę. Dlatego nowa grupa działa dopiero po ponownym zalogowaniu: lista grup jest przyklejana do procesu przy starcie i dziedziczona przez dzieci.

A useradd i spółka? To nie żadna magia. Dopisują linijki do czterech plików tekstowych, zakładając wcześniej blokadę, żeby dwie osoby nie edytowały księgi naraz. Dlatego nie edytuj tych plików zwykłym edytorem. Jeśli musisz ręcznie, użyj vipw i vigr, które pilnują blokady.

Ściąga flag

KomendaFlagaCo robi
useradd-mzakłada folder domowy z /etc/skel
useradd-s /bin/bashpowłoka na start
useradd-c "Imię Nazwisko"opis konta
useradd-g grupa / -G g1,g2grupa podstawowa / dodatkowe
useradd-u 1500konkretny UID
useradd-e 2027-03-31data wygaśnięcia konta
useradd-Dpokazuje ustawienia domyślne
usermod-aG grupadopisuje do grupy (zawsze z -a!)
usermod-s, -c, -d … -mzmienia powłokę, opis, folder (z przeniesieniem)
userdel-rusuwa konto z folderem domowym
passwd(bez flag) / -Sustawia hasło / pokazuje stan
chage-lpokazuje ważność hasła i konta
chage-d 0wymusza zmianę hasła przy logowaniu
chage-M 90 / -W 14maks. wiek hasła / dni ostrzeżenia
chage-E 2027-03-31data wygaśnięcia konta
groupadd-g 2000nowa grupa, opcjonalnie z GID
groupdelusuwa grupę
gpasswd-a / -d / -M / -Adopisz / wypisz / ustaw listę / admin grupy
id-nGgrupy użytkownika po nazwie
getentpasswd, group, shadowpyta o konta tak jak programy
find-nouser, -nogroupszuka plików osieroconych

⚠ Typowy błąd

Ania jest w grupie sudo, czyli może administrować, i w ksiegowosc. Ktoś chce ją dopisać do jeszcze jednej grupy i pisze bez -a:

sudo usermod -aG sudo anna
id anna
sudo usermod -G ksiegowosc anna
id anna
uid=1001(anna) gid=1002(anna) groups=1002(anna),27(sudo),1001(ksiegowosc)
uid=1001(anna) gid=1002(anna) groups=1002(anna),1001(ksiegowosc)

Grupa sudo zniknęła. Bez żadnego ostrzeżenia. -G bez -a znaczy: „ustaw listę grup dokładnie na tę”, a nie „dopisz”. Jak lista obecności, którą ktoś przepisał od nowa, wpisując tylko siebie.

Najgorsza wersja tej historii: robisz to na sobie, na serwerze, gdzie jesteś jedynym adminem. Odbierasz sobie sudo i nie masz go jak przywrócić. Zostaje konsola awaryjna albo uruchomienie w trybie ratunkowym. Dlatego: usermod -aG, zawsze razem, jak sól i pieprz. A przy zmianach własnych uprawnień miej otwartą drugą sesję z rootem, dopóki nie sprawdzisz, że wszystko działa.

Naprawa: sudo usermod -aG sudo anna z innego konta z uprawnieniami. [RHEL] Tam grupa adminów nazywa się wheel, a nie sudo. Błąd ten sam.

✎ Zadanie

  1. Utwórz grupę projekt i użytkownika tester z folderem domowym i powłoką Bash, z opisem „Konto testowe”. Dopisz go do grupy projekt, nie tracąc jego grupy podstawowej.
  2. Ustaw mu hasło, wymuś zmianę przy pierwszym logowaniu i ustaw wygaśnięcie konta na ostatni dzień przyszłego miesiąca. Pokaż chage -l tester i getent passwd tester.
  3. Jako tester (przez su - tester) utwórz plik w /tmp. Potem usuń konto razem z folderem domowym i znajdź komendą find pliki, które po nim zostały.
Pokaż rozwiązanie
sudo groupadd projekt
sudo useradd -m -s /bin/bash -c "Konto testowe" tester
sudo usermod -aG projekt tester
sudo passwd tester
sudo chage -d 0 tester
sudo chage -E "$(date -d "$(date +%Y-%m-01) +2 month -1 day" +%F)" tester
sudo chage -l tester
getent passwd tester
Account expires                                         : Dec 31, 2026
...
tester:x:1001:1002:Konto testowe:/home/tester:/bin/bash

Ostatni dzień przyszłego miesiąca to „pierwszy dzień tego miesiąca, plus dwa miesiące, minus jeden dzień”. date -d rozumie takie zdania po angielsku. Liczenie, ile dni ma luty, zostawiamy komputerowi.

Teraz logowanie jako tester:

sudo su - tester
You are required to change your password immediately (administrator enforced).
Changing password for tester.
Current password:
New password:
BAD PASSWORD: The password contains the user name in some form

Działa wymuszona zmiana hasła. A przy okazji system odrzucił moje nowe hasło „Testera…”, bo zawierało nazwę użytkownika. Słusznie. Hasło „tester123” na koncie „tester” to jak kod do sejfu wypisany na sejfie.

Po zmianie hasła touch /tmp/slad_testera, wylogowanie i sprzątanie:

sudo userdel -r tester
sudo groupdel projekt
sudo find /tmp -xdev -nouser -ls
  1204535      0 -rw-rw-r--   1 1001     1002            0 Nov  3 16:40 /tmp/slad_testera

Sierota znaleziona, z gołymi numerami zamiast nazw. I jeszcze jedno: zauważ, że w rozwiązaniu napisałem sudo su - tester. To działa, ale pod koniec tej lekcji będziesz wiedział, czemu to trochę jak dojazd do pracy dwoma autobusami, kiedy jeździ tramwaj bezpośredni.

Co dalej

Ania ma konto, ale nie ma władzy. W następnej lekcji sudo i root: jak dać komuś prawo do jednej konkretnej komendy, a nie do całego serwera, czemu visudo ratuje życie i dlaczego sudo su - to sygnał, że ktoś nie oglądał tej lekcji.