11 Model bezpieczeństwa SQL


#241
Rozdział 11.
Model bezpieczeństwa SQL

SQL używa warstwowego modelu bezpieczeństwa, który udostępnia administratorom odpowiednio zróżnicowane poziomy kontroli dostępu do zasobów bazy danych. Na model bezpieczeństwa SQL składają się przywileje (ang. privilages), użytkownicy (ang. users) i zasoby (ang. resources). Użytkownikom nadawane są przywileje pozwalające im wykonywać szereg różnych zadań na zasobach. Przykładowo, użytkownikowi może zostać nadane prawo do operacji SELECT na danej tabeli, ale bez możliwości wykonywania poleceń typu UPDATE, DELETE lub INSERT.
Sprawowanie kontroli nad dostępem do bazy danych wspomagają dwa polecenia: GRANT i REVOKE. Wyrażenie GRANT nadaje przywileje użytkownikom, natomiast REVOKE odbiera je. Zanim zajmiemy się nadawaniem przywilejów, omówimy zagadnienie użytkowników oraz sposób ich tworzenia.

Bezpieczeństwo baz danych

Bezpieczeństwo informacji jest elementem kluczowym w dowolnym środowisku wykorzystywanym przez wielu użytkowników jednocześnie. Gdy tylko istnieje potencjalna możliwość uzyskania dostępu do danych przez niepowołane osoby, należy podjąć wszelkie kroki, aby zapobiec takiej sytuacji. Żadna firma nie zostawia na biurkach poufnych raportów finansowych, kiedy jej pracownicy opuszczają miejsce pracy. Podobnie niezbędne jest zabezpieczenie poufnych informacji w przypadku, gdy są one przechowywane elektronicznie.
Weźmy pod uwagę prawa dostępu do plików. Większość systemów operacyjnych daje użytkownikom możliwość kontrolowania praw dostępu do plików. Dzięki temu inni użytkownicy nie są w stanie zobaczyć lub zmodyfikować oryginalnych plików, o ile ich właściciel nie zezwoli na taką operację. W podobny sposób kontrolowany jest dostęp do obiektów relacyjnej bazy danych, dający jedynie wybranym użytkownikom prawo do
#242
przeglądania lub modyfikowania informacji zapisanych w bazie. Mówiąc najogólniej, zarządzanie dostępem do obiektów bazy danych polega na nadawaniu identyfikatorów użytkownikom bazy i ograniczaniu ich praw dostępu w oparciu o tenże właśnie identyfikator.
Produkty bazodanowe różnią się znacznie pod względem implementacji modelu użytkowników. Wiele z nich posiada swój własny wbudowany system zarządzania użytkownikami. Użytkownicy są tworzeni specjalnie na potrzeby bazy danych i nie mają nic wspólnego z warstwą systemu operacyjnego, w której rezyduje baza danych. Podejście takie stosuje większość popularnych baz danych, w tym Oracle, Sybase i Microsoft SQL Server. Innym rozwiązaniem jest współdzielenie przez bazę danych informacji o użytkowniku z samym systemem operacyjnym.
Bez względu na rzeczywiste rozwiązanie modelu użytkowników, należy zawsze bardzo rozważnie zarządzać modelem bezpieczeństwa bazy danych. Tylko takie podejście gwarantuje zabezpieczenie ważnych informacji przed nieautoryzowanymi użytkownikami.

Konto administratora bazy danych

W chwili tworzenia bazy danych generowane jest jedno konto użytkownika - administratora tej bazy danych. Jeżeli aplikacja bazy danych działa w trybie jednego użytkownika, jest to jedyne konto, jakie może istnieć. Administrator bazy danych, określany na ogół skrótem DBA (ang. DataBase Administrator), posiada prawo do wykonywania wszelkiego rodzaju operacji na bazie danych. Może również tworzyć innych użytkowników i nadawać im przywileje DBA dla tej konkretnej bazy danych.
Użytkownik DBA jest ostatecznym właścicielem wszystkich obiektów bazy danych. Niezależnie od tego, do kogo należy dany obiekt, DBA może dodawać, zmieniać, usuwać rekordy lub nawet całe tabele. Ze względu na ogromne możliwości konta DBA w odniesieniu do bazy danych, należy korzystać z niego tylko w sytuacjach, kiedy jest to absolutnie niezbędne.

Na ogół praktykuje się bezpieczne rozwiązanie polegające na utworzeniu dodatkowych użytkowników dla większości zadań wykonywanych na bazie danych i korzystanie z konta DBA wyłącznie, kiedy jest to konieczne do zadań administracyjnych. Większość baz danych rozróżnia indywidualne prawa posiadane przez konto DBA i pozwala na przypisywanie ich użytkownikom w celu umożliwienia im wykonywania pewnych zadań przypisanych do DBA. Rozwiązanie takie pomaga uniknąć fatalnych w skutkach pomyłek, które łatwiej popełnić, kiedy użytkownik posiada prawo do modyfikowania lub usuwania dowolnych części bazy danych.
Jeżeli więcej niż jedna osoba wymaga przywilejów administratora, wskazane jest utworzenie konta o uprawnieniach DBA dla każdego z nich. W ten sposób każdy użytkownik DBA będzie się logował poprzez swój unikalny identyfikator, co umożliwi śledzenie jego aktywności (rejestrowanej w dziennikach bazy danych).
#243
Właściciele bazy danych

W dalszej części tego rozdziału wyjaśniona zostanie hierarchia obiektów w typowej relacyjnej bazie danych. Na szczycie takiej hierarchii znajduje się baza główna (ang. master database), której właścicielem jest użytkownik DBA. Poniżej występują indywidualne bazy danych będące własnością różnych użytkowników. Właściciel bazy danych (DBO - DataBase Owner) posiada specjalne prawa z nią związane. Niektóre z tych praw mogą być przyznawane innym użytkownikom.
Przykładowo, po utworzeniu bazy danych jedynie jej właściciel ma prawo do tworzenia i usuwania obiektów w jej wnętrzu. Właściciel bazy może przyznać te prawa również innym użytkownikom lub zachować je wyłącznie dla siebie.

Tworzenie użytkowników bazy danych

Model użytkownika bazy danych jest ściśle związany z konkretnym produktem. Niektóre bazy danych oferują wysokiej jakości modele, uwzględniające mechanizmy nadawania przywilejów bazujących na rolach. Inne ograniczają się jedynie do najprostszej funkcjonalności środowiska wieloużytkownikowego lub w ogóle nie zapewniają takich możliwości.
Niniejszy rozdział poświęcony jest bazom implementującym standardowy model bezpieczeństwa SQL. Niektóre bazy danych umożliwiają administratorom dodawanie i usuwanie kont użytkowników przy użyciu interfejsu graficznego, zamiast zwykłych wyrażeń języka SQL. Niestety, tego typu interfejsy administracyjne są specyficzne dla produktu, w którego skład wchodzą. Aby móc skorzystać z informacji zawartych w tym rozdziale, niezbędne jest posiadanie bazy danych umożliwiającej administrowanie użytkownikami przy użyciu języka SQL.
Użytkownicy tworzeni są za pomocą wyrażenia CREATE USER. W najprostszej formie wyrażenie to wywoływane jest z pojedynczym argumentem będącym nazwą użytkownika:

CREATE USER nazwa_uzytkownika

User create.

Na ogół użytkownikom przypisywane są hasła, które mają za zadanie zapobiegać próbom nieautoryzowanego dostępu do danych. Niektóre bazy danych wymagają obowiązkowo, aby nowoutworzonemu użytkownikowi nadane zostało hasło. Sposób nadawania haseł jest cechą specyficzną każdej z baz danych. W przypadku systemów Oracle do określenia hasła dla nowego użytkownika stosowane są słowa kluczowe IDENTIFY BY:

CREATE USER nazwa_uzytkownika IDENTIFY BY hasło

User created.
#244
Szczegółowy opis składni służącej do tworzenia użytkowników oraz wszelkie opcje bezpieczeństwa jej towarzyszące znaleźć można w dokumentacji bazy danych. Większość baz danych oferuje szereg opcji, które mogą zostać ustawione w chwili tworzenia użytkownika. Przykładowo można wskazać, jakie elementy bazy danych tworzone przez użytkownika będą faktycznie zapisywane. Niektóre typy baz danych pozwalają na określenie rozmiaru pamięci, jaki przysługuje użytkownikowi. Szczegółów na ten temat należy szukać w dokumentacji konkretnego produktu.
===================
Rada
W systemie Oracle można przełączyć się na nowego użytkownika przy pomocy wyrażenia CONNECT. Wyrażenie to kończy bieżącą sesję i tworzy nową dla użytkownika podanego jako argument. Na przykład, jeśli jesteśmy zalogowani jako użytkownik system i utworzymy nowe konto o nazwie użytkownik, możemy przełączyć się na nie używając następującego polecenia:

CONNECT użytkownik
=====================

Modyfikowanie użytkowników

Użytkownicy, tak jak dowolne inne elementy bazy danych tworzone przy użyciu wyrażenia CREATE, mogą być modyfikowani wyrażeniem ALTER. Polecenie ALTER USER jest w stanie zmienić wszelkie atrybuty użytkownika, które ustawiane są w wyrażeniu CREATE USER. Na przykład w bazie Oracle wyrażenie ALTER USER może posłużyć do zmiany hasła użytkownika:

ALTER USER użytkownik IDENTIFY BY hasło

User altered.


Usuwanie użytkowników

Do usuwania użytkowników z bazy danych służy polecenie DROP USER. Na ogół, polecenie to może być wykonywane jedynie przez użytkowników typu DBA. Inni użytkownicy mogą również usuwać użytkowników po nadaniu im odpowiedniego uprawnienia przez DBA. Użytkownik usuwany jest z bazy danych następującym poleceniem SQL:

DROP USER użytkownik


Elementy bazy danych

Ze względów bezpieczeństwa bazy danych istnieje pewna hierarchia elementów, z których każdy posiada własne ustawienia. Elementy te rozciągają się od najwyższego poziomu bazy danych do najniższego poziomu kolumny. Prawdopodobnie najlepiej można to sobie wyobrazić jako grupę zagnieżdżających się okręgów - rysunek 11.1.
#245
{{Główna baza danych[[Baza danych (Tabela {Kolumna} {Widok [Kolumna widoku]})]]}}
W {{..}} mieści się [[..]] w którym mieści się {1...} i (2...},a w 2. mieści się [..]

Rysunek 11.1.

Elementy w modelu bezpieczeństwa SQL.

Prześledźmy ten model poruszając się od okręgu najbardziej zewnętrznego w głąb. W większości przypadków element obejmujący sobą pozostałe jest główną bazą danych. Główna baza danych jest własnością menadżera systemu (często nazywanego są lub system) i przechowuje wszystkie informacje związane z bazą danych znajdującą się w jej wnętrzu, łącznie z tabelami zawierającymi dane dotyczące użytkowników oraz definicje innych tabel i elementów przechowywanych w bazie danych.

Bazy danych

Poniżej bazy głównej znajdują się różne bazy indywidualne. Bazy danych są często przypisywane każdemu użytkownikowi lub powstają specjalnie dla określonej aplikacji lub projektu. Podczas programowania można być niemal pewnym, że nasze dane zapisywane są w jednej z podbaz bazy głównej. Na przykład tabele przechowujące informacje związane z filmami, do których odwoływaliśmy się w kolejnych rozdziałach książki, byłyby prawdopodobnie zapisane w bazie o nazwie moviedb lub innej podobnej. Wszystkie tego typu podbazy pracują w kontekście konkretnego egzemplarza bazy głównej. Nie są one oddzielnymi procesami i zazwyczaj wszystkie wykorzystują miejsce przydzielone bazie głównej. Podbazy umożliwiają po prostu wprowadzanie odrębnych praw własności oraz przestrzeni nazw dla użytkowników. Oznacza to, że można stworzyć dwie bazy danych o przykładowych nazwach development i moviedb, a następnie umieścić w nich takie same tabele bez obawy powstania kolizji nazw.
Wyboru bazy danych, do której chcemy wysyłać zapytania, można dokonać przy użyciu polecenia use. Przykładowo, jeżeli do tej pory pracowaliśmy z bazą danych development, a teraz chcemy wysłać kilka zapytań do bazy moviedb, powinniśmy wcześniej wykonać następujące polecenie SQL:

use moviedb
#246
Od tego momentu, dopóki nie zostanie wykonane kolejne polecenie use wszystkie uruchamiane zapytania będą kierowane do tej właśnie bazy danych.
Tabele należące do innej bazy danych mogą być wskazywane w zapytaniu przy użyciu tej samej notacji kropkowej, jaka stosowana jest do wskazywania kolumn określonej tabeli. Jawne specyfikowanie nazw baz danych w zapytaniach może mieć miejsce w dowolnej chwili - wymagane jest ono jedynie w przypadku, gdy chcemy odwołać się do tabeli z bazy danych innej niż bieżąca. Dla przykładu, jeżeli po wydaniu polecenia use moviedb chcielibyśmy wybrać listę filmów z tabeli Movies w bazie danych development, należałoby się posłużyć zapytaniem z listingu 11.1, aby wykonać to zadanie bez konieczności ponownego przełączania się na bazę development.

--------------------------------------
Listing 11.1. Zapytanie wydobywające dane z bazy danych innej niż bieżąca

SELECT studio_name
FROM development .Studios

STUDIO_NAME
--------------------------------------
Giant
MPM
FKG
Delighted Artists
Metaversal Studios
--------------------------------------

Nic nie stoi na przeszkodzie, aby połączyć odwołania do różnych baz danych w pojedynczym zapytaniu. Tabele z różnych baz danych mogą być łączone w pojedynczym zapytaniu przez umieszczenie ich w klauzuli FROM. Inna metoda polega na umieszczeniu odwołania do tabeli z nieaktywnej bazy danych w podzapytaniu, a odwołania do tabeli bieżącej bazy danych w zapytaniu zewnętrznym. Jedyne ograniczenia nakładane na taki sposób łączenia tabel wynikają z użycia wyrażeń GRANT i REVOKE. Przykład zapytania używającego tabel z różnych baz danych znajduje się w listingu 11.2. Jest to zapytanie porównujące tabele Movies z baz danych moviedb i development.

--------------------------------------
Listing 11.2. Zapytanie wydobywające dane z różnych baz danych

SELECT moviedb.Movies.movie_id, development.Movies.movie_title
FROM development.Movies, moviedb.Movies
WHERE development.Movies.movie_id = moviedb.Movies.movie_id

MOVIE_ID MOVIE_TITLE
--------------------------------------
1 Vegetable House
2 Prince Kong
3 The Code Warrior
4 Bili Durham
5 Codependence Day
6 The Linux Files
7 SQL Strikes Back
8 The Programmer
9 Hard Code
10 The Rear Windows
16 SQL Planet

MOVIE_ID MOVIE_TITLE
--------------------------------------
17 The Maltese Tupie 12 rows selected.
--------------------------------------
#247
Tabele

Kolejny poziom w dół modelu bezpieczeństwa zawiera tabele bazy danych. Jak wiadomo, każda tabela istnieje wewnątrz określonej bazy danych. Tabele o tych samych nazwach w różnych bazach niekoniecznie muszą mieć ze sobą cokolwiek wspólnego. Dla przykładu tabela o nazwie People w bazie danych magazines może nie mieć nic wspólnego z tabelą People w bazie danych moviedb.
Ogólnie rzecz biorąc, tabele są własnością użytkownika, który je stworzył i to on kontroluje ustawienia związane z ich bezpieczeństwem. Ustawienia bezpieczeństwa mogą być również wyspecyfikowane dla kolumn tabel lub widoków bazujących na tabelach, tworząc w ten sposób dostatecznie szczegółowy poziom dostępu do danych w bazie. Ponieważ ustawienia bezpieczeństwa dla poziomu tabel są najczęściej modyfikowane, do tematu tego powrócimy przy okazji omawiania faktycznych elementów bezpieczeństwa podlegających zmianom.

Widoki

Stosowanie widoków oraz mechanizmów kontroli dostępu, wbudowanych w większość baz danych, pozwala na ograniczenie praw dostępu użytkownika do danych w taki sposób, aby mógł on widzieć wyłącznie zakres informacji ustalony z góry przez administratora.
Załóżmy dla przykładu, że niezbędne jest, aby pewna grupa użytkowników mogła widzieć ludzi pochodzących z Teksasu, ale nie z innych stanów. W tym celu można stworzyć widok podobny do przedstawionego w listingu 11.3.

--------------------------------------
Listing 11.3. Prosty przykład widoku

CREATE VIEW People_From_Texas
AS
SELECT *
FROM People
WHERE person_state = 'TX'
--------------------------------------

Następnie wspomnianej grupie użytkowników należy zablokować dostęp do tabeli People i jednocześnie udostępnić widok People_From_Texas. W podobny sposób można ograniczać dostęp do kolumn. Pewnej grupie pracowników można na przykład zezwolić na przeglądanie wszelkich informacji z wyłączeniem danych finansowych dotyczących filmów. W tym celu niezbędny byłby widok w postaci:

CREATE VIEW Movie_Info
AS SELECT movie_id, movie_title, director_id, studio_id
FROM Movies

Utworzony widok należy udostępnić wybranej grupie użytkowników zamiast tabeli bazowej Movies. Wykorzystywane w ten sposób widoki są doskonałym środkiem pozwalającym zarządzać dostępem do określonego zbioru danych.
#248
Kolumny oraz kolumny widoku

Jak wynika z powyższych rozważań, możemy zarządzać zakresem informacji dostępnych dla użytkowników poprzez udostępnianie im widoków zawierających wybrane podzbiory danych, zamiast rzeczywistych tabel stanowiących podstawę tych widoków. Użytkownicy mogą także otrzymać prawo uaktualniania, pozwalające im wprowadzać zmiany do wszystkich kolumn widoku lub tabeli. Niemniej jednak, w pewnych przypadkach konieczne jest ograniczenie takiego prawa jedynie do pewnego podzbioru kolumn. Na przykład, jeśli używamy widoku w celu ograniczenia dostępu do tabeli, widok ten prawdopodobnie zawiera klucz główny tabeli. Niezbędne może okazać się zablokowanie użytkownikom prawa do wprowadzania zmian w tej konkretnej kolumnie. Jest to możliwe, ponieważ SQL udostępnia mechanizm blokowania działający na kolumnach, podobnie jak na tabelach i widokach.

Polecenia GRANT i REVOKE

Polecenia GRANT i REVOKE służą do nadawania lub odbierania określonych przywilejów dla zasobów. Podstawowa składnia polecenia GRANT wygląda następująco:

GRANT przywilej ON obiekt TO użytkownik

Podobnie wygląda składnia polecenia REVOKE:

REVOKE przywilej ON obiekt FROM użytkownik

Załóżmy dla przykładu, że użytkownik development jest właścicielem całej bazy danych filmów i istnieje jeszcze jeden użytkownik o nazwie patrycja. Aby umożliwić użytkownikowi patrycja wydobywanie rekordów z tabeli Movies development, właściciel powinien wykonać następujące polecenie:

GRANT SELECT ON Movies TO patrycja

Istnieje specyficzny zbiór przywilejów, jakie mogą być nadawane lub odbierane zasobom znajdującym się w bazie danych. Zbiór ten jest różny dla różnych baz danych, niemniej jednak istnieją pewne podstawowe elementy wspólne, które spotkać można we wszystkich produktach. Tabela 11.1 przedstawia przywileje dla tabel, widoków i kolumn dostępne w systemie Oracle 8.
O ile wcześniej patrycja nie miała dostępu do tej tabeli, teraz może wykonywać na niej wyrażenia SELECT, w wyniku których otrzymywać będzie konkretne dane. Jeżeli administrator bazy danych zmieni zdanie, może cofnąć dostęp Patrycji do tabeli Movies wykorzystując do tego celu polecenie REVOKE:

REVOKE SELECT ON Movies FROM patrycja

Używając słowa kluczowego ALL można nadać lub odebrać wszelkie uprawnienia dotyczące danego obiektu bazy danych.
#249
Tabela 11.1. Przywileje w bazie danych Oracle

Wyrażenia(Wyłącznie Tabele) Przywileje
ALTER Użytkownik może wydawać polecenia ALTER dla tabeli
REFERENCES Użytkownik może tworzyć klucze obce odwołujące się do kolumn wewnątrz tabeli
INDEX Użytkownik może zakładać indeksy na kolumnach tabeli
ALL Użytkownik może wykonywać wszystkie trzy wymienione wyżej funkcje
SELECT Użytkownik może wykonywać polecenia SELECT w odniesieniu do tabeli
INSERT Użytkownik może wstawiać rekordy do tabeli
UPDATE Użytkownik może modyfikować rekordy tabeli
DELETE Użytkownik może usuwać rekordy z tabeli

Na przykład, jeżeli administrator zechce wyposażyć Patrycję w pełne prawa dostępu do tabeli Movies użyje polecenia:

GRANT ALL ON Movies TO patrycja

Cofnięcie z powrotem wszystkich przywilejów nastąpi po wykonaniu polecenia:

REVOKE ALL ON Movies FROM patrycja

======================
Rada
Zanim użytkownik będzie mógł się zalogować i uzyskać dostęp do tabel w bazie Oracle, musi mu zostać nadany przywilej CREATE SESSION. Przywilej ten umożliwia użytkownikom tworzenie nowej sesji pracy z bazą danych lub, mówiąc inaczej, łączenie się z bazą danych. Nadanie tego przywileju umożliwia polecenie GRANT postaci:

GRANT CREATE SESSION TO user
=======================

Polecenia GRANT i REVOKE mogą zawierać listę obiektów, w odniesieniu do których ma być podjęta odpowiednia akcja. Załóżmy na przykład, że istnieje jeszcze jeden użytkownik o nazwie Katarzyna, któremu administrator chce zabronić dostępu do wszelkich danych w bazie. Zmiany w uprawnieniach administrator może wykonać jednocześnie dla obu pań Katarzyny i Patrycji:

REVOKE ALL ON Movies FROM patrycja, katarzyna
GRANT UPDATE ON Movies, Studios TO patrycja, katarzyna

Na podstawie powyższego przykładu można zauważyć, iż wyrażenia GRANT i REVOKE umożliwiają stosowanie list w celu jednoczesnej zmiany przywilejów dla wielu użytkowników lub dla wielu obiektów.

Użytkownik publiczny

Oprócz ustawiania uprawnień dla indywidualnych użytkowników, niektóre bazy danych umożliwiają również jednoczesne dostosowywanie uprawnień dla wszystkich
#250
użytkowników. W Oracle istnieje użytkownik public będący swego rodzaju przekierowaniem na wszystkich użytkowników, którzy nie posiadają specyficznych przywilejów dla obiektu bazy.
Przykładowo, nieco wcześniej użytkownikom katarzyna i patrycja nadane zostały specyficzne przywileje dla tabeli Movies. Nikomu natomiast nie zostały nadane jakiekolwiek prawa związane z tabelą studios. Nadanie lub odebranie wszelkich praw dostępu do tej tabeli wszystkim użytkownikom jest równoważne z nadaniem ich lub odebraniem użytkownikowi public:

GRANT ALL ON Studios TO public

Powyższe polecenie umożliwia każdemu użytkownikowi, który może się zalogować do bazy danych wprowadzanie dowolnych zmian w zawartości tabeli studios. Administrator nie musi, oczywiście, nadawać od razu wszelkich praw, a ograniczyć się jedynie do nadania tych, które jego zdaniem są faktycznie niezbędne wszystkim użytkownikom:

REVOKE ALL ON Studios FROM public
GRANT SELECT ON Studios TO public

Dostosowując uprawnienia użytkownika public unika się konieczności tworzenia tych samych ustawień dla każdego indywidualnego użytkownika bazy danych.

Nadawanie użytkownikom uprawnienia GRANT

Domyślnie każdy użytkownik, po otrzymaniu uprawnień do pewnych obiektów bazy danych, nie może sam nadawać tych praw komuś innemu. Sytuację tę można jednak zmienić przy użyciu klauzuli WITH GRANT OPTION, która umożliwia użytkownikowi nadawanie posiadanych przez niego praw dostępu innym użytkownikom. Dla przykładu, jeżeli użytkownikowi patrycja nadane zostanie prawo wyboru (SELECT) danych z tabeli Movies, będzie ona mogła przeglądać wszelkie rekordy w tej tabeli, ale nie będzie mogła umożliwić komukolwiek innemu wykonywanie tej samej operacji. Jeśli wspomniany przywilej zostanie nadany jej z klauzulą WITH GRANT OPTION, wtedy będzie ona mogła udzielać prawa SELECT dla Movies innym użytkownikom.
Składnia polecenia GRANT z użyciem klauzuli WITH GRANT OPTION wygląda następująco:

GRANT SELECT ON Movies TO patrycja WITH GRANT OPTION

Po wykonaniu powyższego polecenia Patrycja otrzymuje prawo SELECT dla tabeli Movies, które może przyznawać również innym użytkownikom.
Po zalogowaniu mogłaby ona wpisać następujące polecenie, które umożliwiłoby użytkownikom paweł i piotr pobieranie danych z tabeli Movies:

CONNECT patrycja
Connected.

GRANT SELECT ON Movies TO piotr, paweł
#251
Warto zauważyć, że w poleceniu dającym Piotrowi i Pawłowi dostęp do tabeli Movies Patrycja nie użyła klauzuli WITH GRANT OPTION, zatem żaden z nich nie może przyznawać tego przywileju innym użytkownikom. Próba przyznania przywileju SELECT przez Piotra innemu użytkownikowi zakończy się niepowodzeniem:

CONNECT piotr
Connected.

GRANT SELECT ON Movies TO tomek

Gdyby Patrycja dodała klauzulę WITH GRANT OPTION podczas udzielenia praw dostępu do tabeli Movies, Piotr i Paweł staliby się kolejnymi użytkownikami zdolnymi do powiększania listy osób uprawnionych do korzystania z tabeli Movies.

====================
Rada
Klauzulę WITH GRANT OPTION należy stosować z wielką ostrożnością. Użytkownik po otrzymaniu takiego prawa jest w stanie nadać je innym użytkownikom, czego efektem może okazać się bardzo szybka utrata kontroli nad listą osób uprawnionych do korzystania z określonych danych. Opcję GRANT można przekazywać jedynie użytkownikom zaufanym, co do których mamy pewność, że będą korzystać z niej bardzo rozsądnie.
======================

Kolejność poleceń GRANT i REVOKE

Porządek wykonywania poleceń GRANT i REVOKE jest bardzo istotny. Obowiązujący stan uprawnień użytkownika zależy od ostatnio nadanych lub odebranych mu uprawnień.
W wyniku wykonania dwóch poniższych poleceń Patrycja traci prawo do wykonywania poleceń SELECT na tabeli People:

GRANT SELECT ON People TO patrycja
REVOKE ALL ON People FROM patrycja

Mimo, że SELECT jest przywilejem bardziej szczegółowym w porównaniu do ALL, usunięcie wszystkich przywilejów do tabeli People użytkownikowi patrycja cofa również prawo do wybierania z niej wierszy. Fakt, iż użytkownikowi jawnie przyznano dany przywilej, nie ma tutaj żadnego znaczenia.

Role a bezpieczeństwo bazy danych

Niektóre bazy danych umożliwiają administratorom tworzenie warstwy abstrakcji pomiędzy obiektami bazy a użytkownikami poprzez tzw. role. Mówiąc najprościej, role są pewnymi pakietami ustawień bezpieczeństwa. Rolom można przypisywać dowolną liczbę uprawnień, które obowiązywać będą każdego przypisanego do niej użytkownika. Tworząc nowego użytkownika można od razu przypisać go do konkretnej roli, zamiast nadawać mu kolejno wszystkie indywidualne uprawnienia, jakich będzie potrzebował w swojej pracy. Jeżeli zajdzie potrzeba zmiany uprawnień wszystkich członków przypisanych do roli, wystarczy dokonać centralnej modyfikacji w samej roli, a uprawnienia przypisanych jej użytkowników zostaną automatycznie uaktualnione.
#252
Tworzenie i usuwanie ról

Role pod pewnymi względami są bardzo podobne do użytkowników. Są one tworzone przy użyciu wyrażenia CREATE ROLE, a następnie wzbogacane lub pozbawiane pewnych przywilejów poprzez polecenia GRANT i REVOKE. Składnia polecenia CREATE ROLE wygląda następująco:

CREATE ROLE accounting

Po utworzeniu roli można przypisywać jej różne przywileje w taki sam sposób, jaki obowiązuje dla użytkowników:

GRANT UPDATE (budget, gross) ON Movies TO accounting
GRANT SELECT ON Movies TO accounting

Do usuwania istniejących ról służy polecenie DROP ROLE:

DROP ROLE accounting


Przypisywanie użytkowników do ról

Po utworzeniu roli i nadaniu jej odpowiednich uprawnień, można rozpocząć przypisywanie do niej użytkowników. Użytkownik jest dodawany do roli poleceniem GRANT lub usuwany z niej poleceniem REVOKE. Składnia wyrażenia przypisującego użytkownika do roli jest taka sama, jak w przypadku nadawania mu przywileju:

GRANT rola TO user

Jeżeli użytkownik paweł, który obecnie nie posiada żadnych uprawnień do tabeli Movies, spróbuje pobrać listę filmów z tej tabeli, otrzyma w odpowiedzi błąd pokazany w listingu 11.4.
(Wyłącznie Tabele)
--------------------------------
Listing 11.4. Wynik 'wykonania zapytania przy braku odpowiednich uprawnień

CONNECT paweł
Connected.

SELECT movie_title
FROM development.Movies
ERROR at line 2:
ORA-00942: table or view does not exist
--------------------------------

Błąd zwrócony przy próbie dostępu do Movies stwierdza, iż tabela ta nie istnieje. Jest to środek bezpieczeństwa stworzony po to, aby zapobiec powstawaniu sytuacji, w których użytkownik jest w stanie odkryć istnienie tabel, do których nie ma odpowiednich uprawnień. Przypisanie roli accounting użytkownikowi paweł, co umożliwi mu wybieranie wierszy z tabeli Movies, odbywa się w następujący sposób:

CONNECT development
Connected.
GRANT accounting TO paweł
Grant succeeded.

Po tej operacji użytkownik paweł może ponownie połączyć się z bazą danych i z powodzeniem wykonywać polecenia SELECT na tabeli Movies - listing 11.5.
#253
--------------------------------
Listing 11.5. Wyrażenie SELECT działające dzięki nadaniu użytkownikowi odpowiednich uprawnień

CONNECT paweł
Connected.

SELECT MOVIE_TITLE
FROM development.Movies

MOVIE_TITLE
-------------------
Vegetable House
Prince Kong
The Code Warrior
Bili Durhara
Codependence Day
The Linux Files
SQL Strlkes Back
The Programmer
Hard Code
The Rear Windows
SQL Planet
The Maltese Tupie

12 rows selected.
--------------------------------

Użytkownicy, którym przypisana została rola accounting mogą uaktualniać wyłącznie kolumny budget i gross tabeli Movies. Mając to na uwadze, przyjrzyjmy się trzem kolejnym wyrażeniom SQL przedstawionym w listingu 11.6.

--------------------------------
Listing 11.6. Wyrażenia uaktualniające tabelę do której użytkownik ma ograniczony dostęp

CONNECT paweł
Connected.

UPDATE development.Movies
SET movie_title = 'Walks Like a Duck'
WHERE movie_id = 17

UPDATE development.Movies

ERROR at line 1:
ORA-01031: insufficient privileges

UPDATE development.Movies
SET budget = 20
WHERE movie_id = 17

1 row updated.

UPDATE development .Movies SET budget = 20, movie_title = 'Walks Like a Duck'
WHERE movie_id = 17

UPDATE development.Movies

ERROR at line 1:
ORA-01031: insufficient privileges
--------------------------------

Pierwsze zapytanie w listingu 11.6 kończy się błędem, ponieważ Paweł nie otrzymał prawa do polecenia UPDATE na kolumnie movie_title tabeli Movies. W drugim przypadku Paweł posiada prawo do modyfikowania kolumny budget (wynikające z przynależności do roli accounting), więc zapytanie wykonuje się poprawnie.
#254
Trzecie zapytanie ponownie generuje błąd. Mimo że Paweł może wprowadzać zmiany do kolumny budget, wykonanie tego polecenia wymaga posiadania przez niego uprawnień do wszystkich kolumn wymienionych w klauzuli SET.
Przypisując rolę użytkownikowi można mu jednocześnie przyznać prawo wykonywania takiej operacji w odniesieniu do innych użytkowników. Jest to działanie podobne do opcji WITH GRANT OPTION z tą różnicą, iż odnosi się do ról, a nie do przywilejów. Aby wyposażyć użytkownika w prawo do przypisywania ról innym użytkownikom, należy posłużyć się następującym poleceniem:

GRANT rola TO użytkownik WITH ADMIN OPTION

Przypisywanie ról innym rolom

Role cechują się ciekawą właściwością, polegającą na możliwości wzajemnego przypisywania ich sobie. W wyniku przypisania jednej roli do innej, druga z nich zostaje wzbogacona o wszystkie przywileje pierwszej roli z zachowaniem przywilejów już przez siebie posiadanych. Tak elastyczny mechanizm przypisywania ról i zarządzania nimi pozwala konstruować złożone modele bezpieczeństwa baz danych przy jednoczesnym zachowaniu łatwości zarządzania nimi.
Przyjrzyjmy się dwóm następującym rolom:

CREATE ROLE casting GRANT INSERT ON Cast_Movies TO casting
GRANT SELECT ON Cast_Movies TO casting
GRANT UPDATE ON Cast_Movies TO casting
CREATE ROLE director
GRANT DELETE ON Cast_Movies TO director

W tym przypadku członkowie roli casting posiadają uprawnienia do przeglądania, dodawania lub modyfikowania informacji związanych z obsadą filmów, ale nie mogą usuwać członków obsady z filmu. Członkowie roli director są zdolni jedynie do usuwania członków obsady filmu, ich uprawnienia nie pozwalają im na wprowadzanie jakichkolwiek zmian do obsady. Poniżej przedstawiona została metoda pozwalająca utworzyć rolę łączącą wszystkie przywileje w jedną całość:

CREATE ROLE executive_producer
GRANT casting TO executive_producer
GRANT director TO executive_producer

Nowa rola (executive_producer) - powstała w wyniku połączenia dwóch innych ról - umożliwia wybieranie, wstawianie, uaktualnianie i usuwanie wierszy z tabeli Movie_Cast. Zatem przypisanie tej roli użytkownikowi jest równoznaczne z umożliwieniem mu swobodnego operowania na wyżej wymienionej tabeli, w tym na przykład wstawiania nowych wierszy - listing 11.7.
--------------------------------
Listing 11.7. Członek roli executivejyroducer wstawia rekord do tabeli Cast_Movies

INSERT INTO development. Cast_Movies
VALUES
(1, 5, 'John James', 50000);

1 row created.
--------------------------------
#255
Po wycofaniu przywileju INSEKT z roli casting, użytkownik Paweł utraci możliwość wstawiania rekordów do tabeli Cast_Movies. Sytuację taką demonstruj e listing 11.8.
--------------------------------
Listing 11.8. Wyrażenie zakończone niepowodzeniem ze względu na brak odpowiednich uprawnień użytkownika do tabeli

REVOKE INSEKT ON Cast_Movies FROM casting

Revoke sucoeeded.

CONNECT paweł
Connected.

INSEKT INTO development.Cast_Movies
VALUES
(2, 5, 'John James', 50000);

ERROR at linę 1:
ORA-01031: insufficient privileges
--------------------------------

Jeżeli zmienione zostaną przywileje jednej z ról, wszystkie role, do których została ona przypisana, również zostaną zmienione. Oznacza to, że modyfikacja roli wpływa kaskadowo na użytkowników i role, których przywileje dziedziczą się z roli zmodyfikowanej.

Widoki a bezpieczeństwo bazy danych

Obok zdolności do różnicowania uprawnień użytkowników poprzez ich konta dostępu, najbardziej użyteczną cechą relacyjnych baz danych pod względem bezpieczeństwa są widoki. W tym, a także w poprzednim rozdziale pojawiały się już przykłady demonstrujące sposób ograniczania dostępu do danych poprzez tworzenie widoków pozbawionych pewnych porcji informacji.
Kluczem do pomyślnego stosowania widoków jest dbanie o to, aby wewnątrz widoku znajdowały się wyłącznie odpowiednie dane oraz prawidłowe zarządzanie prawami dostępu użytkowników lub ról korzystających z widoków i tabel, w oparciu o które widoki te są budowane. Ogólnie rzecz biorąc, oznacza to, że użytkownicy lub role nie powinny mieć dostępu do tabel, a wszelkie zapytania powinny być kierowane do widoków.
Kiedy użytkownik chce wysłać zapytanie SQL do tabeli nie będącej jego własnością, musi poprzedzić jej identyfikator nazwą właściciela tabeli. Widoki mogą być tworzone po to, aby wyeliminować taką konieczność we wszystkich zapytaniach. Przykładowy widok z listingu 11.9 umożliwia użytkownikowi (paweł) odwołanie się do tabeli Movies bez konieczności poprzedzania jej za każdym razem nazwą właściciela - development.
=============
Rada
Aby użytkownik systemu Oracle mógł tworzyć tabele, widoki i inne obiekty bazy danych, DBA musi mu nadać rolę resource.
=================
#256
--------------------------------
Listing 11.9. Widok importujący tabelę do przestrzeni nazw innego użytkownika

CONNECT paweł
Connected.

CREATE VIEW Movies
AS
SELECT *
FROM development.Movies

View created.
SELECT movie_id FROM Movies

MOVIE_ID
-----------
1
2
3
4
5
6
7
8
9
10
16

MOVIE_ID
----------
17

12 rows selected.
--------------------------------

W wyniku utworzenia widoku tabeli Movies w prywatnej przestrzeni nazw użytkownika, Paweł może teraz odwoływać się do tabeli development. Movies bez potrzeby podawania przedrostka development.
================
Rada
W bazie danych Oracle istnieje możliwość importowania tabel do własnej przestrzeni nazw z pominięciem widoków, za to z zastosowaniem tzw. synonimów. Synonimy służą do nadawania alternatywnych nazw widokom lub tabelom. Zatem, aby stworzyć synonim Movies dla tabeli development .Movies wystarczy wykonać następujące polecenie:

CREATE SYNONYM Movies FOR development.Movies

Z równą łatwością można utworzyć synonim dla obiektu, który istnieje w naszej własnej przestrzeni nazw. Zakładając, że wygenerowaliśmy wcześniej widok o nazwie Movies, możemy teraz pokusić się o stworzenie dla niego synonimu z krótszą nazwą:

CREATE SYNONYM Mov FOR Movies
=================
#257
Dostosowywanie praw dostępu poprzez widoki

Mechanizm łączenia widoków z przywilejami bazy w celu zarządzania dostępem do danych był omawiany już wcześniej. Teraz przedstawimy przykład pokazujący, jak faktycznie należy skonfigurować bazę danych, aby być pewnym, iż użytkownicy widzą i modyfikują jedynie te dane, do których zostali uprawnieni.
Załóżmy, że stworzyliśmy użytkownika, którego praca wymaga jedynie dostępu do listy filmów na bieżąco pokazujących się w bazie danych. Pod żadnym warunkiem użytkownik ten nie ma prawa wprowadzać jakichkolwiek modyfikacji i nie powinien móc stosować złączeń w celu wydobycia interesujących go danych. W takim przypadku najprostszym rozwiązaniem jest odebranie mu praw dostępu do tabel bazowych, a następnie stworzenie widoku łączącego tabele z niezbędnymi informacjami. Proces ten ilustruje listing 11.10.
--------------------------------
Listing 11.10. Tworzenie widoku dla użytkownika wymagającego pasywnego dostępu do listy filmów

CREATE USER guest
IDENTIFIED BY guest

User created.

REYOKE ALL ON Movies FROM guest

Revoke succeeded.

REYOKE ALL ON People FROM guest

Revoke succeeded.

REYOKE ALL ON Studios FROM guest

Revoke succeeded.
CREATE VIEW Movie_List (title, studio, director_fname,
director_lname, release_date)
AS
SELECT movie_title, studio_name, person_fname, person_lname, release_date FROM Movies, Studios,~People
WHERE director_id - person_id
AND Movies.studio_id - Studios.studio_id

View created.

GRANT SELECT ON Movie_List TO guest

Grant succeeded. GRANT connect TO guest

Grant succeeded.
CONNECT guest/guest
Connected.

SELECT *
FROM development.Movie_List

TITLE STUDIO DIRECTOR_F DIRECTOR_L RELEASE_D
--------------------------------
Vegetable House Giant Jeff Prince 01-JAN-75
Prince Kong MPM Carol Delano 01-MAY-79
The Code Warrior FKG Chunk Peterson 01-SEP-91
Bili Durham Delighted Artists Becky Orvis 15-JUL-88
Codependence Day Giant Jeff Price 01-JUL-97
The Linux Files MPM Chunk Peterson 22-AUG-9.
#258
SQL Strikes Back Delighted Artists Becky Orvis 01-NOV-98
The Programmer Delighted Artists Jeff Price 17-APR-93
Hard Code FKG Carol Delano 18-APR-95
The Rear Windows Giant Jeff Price 11-JUL-87
SQL Planet Giant Becky Orvis 06-JAN-95

TITLE STUDIO DIRECTOR_F DIRECTOR_L RELEASE_D
--------------------------------
The Maltese Tupie MPM Chunk Peterson 08-Aug-91

12 rows selected.

SELECT *
FROM development.Movies

ERROR at linę 1:
ORA-00942: table or view does not exist
--------------------------------

Na początku tworzony jest nowy użytkownik o nazwie i haśle guest. Użytkownikowi temu odbierane są wszystkie prawa do tabel studios, Movies i People. Najprawdopodobniej postępowanie takie jest zbędne, ponieważ utworzony użytkownik domyślnie nie powinien mieć dostępu do wymienionych tabel. Polecenia te pozwalają jednak lepiej zrozumieć cały proces postępowania.
Po zablokowaniu dostępu do tabel, których użytkownik nie powinien widzieć, tworzony jest widok Movie_List łączący Movies, studios i People w celu wyświetlenia określonego zbioru danych. Kolejne polecenie nadaje użytkownikowi guest prawo SELECT do utworzonego przed chwilą widoku. Ponieważ konto guest jest zupełnie nowe (a cały proces odbywa się w systemie Oracle), niezbędne jest także przypisanie mu roli connect, dzięki której użytkownik będzie mógł faktycznie połączyć się z bazą danych.
Po ustawieniu wszystkich niezbędnych przywilejów konta guest, łączymy się przy jego użyciu z bazą danych (CONNECT) i wykonujemy polecenie wyświetlenia zawartości widoku Movie_List, aby przekonać się o jego działaniu. Wykonujemy również ; polecenie pobrania danych z tabeli Movies, aby upewnić się, że operacja taka jest niedostępna.
Widoki mogą również ograniczać zakres wierszy tabeli dostępnych dla użytkownika. Na przykład odpowiednio skonstruowany widok (listing 11.11) może uniemożliwić użytkownikowi guest wybieranie rekordów dotyczących osób pochodzących spoza stanu Teksas.
--------------------------------
Listing 11.11. Widok zawierający jedynie osoby ze stanu Teksas

CREATE VIEW People_From_Texas
AS
SELECT *
FROM People
WHERE person_state - 'TX'

GRANT ALL ON People_From_Texas TO guest
--------------------------------

Prawa do tabeli People zostały już odebrane kontu guest, wystarczy więc stworzyć nowy widok zawierający jedynie osoby z Teksasu i przyznać użytkownikowi guest wszystkie odpowiednie prawa do tego widoku.
#259
Kiedy użytkownik guest wykonuje zapytanie mające wpływ na zawartość widoku People_From_Texas, jedynie wiersze widoczne w tym widoku są faktycznie modyfikowane w tabeli bazowej. Przyjrzymy się zapytaniom z listingu 11.12.
--------------------------------
Listing 11.12. Zapytania wykonywane w odniesieniu do widoku zawierającego klauzulą WHERE

CONNECT guest/guest
Connected.

SELECT person_fname, person_lname, person_state
FROM development. People_From_Texas

PERSON_FNA PERSON_LNA PE
--------------------------------
Brzan Smith TX
Paul Monk TX
Reece Randall TX
Carol Delano TX

INSERT INTO development.People_From_Texas
(person_id, person_fname, person_lname, person_address, person_city,
person_state, person^zip, person_phone, person_ssn)
VALUES
(15, 'Some', 'Person1, 'Address', 'City', 'NY',
'12345', '8185551212', '012345678')

1 row created.

UPDATE development. People_Frora_Texas
SET person_state = 'NC'
WHERE person_state = 'NY'

0 rows created.

DELETE FROM development.People_From_Texas
WHERE person_id - 15

0 rows created.
--------------------------------

Pierwszym wyrażeniem w listingu 11.12 jest SELECT. Wynikiem jego działania są cztery wiersze, ponieważ widok, z którego wybierane są dane zawiera wyłącznie cztery osoby ze stanu Teksas. Następne polecenie wstawia nowy wiersz do widoku, a tym samym do jego tabeli bazowej People. Na podstawie rezultatu można stwierdzić, że jeżeli widok jest modyfikowalny i użytkownik ma prawo wstawiania danych dla tego widoku, to może dodawać rekordy do tabeli bazowej widoku, nawet jeżeli zawarte w nich dane nie spełniaj ą ograniczeń narzuconych przez klauzulę WHERE widoku.
Dalej użytkownik guest próbuje zmienić wszystkich użytkowników z wartością NY w polu stanu na użytkowników ze stanu NC. Polecenie (o czym świadczy wynik) nie dało żadnego efektu, mimo że w tabeli bazowej są przynajmniej dwa wiersze pasujące do warunku w klauzuli WHERE. Zapytanie działa wyłącznie w odniesieniu do wierszy zawartych w widoku, a nie w tabeli bazowej. Podobna zasada obowiązuje dla wyrażenia DELETE - identyfikator umieszczony w klauzuli WHERE nie pasuje do żadnego z wierszy widoku, zatem żaden z nich nie został usunięty.
Warunki tego typu stawiają użytkowników w bardzo specyficznej sytuacji - mogą oni wstawiać nowe wiersze do tabeli bazowej bez możliwości ich usuwania, chyba że jawnie zostaną im nadane odpowiednie prawa.
#260
W praktyce

Ustawienia bezpieczeństwa nie zawsze mają istotne znaczenie w rzeczywistych aplikacjach, ponieważ między użytkownikiem a bazą danych wstępuje jeszcze jedna dodatkowa warstwa w postaci programu klient-serwer lub aplikacji sieci WWW. Większość aplikacji działających poprzez sieć WWW używa pojedynczego konta użytkownika do wykonywania wszystkich operacji na bazie danych, natomiast reguły bezpieczeństwa zaimplementowane są w samej aplikacji. Podobnie rzecz ma się w przypadku wielu aplikacji typu klient-serwer. Zasady zachowania bezpieczeństwa zaszywane są w ich wnętrzu i egzekwowane zanim jeszcze zapytania zostaną zbudowane i wysłane do bazy.
Małe aplikacje często logują się bezpośrednio poprzez konto DBA i wykonują swoje zapytania z przywilejami administratora. W przypadku większych baz danych administrator tworzy specjalne konto aplikacji z pewnymi ograniczeniami w porównaniu do DBA. Aplikacji nie jest potrzebne prawo do tworzenia nowych użytkowników, nadawania im praw lub wykonywania zadań administracyjnych, takich jak tworzenie kopii zapasowej bazy danych lub jej odtwarzanie.
W przypadku, gdy z tych samych danych musi korzystać więcej niż jedna aplikacja lub więcej niż jeden użytkownik logujący się bezpośrednio, zarządzanie przyznanymi im prawami musi odbywać się z zachowaniem szczególnej ostrożności. Rozważmy dla przykładu bazę danych zasobów ludzkich w pewnej korporacji. Jedna z aplikacji może służyć pracownikom do wprowadzania ich czasu pracy. Przywileje przypisane użytkownikowi dla tej aplikacji umożliwiałby mu wprowadzanie godzin pracy dla każdego pracownika. Zatem w samej aplikacji musiałaby zostać zaimplementowane ograniczenia uniemożliwiające pracownikom wprowadzanie, modyfikowanie lub choćby przeglądanie kart czasu pracy innych osób.
Aplikacja wystawiająca czeki wypłaty oraz obsługująca inne zadania księgowe dla każdego pracownika, wymagałaby innego typu użytkownika. Użytkownik ten musiałby posiadać przywileje niezbędne do wydobywania stawki godzinowej, całkowitego wynagrodzenia pracownika, a także innych wartości związanych z tworzeniem listy płac.
Nie byłyby mu prawdopodobnie potrzebne uprawnienia do uaktualniania lub usuwania danych wprowadzonych przez użytkowników, chociaż powinien być zdoby do wprowadzania alternatywnych rekordów, jeżeli konieczne byłoby dokonanie zmian.
Podział praw dostępu do bazy danych pomiędzy użytkowników przypisanych do poszczególnych aplikacji jest podejściem jak najbardziej prawidłowym, gdyż uniemożliwia poszczególnym aplikacjom odwoływanie się do danych, które nie są dla nich przeznaczone oraz zapobiega błędnemu kodowaniu aplikacji, w wyniku którego mógłby zostać stworzony dostęp do nieodpowiednich danych.

Wyszukiwarka

Podobne podstrony:
MS SQL Server 6 5 Bezpieczeństwo w SQL Server
MS SQL Server 6 5 Bezpieczeństwo w SQL Server
1b 2 2 4 11 Lab Konfiguracja aspektów bezpieczeństwa na przełączniku
Sopot stat 11 wyklad 9 Analiza kowariancji i ogolny model liniowy
1 Budowa atomu model Bohra cw 11
Podstawy baz danych sql 19 11
11 Bezpieczna Jazda Oraz Bezpieczeństwo Osobiste 1 32
Protesty przeciw paktowi bezpieczeństwa (21 11 2008)
Podstawy baz danych  12 11 SQL
Iracki rząd zatwierdził pakt bezpieczeństwa (16 11 2008)
11 05 Znaki i sygnaly bezpieczenstwa Hakowi i sygnalisci
Wykład 11 Bezpieczeństwo w zarządzaniu systemami i sieciami
S51 Vacad przeno¶nik 20006 11 28 Model (1)[1] p df
model ekonometryczny 11 zużycie energii (14 stron)
2007 11 Amavis – system zabezpieczenia poczty [Bezpieczenstwo]
2007 11 Amavis – system zabezpieczenia poczty [Bezpieczenstwo]
Model 11

więcej podobnych podstron