Etykiety

linux (14) php (14) Laravel (9) mysql (9) Hardware (8) Windows (6) sieci (5) PowerShell (4) software (4) MariaDB (3) apache (3) html (3) Microsoft (2) bezpieczeństwo LAN (2) cygwin (2) Akcesoria (1) CMS (1) Laptop (1) Open Office (1) drupal 7 (1) gpg (1) hosting (1) jquery (1) sieci LAN (1) xml (1) zabezpieczenie sieci LAN (1)

piątek, 28 sierpnia 2015

Wytwórnia obiektów MySql w php

Wstęp


Jakiś czas temu pisałem o tym, jak w bezpieczny sposób korzystać z bazy danych MySql w skryptach php. Dziś pragnę podzielić się z Wami wiedzą dotyczącą tak zwanych wytwórni obiektów z danych MySql. Temat przeznaczony jest dla czytelników z dobrą znajomością języka php i serwera MySql, którzy pragną korzystać z dobrodziejstw obiektowego podejścia php do zagadnień bazodanowych.

Posłużę się w tym miejscu przykładem kartoteki kontrahentów, w której znajdują się zarówno osoby fizyczne, jak i przedsiębiorstwa oraz skryptem php, którego zadaniem jest wytwarzanie obiektów z danych obecnych w kartotece.

Aby rozpocząć należy utworzyć bazę danych MySql o nazwie kartoteka, a w niej tabelę o nazwie kontrahenci. O tym jak utworzyć bazę danych i prostą tabelę MySql pisałem w artykule PHP a bezpiecznie połączenie z bazą danych MySQL. Jest w nim również mowa o tworzeniu użytkownika MySql i nadawaniu uprawnień dostępowych.

Aby utworzyć naszą przykładową tabelę kontrahenci można posłużyć się poleceniem CREATE TABLE z wiersza poleceń MySQL w następujący sposób:

CREATE TABLE `kontrahenci` (
`id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`imie` varchar(15) DEFAULT NULL,
`nazwisko` varchar(20) DEFAULT NULL,
`adres` varchar(25) NOT NULL,
`nazwa` varchar(20) DEFAULT NULL,
`miasto` varchar(20) NOT NULL,
`kodPocztowy` char(5) NOT NULL,
`typ` enum('O','F') DEFAULT NULL,
`nip` char(13) DEFAULT NULL,
`pesel` char(11) DEFAULT NULL,
`regon` char(14) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Tabelę można oczywiście utworzyć także korzystając z interfejsu phpMyAdmin, bądź innym dowolnym sposobem. Osobiście preferuję pracować z wierszem poleceń MySql.

Utworzona tabela MySql
Utworzona tabela MySql


Po utworzeniu tabeli warto do niej wrzucić kilka przykładowych wierszy, bowiem pusta tabela do niczego się nam nie przyda. Dla celów niniejszego artykułu tabela powinna zawierać wiersze zarówno dotyczące osób fizycznych jak i te dotyczące firm. Pole typ określa rodzaj zawartości danego wiersza danych ('O' = osoba fizyczna, 'F' = firma).

Dodajemy zatem kilka przykładowych wierszy danych do nowo utworzonej tabeli kontrahenci:

MariaDB [kartoteka]> insert into kontrahenci (`imie`,`nazwisko`,`adres`,`miasto`,`kodPocztowy`,`pesel`,`typ`) values('Jan','Kowalski','Plac Wolności 1','Warszawa','00001','01010101010','O');
Query OK, 1 row affected (0.02 sec)

MariaDB [kartoteka]> insert into kontrahenci (`imie`,`nazwisko`,`adres`,`miasto`,`kodPocztowy`,`pesel`,`typ`) values('Janusz','Kowal','Plac Wolności 2','Warszawa','00001','02020202020','O');
Query OK, 1 row affected (0.03 sec)

MariaDB [kartoteka]> insert into kontrahenci (`nazwa`,`adres`,`miasto`,`kodPocztowy`,`nip`,`regon`,`typ`) values('Jakaś Firma','Plac Wolności 3','Warszawa','00002','1231231231231','12121212121212','F');
Query OK, 1 row affected (0.00 sec)

MariaDB [kartoteka]> insert into kontrahenci (`nazwa`,`adres`,`miasto`,`kodPocztowy`,`nip`,`regon`,`typ`) values('Jakaś Inna Firma','Plac Wolności 4','Warszawa','00002','1241241241241','14141414141414','F');
Query OK, 1 row affected (0.02 sec)

Przykładowe dane można oczywiście wprowadzić dowolną metodą, nie koniecznie z wiersza poleceń MySql.

Wprowadzanie przykładowych danych do tabeli MySql
Wprowadzanie przykładowych danych do tabeli MySql z wiersza poleceń
 
Zawartość tabeli MySql po wprowadzeniu przykładowych danych
Zawartość tabeli po wprowadzeniu przykładowych danych

 

Wytwórnia obiektów MySQL w php


Ze strony MySql jest już wszystko gotowe. Przejdźmy teraz do skryptu php, który umożliwia tworzenie obiektów na podstawie danych zawartych w tabeli MySql. Od czego zacząć? Przede wszystkim będzie nam potrzebne połączenie z bazą MySql, oraz kilka prostych klas.

Plik db_ini.php zawiera wartości umożliwiające nawiązanie połączenia z serwerem MySql, takie jak nazwa hosta, nazwa użytkownika i hasło. Należy pamiętać, że nazwa użytkownika i hasło muszą być zgodne z rzeczywiście utworzonym użytkownikiem, a także o nadaniu użytkownikowi odpowiednich uprawnień do bazy danych i tabeli. O tym jak się to robi pisałem w artykule PHP a bezpiecznie połączenie z bazą danych MySQL. Oto zawartość pliku db_ini.php:

<?php
// Dostęp do bazy danych
$host = 'localhost';
$db = 'kartoteka';
$user = 'mike';
$password = 'kot-dachowiec';
?>

Skrypt php zawiera kilka klas, zdefiniowanych w bardzo prosty sposó i kilka linijek prostego kodu, tak aby skupić się na ogólnym jego działaniu i ewentualnym zastosowaniu wytwórni obiektów MySql. Na wszelkie pomysły związane z udoskonaleniami i rozbudową skryptu pozostawiam wolne pole czytelnikom.

Klasy OsobaFizyczna i Firma dziedziczą składowe i przysłaniają metody abstrakcyjnej klasy nadrzędnej Kontrahent. Uzupełniają one klasę Kontrahent ważnymi dla konkretnego celu składowymi i metodami, co oznacza, że klasy OsobaFizyczna i Firma są swojego rodzaju specjalizacjami nadrzędnej klasy Kontrahent. Firma przeważnie posiada nip i regon, podczas gdy dla identyfikacji osoby fizycznej ważny jest identyfikator PESEL. W takich przypadkach nie ma sensu tworzyć jednej rozbudowanej klasy ze wszystkimi możliwymi składowymi dla firm i osób prywatnych, ponieważ dawało by to miejsce pewnej nadmiarowości: powstałe w ten sposób obiekty zawierałyby puste i niewykorzystywane zmienne. Zarówno firma, jak i osoba fizyczna, posiadają pewne wspólne cechy, takie jak adres, kod pocztowy, miasto itp., ale jednocześnie różnią się dodatkowymi informacjami. Warto jest więc w tym przypadku utworzyć jedną abstrakcyjną klasę nadrzędną oraz 2 wyspecjalizowane klasy pochodne.

Klasy OsobaFizyczna i Firma umożliwiają tworzenie egzemplarzy odpowiadających im obiektów i zawierają podstawowe metody umożliwiające pozyskiwanie związanych z utworzonymi obiektami informacji. Konstruktor klasy Kontrahent dostępny jest tylko ze swoich klas pochodnych. Natomiast statyczna metoda getInstance() klasy Kontrahent dostępna jest publicznie. Dla zwiększenia bezpieczeństwa wszystkie składowe klas zdefiniowałem są jako prywatne.

Najistotniejsza dla niniejszego przykładu jest statyczna funkcja getInstance() klasy Kontrahent. Funkcja ta pobiera, za pomocą nawiązanego uprzednio połączenia z MySql z wykorzystaniem klasy PDO, wybrane wiersze danych z tabeli kontrahenci, a w zależności od tego, czy dany wiersz dotyczy osoby fizycznej czy firmy, funkcja tworzy nowy egzemplarz odpowiedniego obiektu. Tego typu rozwiązanie nazywamy wytwórnią obiektową.

Klasa KontrahentInfo zawiera metody umożliwiające wyświetlanie danych dotyczących obiektów klasy Kontrahent i jej podrzędnych klas.

Oto skrypt:

<?php

// Dostęp do bazy danych
include("db_ini.php");

abstract class Kontrahent {
    private $id;
    private $adres;
    private $kodPocztowy;
    private $miasto;

    protected function __construct($id, $adres, $kodPocztowy, $miasto) {
        $this->id = $id;
        $this->adres = $adres;
        $this->kodPocztowy = $kodPocztowy;
        $this->miasto = $miasto;
    }

    public static function getInstance($id, PDO $pdo) {
        $stm = $pdo->prepare("select * from kontrahenci where id=?");
        $stm->execute( array( $id ) );
        $row = $stm->fetch(PDO::FETCH_ASSOC);
      
        if (empty($row)) { return null; }
      
        if ($row['typ'] == "O") {
      
        // Osoba Fizyczna
        $obj = new OsobaFizyczna ($row['id'], $row['adres'], $row['kodPocztowy'], $row['miasto'], $row['imie'], $row['nazwisko'], $row['pesel']);
              
        } elseif ($row['typ'] == "F") {
      
        // Firma
        $obj = new Firma ($row['id'], $row['adres'], $row['kodPocztowy'], $row['miasto'], $row['nazwa'], $row['nip'], $row['regon']);
      
        } else return null;

        return $obj;  
    }
  
    protected function getId() {
        return "ID: {$this->id}";
    }
  
    protected function getInfo() {
        $base = "Adres: {$this->adres}\n".
                "Kod pocztowy: {$this->kodPocztowy}\n".
                "Miasto: {$this->miasto}";
              
        return $base;
    }
}

class OsobaFizyczna extends Kontrahent {
    private $imie;
    private $nazwisko;
    private $pesel;
  
    public function __construct ($id, $adres, $kodPocztowy, $miasto, $imie, $nazwisko, $pesel) {
        parent::__construct($id, $adres, $kodPocztowy, $miasto);
        $this->imie = $imie;
        $this->nazwisko = $nazwisko;
        $this->pesel = $pesel;
    }
  
    public function getInfo() {
        $base = parent::getId()."\n";
        $base.= "Imie: {$this->imie}\n";
        $base.= "Nazwisko: {$this->nazwisko}\n";
        $base.= parent::getInfo()."\n";
        $base.= "PESEL: {$this->pesel}";
        return $base;
    }
}

class Firma extends Kontrahent {
    private $nazwa;
    private $nip;
    private $regon;
  
    public function __construct($id, $adres, $kodPocztowy, $miasto, $nazwa, $nip, $regon) {
        parent::__construct($id, $adres, $kodPocztowy, $miasto);
        $this->nazwa = $nazwa;
        $this->nip = $nip;
        $this->regon = $regon;
    }
  
    public function getInfo() {
        $base = parent::getId()."\n";
        $base.= "Nazwa: {$this->nazwa}\n";
        $base.= parent::getInfo()."\n";
        $base.= "NIP: {$this->nip}\n";
        $base.= "REGON: {$this->regon}";
        return $base;
    }
  
}

class KontrahenciInfo {
        public function showInfo(Kontrahent $kontrahent) {
            print "<pre>{$kontrahent->getInfo()}</pre><br>---------<br>";
        }
}

try {
    // Nawiązanie połączenia z bazą danych MySQL
    $conn = new PDO("mysql:host={$host};dbname={$db}", $user, $password,array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET NAMES utf8",PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
     
    for ($id=1;$id<=4;$id++) {
        $kontrahent = Kontrahent::getInstance($id,$conn);
        $info = new KontrahenciInfo;
        $info->showInfo($kontrahent);
    }
          
}    catch (PDOException $e) {
        // Obsługa wyjątków
        print "Błąd PDO: " . $e->getMessage() . "<br/>";
        die();
}

?>

Jak działa ten skrypt? Na początku skryptu występują definicje niezbędnych do jego działania klas. W następnym etapie nawiązujemy połączenie z bazą danych korzystając z popularnej bazodanowej klasy PDO. Dla celów niniejszego artykułu skrypt wyszukuje konkretne wiersze z tabeli, zdefiniowane pętlą for-next. Po nawiązaniu połączenia z bazą danych wywołujemy – w pętli for-next - zdefiniowaną w klasie Kontrahent statyczną metodę Kontrahent::getInstance(), do której przekazujemy obiekt PDO połączenia z bazą oraz identyfikator wiersza tabeli MySql kontrahenci i która w ten sposób odczytuje wybrane dane z tabeli i tworzy na ich podstawie zróżnicowane obiekty, odpowiednio klas OsobaFizyczna bądź Firma, w zależności od wartości pola typ w napotkanym wierszu MySql. W tej samej pętli tworzony jest także obiekt klasy KontrahenciInfo, a za pomocą metody KontrahenciInfo::ShowInfo() wyświetlane są informacje o każdym utworzonym obiekcie z podrzędnej hierarchii klasy Kontrahent. Nawiązanie połączenia MySql, odczyt wierszy danych z tabeli, tworzenie obiektów z odczytanych danych, a także korzystanie z metody wyświetlającej informacje o utworzonych obiektach, to czynności opatrzone w skrypcie w podstawowy mechanizm przechwytywania wyjątków try-catch.

A oto efekt działania skryptu:

ID: 1
Imie: Jan
Nazwisko: Kowalski
Adres: Plac Wolności 1
Kod pocztowy: 00001
Miasto: Warszawa
PESEL: 01010101010

---------
ID: 2
Imie: Janusz
Nazwisko: Kowal
Adres: Plac Wolności 2
Kod pocztowy: 00001
Miasto: Warszawa
PESEL: 02020202020

---------
ID: 3
Nazwa: Jakaś Firma
Adres: Plac Wolności 3
Kod pocztowy: 00002
Miasto: Warszawa
NIP: 1231231231231
REGON: 12121212121212

---------
ID: 4
Nazwa: Jakaś Inna Firma
Adres: Plac Wolności 4
Kod pocztowy: 00002
Miasto: Warszawa
NIP: 1241241241241
REGON: 14141414141414

---------

poniedziałek, 24 sierpnia 2015

PHP a bezpiecznie połączenie z bazą danych MySQL

Wstęp


W sieci web można dziś łatwo znaleźć obfitą ilość instruktaży dotyczących metod łączenia się z bazą danych MySQL z poziomu przeglądarki internetowej za pomocą języka php. Większość z nich to jednak metody bardzo ogólne i podstawowe, generalnie bazujące na oprogramowaniu strukturalnym, bez odpowiedniego podejścia do kwestii bezpieczeństwa kodu. Tego typu tutoriale są często źródłem złych nawyków programistycznych, które stają się barierą w rozwoju dalszych umiejętności. Ponieważ kod przedstawiony w danym instruktarzu działa, większość początkujących programistów jest przekonana o jego zupełniej prawidłowości i pełnej efektywności. Wiele z przykładów przedstawianych w popularnych instruktażach związanych z tematem, to metody, które w środowisku produkcyjnym raczej by się długoterminowo nie sprawdziły i na pewno w końcu by zawiodły. W niniejszym artykule postaram się przedstawić temat korzystania z bazy danych MySQL za pomocą języka php z perspektywy bezpieczeństwa i efektywności kodu, skupiając się na metodzie OOP (programowanie obiektowe) z zastosowaniem klasy PDO. W celu ułatwienia czytelnikom zrozumienia omawianej tutaj tematyki, przytoczę konkretne i sprawdzone przeze mnie przykłady. Artykuł jest skierowany do czytelników z dobrą znajomością php i przynajmniej podstawową wiedzą dotyczącą MySQL oraz programowania obiektowego.

Klasa PDO


Klasa PDO oferuje programistom php szeroki wachlarz możliwości jeśli chodzi o bazy danych, stanowiąc swego rodzaju abstrakcyjną powłokę dostępu do danych. PDO zapewnia dość wysoki poziom bezpieczeństwa przy minimalnej ilości kodu, a jednocześnie skrypty wykonywane są bardzo szybko. Stosowanie odpowiednich sterowników PDO umożliwia współpracę klasy z rozmaitymi systemami baz danych. Na dzień dzisiejszy wspierane są następujące rozwiązania bazodanowe:

IBM DB2
ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
PostgreSQL
Cubrid
FreeTDS / Microsoft SQL Server / Sybase
Firebird
SQLite 3 and SQLite 2
Microsoft SQL Server / SQL Azure
4D IBM Informix Dynamic Server
MySQL 3.x/4.x/5.x
Oracle Call Interface

PHP PDO
PHP PDO


Niezależnie od stosowanego sterownika bazy danych, w każdym przypadku odczyt i manipulacja danymi odbywają się za pomocą identycznych funkcji tej klasy, co pozwala na szybkie opanowanie dostępnych w klasie narzędzi i stosowanie ich w pracy z różnymi rodzajami baz danych.

PHP a bezpieczne połączenie z bazą danych MySQL


Za pomocą klasy PDO można korzystać z dobrodziejstw MySQL z poziomu przeglądarki internetowej w prosty i bezpieczny sposób. Postaram się wyjaśnić jak to zrobić na podstawie prostego przykładu kartoteki kontrahentów. Aby rozpocząć, należy w dowolny sposób utworzyć bazę danych o nazwie kartoteka oraz prostą tabelę o nazwie kontrahenci. Dla jasności przykładu posłużę się w tym celu klientem MySQL MariaDB w środowisku Scientific Linux 7. Bazę i tabelę można oczywiście utworzyć w dowolny sposób, np. korzystając z interfejsu phpMyAdmin, bądź podobnego oprogramowania.
MariaDB [(none)]> create database kartoteka;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> use kartoteka;
Database changed

MariaDB [kartoteka]> create table kontrahenci (
-> id smallint unsigned not null auto_increment primary key,
-> imie varchar(15) not null,
-> nazwisko varchar(20) not null,
-> adres varchar(25) not null ) engine=InnoDB charset utf8;
Query OK, 0 rows affected (0.06 sec)
Po utworzeniu tabeli o nazwie kontrahenci należy utworzyć użytkownika o przykładowej nazwie mike i nadać mu uprawnienia niezbędne do odczytu i zapisu danych:
MariaDB [kartoteka]> grant usage on *.* to mike@localhost identified by 'kot-dachowiec';
Query OK, 0 rows affected (0.01 sec)

MariaDB [kartoteka]> grant select, insert, update on kartoteka.kontrahenci to mike@localhost;
Query OK, 0 rows affected (0.00 sec)
Warto sprawdzić, czy uprawnienia dla użytkownika mike są odpowiednio ustawione:
MariaDB [kartoteka]> show grants for mike@localhost;
+-------------------------------------------------------------------------------------------------------------+
| Grants for mike@localhost |
+-------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'mike'@'localhost' IDENTIFIED BY PASSWORD '*391D5A941E13141F78608619467FC09552677273' |
| GRANT SELECT, INSERT, UPDATE ON `kartoteka`.`kontrahenci` TO 'mike'@'localhost' |
+-------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
Teraz można przystąpić do sporządzenia formularza html, którego kod, dla prostoty i jasności przykładu, wygląda następująco:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd">
<html>
<h3>Dodawanie kontrahenta do kartoteki</h3>
<form method="post" action="dodaj.php">
Imię: <input type="text" name="imie" size="15" maxlength="15"> <br /><br />
Nazwisko: <input type="text" name="nazwisko" size="20" maxlength="20"> <br /><br />
Adres: <input type="text" name="adres" size="25" maxlength="25"> <br /><br />
<input type="submit" value="Dodaj">
</form>
</html>
Powyższy formularz ma za zadanie przesyłanie wprowadzonych do niego danych metodą POST do skryptu dodaj.php. Kod html formularza zawiera tylko te elementy, które są niezbędne dla zrozumienia przedstawianego tutaj przykładu, nie zawiera natomiast elementów takich jak style css, bądź innych elementów poprawiających wygląd czy funkcjonalność.

W pliku o przykładowej nazwie db_ini.php należy umieścić zmienne umożliwiające dostęp do bazy danych:
<?php
// Dostęp do bazy danych
$host = 'localhost';
$db = 'kartoteka';
$user = 'mike';
$password = 'kot-dachowiec';
?>

A oto kod skryptu dodaj.php:
<?php
// Dostęp do bazy danych
include('db_ini.php');
try
{
// Nawiązanie połączenia z bazą danych MySQL
$conn = new PDO("mysql:host={$host};dbname={$db}", $user, $password,
  array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET NAMES utf8",
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

// Dodawanie nowego wiersza danych
$dodaj = $conn->prepare("insert into kontrahenci (imie, nazwisko, adres) values(:imie,:nazwisko,:adres)");
$dodaj->execute(array(':imie'=>$_POST['imie'],':nazwisko'=>$_POST['nazwisko'],':adres'=>$_POST['adres']));

// Zakończenie połączenia
$conn = null;
}

catch (PDOException $e) {
// Obsługa wyjątków
print "Błąd: " . $e->getMessage() . "<br/>";
die();
}
?>
Skrypt dodaj.php ma za zadanie nie tylko wprowadzenie przesłanych za pomocą formularza html danych do tabeli MySQL, lecz także zapewnienie podstawowego poziomu obsługi wyjątków, którą można w prosty sposób dopasować do warunków typowego środowiska produkcyjnego. Skrypt powoduje dodanie nowego wiersza (rekordu) do tabeli kontrahentów. W przypadku wystąpienia wyjątku zostają wykonane polecenia z sekcji catch, którą można dowolnie rozbudować na miarę własnych potrzeb. Należy zwrócić uwagę na specyficzne atrybuty połączenia $conn. Po pierwsze, ponieważ tabela kontrahentów obsługuje system kodowania znaków utf-8, połączenie zostaje utworzone właśnie z obsługą tego standardu kodowania - MYSQL_ATTR_INIT_COMMAND=>"SET NAMES utf8" - co umożliwia prawidłową obsługę polskich czcionek. Po drugie, ponieważ skrypt dodaj.php ma zapewnić podstawową obsługę wyjątków, połączenie zostaje nawiązane z atrybutem PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION. W przypadku ustawień obsługi wyjątków jak w przykładzie powyższego skryptu dodaj.php, pojawienie się wyjątku nie tylko daje o sobie znać w zdefiniowany przez programistę sposób, czyli w postaci wyświetlonej informacji, ale także rozpoczęta przez skrypt transakcja dodawania wpisu zostaje automatycznie wycofana, co zapewnia dobre zabezpieczenie przed skutkami ewentualnych błędów. Przykładowo, jeśli programista przeliteruje w skrypcie nazwę kolumny 'imie' tabeli 'kontrahenci', to transakcja zostanie wycofana, a jednocześnie wyświetli się następujący komunikat:
Błąd: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'imse' in 'field list'
Przechwytywanie wyjątków daje duże możliwości programistyczne, przy jednoczesnej minimalizacji kodu.

Co bardzo istotne dla każdego świadomego programisty php, wszelkie zapytania przekazywane do MySQL poprzez klasę PDO nie stanowią jakiejkolwiek luki bezpieczeństwa. W celu uzyskania maksymalnego poziomu bezpieczeństwa, PDO umożliwia stosowanie sparametryzowanych zapytań poprzez ich przygotowanie metodą prepare oraz powiązanie z wartościami zmiennych przekazanych w tablicy poprzez metodę execute (jak w niniejszym przykładzie). W celu zachowania wysokiego poziomu bezpieczeństwa zapytań PDO można równie dobrze korzystać z metod ::bindParam lub ::bindValue. Nie ma konieczności korzystania z dodatkowych narzędzi typu mysql_real_escape_string() w przykładowym celu zapobiegania atakom sql injection. Klasa PDO eliminuje potrzebę stosowania typowo proceduralnych zabezpieczeń przed różnego rodzaju atakami związanymi z dostępem do baz danych.

W celu uzupełnienia przykładu bezpiecznego zapisu danych, udostępniam przykład odczytu danych z bazy z wykorzystaniem klasy PDO:
<?php
// Dostęp do bazy danych
include('db_ini.php');
try
{
// Nawiązanie połączenia z bazą danych MySQL
$conn = new PDO("mysql:host={$host};dbname={$db}", $user, $password,
  array(PDO::MYSQL_ATTR_INIT_COMMAND=>"SET NAMES utf8",
  PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

// Odczyt i wyświetlanie wierszy danych
$dane=$conn->prepare("select id, imie, nazwisko, adres from kontrahenci");
$dane->execute();
$result = $dane->fetchAll(PDO::FETCH_ASSOC);

// Zakończenie połączenia
$conn = null;
}

catch (PDOException $e) {
// Obsługa wyjątków
print "Błąd: " . $e->getMessage() . "<br/>";
die();
}

// Wyświetlanie wyników
foreach ($result as $kontrahent)
 print "{$kontrahent['id']} - {$kontrahent['imie']} {$kontrahent['nazwisko']}
 {$kontrahent['adres']} <br /&gt";
?>

środa, 19 sierpnia 2015

Amanda Backup: Amrecover - przywracanie zarchiwizowanych danych

Wstęp


Jakiś czas temu opracowałem bardzo ogólny artykuł dedykowany systemowi archiwizacji danych Amanda, w którym przedstawiłem nie tylko ogólny zarys tego znakomitego i darmowego oprogramowania, lecz także przytoczyłem nieco udokumentowany przykład pewnego sprawdzonego wariantu podstawowej konfiguracji systemu.

Dobrze zaplanowana archiwizacja danych jest bardzo ważna, lecz kluczowe znaczenie ma również umiejętność przywracania zarchiwizowanych po stronie serwera plików. Ponieważ kwestia przywracania plików to, w przypadku systemu Amanda, bardzo obszerny temat, w niniejszym artykule mam zamiar omówić bardzo prosty przykład przywracania zarchiwizowanych danych do archiwizowanego klienta z systemem operacyjnym Linux, za pomocą oprogramowania Amrecover.

Należy pamiętać o tym, iż z oprogramowania Amrecover można korzystać tylko i wyłacznie jako użytkownik root na archiwizowanej maszynie.

Przykładowy scenariusz Amrecover


Serwer archiwizacji - z zainstalowanym i prawidłowo skonfigurowanym, dla celów niniejszego przykładu, oprogramowaniem amanda-server - o nazwie hosta amanda i adresie ip 192.168.0.2. Archiwizowany klient Linux o nazwie hosta bob3 i adresie ip 192.168.0.3, z zainstalowanym i prawidłowo skonfigurowanym, dla celów niniejszego przykładu, oprogramowaniem amanda-client.

Ustawienia wstępne


Aby oprogramowanie Amrecover działało prawidłowo kilka ważnych warunków musi zostać spełnionych.

1. Po stronie serwera archiwizacji danych należy sporządzić odpowiednią zawartość pliku /var/lib/amanda/.amandahosts. Dla niniejszego przykładu plik .amandahosts powinien koniecznie zawierać następującą linię, uprawniającą użytkownika root na maszynie adresie ip 192.168.0.3 do dostępu do systemu indeksacji zarchiwizowanych danych oraz do zarchiwizowanej zawartości:
192.168.0.3 root amindexd amidxtaped

2. Po stronie archiwizowanego klienta plik /etc/amanda/amanda-client.conf powinien zawierać następujące linie:
conf  "TestConfig1" # nazwa konfiguracji zgodnie z konfiguracją serwera
index_server "192.168.0.2" # serwer indeksacji danych
tape_server  "192.168.0.2" # serwer archiwizacji
tapedev "" # urządzenie taśmowe

Amrecover w akcji


Jako użytkownik root, po stronie archiwizowanej maszyny Linux zaprzęgamy do pracy Amrecover.
[root@bob3 tmp_test]# amrecover
AMRECOVER Version 3.3.3. Contacting server on amanda.intranet.bla.pl ...
220 amanda AMANDA index server (3.3.3) ready.
Setting restore date to today (2015-08-19)
200 Working date set to 2015-08-19.
200 Config set to TestConfig1.
501 Host bob3 is not in your disklist.
Use the sethost command to choose a host to recover
Po uruchomieniu oprogramowania Amrecover warto się upewnić, że na serwerze archiwizacji znajdują się zarchiwizowane dane z hosta bob3. Sprawdzamy więc listę zarchiwizowanych maszyn za pomocą polecenia listhost:
amrecover> listhost
200- List hosts for config TestConfig1
201- 192.168.0.3
200  List hosts for config TestConfig1
Ponieważ nasza maszyna znajduje się na liście, możemy śmiało kontynuować.
Za pomocą polecenia sethost wybieramy nazwę hosta, którego zarchiwizowane dane mamy zamiar przywrócić:
amrecover> sethost 192.168.0.3
200 Dump host set to 192.168.0.3.
Została prawidłowo wybrana nazwa hosta, którego dane nas interesują. Teraz, korzystając z polecenia listdisk uzyskujemy listę zarchiwizowanych na serwerze katalogów wybranego hosta bob3:
amrecover> listdisk
200- List of disk for host 192.168.0.3
201- /home/bob/dom/multimedia/Muzyka
200 List of disk for host 192.168.0.3
Ponieważ szybko znajdujemy katalog który nas interesuje, śmiało wybieramy go za pomocą polecenia setdisk:
mrecover> setdisk /home/bob/dom/multimedia/Muzyka
200 Disk set to /home/bob/dom/multimedia/Muzyka.
Po wybraniu interesującego nas dysku wyświetlamy jego zawartość:
amrecover> ls
2015-08-19-14-26-04 "gunnar Qmusic/"
2015-08-19-14-26-04 DreamcatcherQ/
2015-08-19-14-26-04 .
Ponieważ mamy zamiar przywrócić wyłącznie katalog DreamcatcherQ, wybieramy go za pomocą polecenia add:
amrecover> add Dreamcatcher
Added dir /Dreamcatcher/ at date 2015-08-19-14-26-04

Należy pamiętać o tym, że wybrane pliki lub katalogi są przywracane do lokalizacji ścieżki, w której obecnie się znajdujemy!

Przystępujemy do przywracania zarchiwizowanych plików za pomocą polecenia extract.
amrecover> extract

Extracting files using tape drive changer on host amanda.intranet.bla.pl.
The following tapes are needed: TestConfig1-1

Extracting files using tape drive changer on host amanda.intranet.bla.pl.
Load tape TestConfig1-1 now
Continue [?/Y/n/s/d]? y
Restoring files into directory /root/tmp_test
All existing files in /root/tmp_test can be deleted
Continue [?/Y/n]? y

./DreamcatcherQ/
./DreamcatcherQ/ab.ini
./DreamcatcherQ/dreamcatcherQ_wav.wav

amrecover>
Dane zostały skutecznie przywrócone, co w przykładowym przypadku umożliwi dalsze słuchanie ulubionej muzyki!

Amrecover oferuje cały szereg przydatnych w odzyskiwaniu danych poleceń. Aby wyświetlić całą listę poleceń, należy z poziomu wiersza poleceń amrecover wydać polecenie help.

W przypadku uwag bądź pytań proszę o komentarze. Służę pomocą!

czwartek, 13 sierpnia 2015

Amanda - sieciowa archiwizacja danych

Co to jest Amanda


Jednymi z trudniejszych zagadnień, najskuteczniej spędzających sen z powiek wielu administratorów sieci w dużych korporacjach są niewątpliwie procedury archiwizacji danych w rozległych i cross-platformowych sieciach komputerowych. Istnieje bardzo szeroki wachlarz rozwiązań umożliwiających zautomatyzowane, bardziej lub mniej skuteczne, procedury zabezpieczania danych w sieci. Amanda jest jednym z tych rozwiązań, które zasługują na więcej uwagi niż inne, ze względu na prostotę obsługi i konfiguracji, skalowalność i niezawodność. System archiwizacji danych pod mianem Amanda to zupełnie darmowe rozwiązanie typu Open Source, a co za tym idzie, jest to świetnie udokumentowane i cross-platformowe oprogramowanie, które może znacznie ułatwić administratorom rozległych sieci wiele trudnych do opanowania procedur. W niniejszym artykule przedstawię niektóre cechy systemu archiwizacji danych Amanda, zaprezentuję i udokumentuję prostą konfigurację systemu Amanda, a także przeprowadzę prosty przykład sieciowej archiwizacji danych z sieciowego folderu Windows.

Jak działa Amanda


Amanda - Sieciowa archiwizacja danych
Amanda Community Server


Amanda jest systemem o architekturze Klient-Serwer, który umożliwia - między innymi - wykonywanie kopii zapasowych danych z wielu maszyn w sieci na jednym serwerze. Amanda oferuje możliwość archiwizacji danych zarówno na dyskach twardych, jak i na taśmach, bądź nośnikach optycznych. Możliwa jest jednoczesna archiwizacja danych na różnych rodzajach nośników. Zarchiwizowane dane mogą znajdować się więc zarówno na szybko dostępnych dyskach, w celu zapewnienia możliwości ich natychmiastowego przywrócenia, jak i na taśmach - w celu ich długoterminowej archiwizacji. Dane mogą zostać dodatkowo zarchiwizowane w chmurze.

System Amanda korzysta ze standardowych sterowników systemowych - jakie są ogólnie stosowane w danym systemie operacyjnym - urządzeń wejścia/wyjścia oraz z powszechnie dostępnych aplikacji archiwizacyjnych, takich jak dump czy GNUTar, wobec czego dostęp do zarchiwizowanych danych jest zawsze możliwy, nawet w przypadku całkowitego odinstalowania systemu Amanda z serwera i z klientów sieciowych. Amanda posiada bardzo dopracowane algorytmy archiwizacji, które są w stanie optymalnie dostroić sposób wykonywania zapisu, mając na uwadze wiele różnych czynników, takich jak ruch w sieci, ilość danych do zarchiwizowania itp.

Typowa konfiguracja serwera Amanda uwzględnia przejściową archiwizację danych w katalogach podręcznych na dysku twardym (holding disk) przed ich docelowym zapisaniem na bardziej trwałych nośnikach, takich jak taśmy. Tego typu rozwiazanie daje optymalne rezultaty jeśli chodzi o wydajność i płynność archiwizacji. Zamiast prawdziwych taśm istnieje możliwość stosowania wirtualnych taśm (vtapes), które są niczym innym jak odpowiednio przygotowanymi w tym celu katalogami na dysku twardym. Katalogi danych podręcznych (holding disk) i wirtualne taśmy, ze względów wydajnościowych powinny mieścić się na odrębnych dyskach fizycznych. Serwer Amanda umożliwia jednoczesne stosowanie wielu oddzielnych zestawów ustawień archiwizacji. W pliku disklist danego zestawu ustawień określa się katalogi, które mają zostać zarchiwizowane oraz sposób ich archiwizacji, który definiowany jest uprzednio w pliku amanda.conf danego zestawu ustawień. Serwer Amanda kontaktuje się z klientami Amanda, zainstalowanymi na maszynach w sieci, a klienci wysyłają archiwa danych w żądany przez serwer sposób. Możliwe jest również wyszukiwanie i odzyskiwanie zapisanych w archiwach serwera plików bezpośrednio poprzez oprogramowanie klienckie na archiwizowanych maszynach.

System archiwizacji Amanda może być z powodzeniem stosowany zarówno w małych sieciach jak i w rozległych korporacyjnych infrastrukturach sieciowych. Amanda oferuje wiele rozmaitych możliwości, nawet takich jak zabezpieczanie danych z serwera NFS, bądź archiwizacja danych z sieciowych folderów Windows z zastosowaniem klienta Samba (smbclient), z którym Amanda idealnie się integruje. W celu wykonania archiwizacji danych w sieci za pomocą systemu Amanda, należy zainstalować i skonfigurować zarówno serwer Amanda, jak i ewentualnie klientów sieciowych na maszynach, które zamierzamy archiwizować. W przypadku konieczności archiwizacji danych z komputerów Windows można, lecz nie trzeba, stosować klienckie oprogramowanie Amanda na maszynach Windows. W przypadku konieczności archiwizacji maszyn Windows, można obejść instalację oprogramowania klienckiego korzystając z oprogramowania smbclient po stronie serwera Amanda - co właśnie zademonstruję w niniejszym artykule.

Instalacja serwera Amanda możliwa jest wyłącznie w środowiskach Linux/UNIX, natomiast oprogramowanie klienckie może zostać zainstalowane na kilku różnych platformach: Linux, UNIX, BSD, Mac OS-X oraz Microsoft Windows. Komunikacja pomiędzy serwerem a klientami Amanda odbywa się w zupełnie bezpieczny sposób, pod warunkiem sporządzenia odpowiedniej konfiguracji systemu.

Od czego zacząć?


System archiwizacji danych Amanda może być skonfigurowany na różne sposoby, w zależności od potrzeb użytkowników i umiejętności administratora. Opanowanie podstaw systemu zajmuje generalnie od kilku do kilkunastu minut. Dogłębne poznanie możliwości systemu Amanda może zająć miesiące, a nawet całe lata. Omówiona w niniejszym artykule instalacja i podstawowa konfiguracja to tylko jedno z ogromnej ilości możliwych podejść do zagadnienia. Dużo informacji można również znaleźć tutaj: http://wiki.zmanda.com/index.php/Getting_Started_with_Amanda


Wstępne uwagi do przykładowej instalacji systemu Amanda


System archiwizacji Amanda dostępny jest w dwóch odmiennych wersjach: komercyjna wersja systemu, oraz Amanda Community – bezpłatna odmiana Amandy. Obie wersje różnią się zasadniczo nie tylko zakresem funkcjonalności, ale rodzajem wsparcia technicznego. W tym artykule skupię się na oprogramowaniu Amanda Community. Pliki niezbędne do instalacji systemu Amanda Community można pozyskać na wiele sposobów. Zaawansowani użytkownicy zapewne skorzystają z plików źródłowych, które można pobrać z witryny http://amanda.org/download.php W oficjalnej witrynie Amanda można także znaleźć pakiety binarne oprogramowania, odpowiednie dla kilku najbardziej popularnych dystrybucji systemu operacyjnego Linux, takich jak Debian, Fedora, Red Hat, Suse i Ubuntu. W opracowanym przeze mnie przykładzie instalacji i konfiguracji Amanda Community skorzystam z narzędzia yum, typowego sposobu instalacji pakietów dla dystrybucji Red Hat i pokrewnych, ponieważ – o dziwo - daje w moim środowisku pracy dostęp do stosunkowo aktualnej wersji oprogramowania.

Instalacja i konfiguracja serwera Amanda Community


Instalacja serwera Amanda wymaga obecności i prawidłowego funkcjonowania pakietu xinetd, za pomocą którego są uruchamiane usługi związane z serwerem archiwizacji. Xinetd, w porównaniu z Inetd zapewnia o wiele większe bezpieczeństwo pracy uruchamianych za jego pomocą usług. Aby zainstalować serwer Amanda i przeprowadzić jego podstawową konfigurację należy wykonać kilka prostych czynności. Aby zademonstrować prostotę i funkcjonalność systemu archiwizacji danych Amanda przygotowałem przykład prostej konfiguracji serwera do archiwizacji danych z klienta sieciowego Windows. Cała procedura instalacji i tego typu konfiguracji nie powinna czasowo przekroczyć 5-10 minut. Wiele jednak zależy od wersji instalowanego oprogramowania i od wersji systemu operacyjnego. W opracowanym przeze mnie przykładzie instalacji pakietów Amanda posługuję się wersjami pakietów 3.3.3, instalowanych w środowisku Scientific Linux 7.

Aby rozpocząć, jako użytkownik root należy zainstalować pakiety amanda oraz amanda-server za pomocą narzędzia yum:
[root@amanda1 ~]# yum install amanda amanda-server
W trakcie instalacji zostaje automatycznie utworzony użytkownik amandabackup, co można zweryfikować zaglądając do /etc/passwd:
amandabackup:x:33:6:Amanda user:/var/lib/amanda:/bin/bash
Jako użytkownik root należy ustawić hasło dla uzytkownika amandabackup!

Następnie należy utworzyć plik konfiguracyjny xinetd /etc/xinetd.d/amandaserver dla serwera Amanda:
# default: on
#
# opis: Usługi serwera i klienta Amanda uruchamiane przez xinetd
#
service amanda
{
disable = no
socket_type = stream
protocol = tcp
wait = no
user = amandabackup
group = disk
groups = yes
server = /usr/lib64/amanda/amandad
server_args = -auth=bsdtcp amdump amindexd amidxtaped
}
Po zapisaniu pliku /etc/xinetd.d/amandaserver można przeładować xinetd. Warto wówczas także sprawdzić czy xinetd i usługa amanda działają prawidłowo:
[root@amanda1 ~]# systemctl reload xinetd
[root@amanda1 ~]# systemctl status xinetd xinetd.service - Xinetd A Powerful Replacement For Inetd
Loaded: loaded (/usr/lib/systemd/system/xinetd.service; enabled)
Active: active (running) since Wed 2015-08-12 23:00:56 CEST; 9min ago
Process: 18344 ExecReload=/usr/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Process: 18216 ExecStart=/usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid $EXTRAOPTIONS (code=exited, status=0/SUCCESS)
Main PID: 18217 (xinetd)
CGroup: /system.slice/xinetd.service
└─18217 /usr/sbin/xinetd -stayalive -pidfile /var/run/xinetd.pid

Aug 12 23:08:25 amanda1 xinetd[18217]: readjusting service amanda
Aug 12 23:08:25 amanda1 xinetd[18217]: Reconfigured: new=0 old=1 dropped=0 (services)
Aug 12 23:08:29 amanda1 systemd[1]: Started Xinetd A Powerful Replacement For Inetd.
Przejdźmy teraz do ustawień koniecznych do archiwizowania danych z sieciowego klienta Windows o przykładowej nazwie sphinx. Aby archiwizacja danych z klienta Windows o nazwie sphinx była możliwa, po stronie serwera Amanda należy wykonać następujące czynności jako użytkownik root:
[root@amanda1 ~]# echo //sphinx/DoArchiwizacji amandabackup%tajnehasloamandy BIURO.LAN >> /etc/amandapass
[root@amanda1 ~]# chown amandabackup:disk /etc/amandapass
[root@amanda1 ~]# chmod 700 /etc/amandapass
Po stronie klienta Windows, należy odpowiednio udostępnić wybrany folder, w tym przypadku jest to folder o udostępnionej nazwie DoArchiwizacji. W niniejszym przykładzie folder jest udostępniany w grupie roboczej BIURO.LAN użytkownikowi systemu Windows (którego należy ewentualnie utworzyć) o nazwie Amandabackup, z hasłem użytkownika tajnehasloamandy.

Należy utworzyć konfigurację serwera Amanda jako użytkownik amandabackup, np. o nazwie Codziennie1.
bash-4.2$  amserverconfig Codziennie1
Logging to /var/log/amanda/amserverconfig.20150813112215.debug
mkdir /etc/amanda/Codziennie1
/var/lib/amanda/gnutar-lists directory exists
/etc/amanda/Codziennie1/advanced.conf created and updated
mkdir /etc/amanda/Codziennie1/curinfo
mkdir /etc/amanda/Codziennie1/index
curinfo and index directory created
tapelist file created
disklist file created
custom amanda.conf created
DONE.
Po udanym utworzeniu konfiguracji Codziennie1 należy edytować zawartość pliku konfiguracyjnego /etc/amanda/Codziennie1/amanda.conf. Plik zawiera mnóstwo opcji, których przeważnie nie trzeba zmieniać, chyba że się dokładnie wie co się robi. Jak widać z poniżej przedstawionej zawartości, plik zawiera załączoną zawartość kolejnego pliku - advanced.conf.

Poniżej zawartość przykładowego pliku amanda.conf z niektórymi typowymi opcjami, ważnymi dla niniejszego przykładu:

org "Przykładowa nazwa" # nazwa Organizacji
dumpuser "amandabackup" # użytkownik uprawniony do wykonywania archiwizacji
mailto "admin@przykladowyadres" # lista operatorów (adresy email oddzielone spacją)
dumpcycle 1 week # długość cyklu archiwizacji
runspercycle 5 # ilość uruchomień amdump w każdym cyklu archiwizacji
tapecycle 10 tapes # ilość taśm w rotacji
runtapes 1 # maks. taśm stosowanych w każdym uruchomieniu amdump

tpchanger "chg-disk://backup/vtapes/Codziennie1/slots"
tapetype HARDDISK
labelstr "^Codziennie1-[0-9][0-9]*$"
dtimeout 1800
ctimeout 30
etimeout 300

define dumptype global {
comment "Global definitions"
auth "bsdtcp"
}

define dumptype gui-base {
global
program "GNUTAR"
comment "gui base dumptype dumped with tar"
compress none
index yes
}

define tapetype HARDDISK {
comment "Virtual Tapes"
length 32768 mbytes
}

define dumptype encrypt-simple {
program "GNUTAR"
comment "szyfrowanie symetryczne - zrzut tar"
encrypt client
compress fast
client_encrypt "/usr/sbin/amcryptsimple"
client_decrypt_option "-d"
}


define holdingdisk Archiwizacja1 { 
directory /amandabackup/dumps/amanda 
use 300 Gb 
}

includefile "advanced.conf"
includefile "/etc/amanda/template.d/dumptypes"
includefile "/etc/amanda/template.d/tapetypes"

Prawidłowe ustawienia dotyczące taśm i rotacji taśm w pliku amanda.conf mają kluczowe znaczenie.

dumpcykle - Długość cyklu archiwizacji. Wartość parametru określa przedział czasowy, w którym wymienione w odpowiednim pliku disklist "dyski" są objęte co najmniej 1 pełną archiwizacją danych.

runspercykle - Wartość tego parametru określa ilość uruchomień programu archiwizacyjnego w przedziale czasowym określonym w dumpcykle. 

runtapes - Maksymalna ilość taśm stosowana przy każdy uruchomieniu programu archiwizacji.

tapecykle -  Ten parametr określa ilość taśm w rotacji, a jego błędne ustawienie może być przyczyną nieprawidłowo wykonywanej archiwizacji. Wartość tego parametru powinna zawsze przewyższać (np. 2x, 3x) ilość taśm stosowanych w danym cyklu archiwizacji, którą można łatwo obliczyć mnożąc wartość parametrów runspercykle x runtapes. Przykładowo, jeśli runspercykle wynosi 7, a runtapes jest 1, to Amanda nadpisuje zestaw 7 taśm w danym cyklu. Jeśli wówczas w rotacji jest 14 taśm (tapecykle = 14) to oznacza, że dane z każdego poprzedniego pełnego cyklu archiwizacji przechowywane są na pozostałym zestawie 7 taśm. Dobrym zwyczajem jest ustawienie parametru tapecykle:

               tapecykle >= 2 x runspercykle x runtapes

Następnie, jako użytkownik root należy utworzyć po stronie serwera Amanda katalogi danych archiwizacji przechowywanych tymczasowo na dysku twardym (holding disk). W tym celu należy wykonać następujące czynności:
[root@amanda1 ~]# mkdir -p /amandabackup/dumps/amanda
[root@amanda1 ~]# chown amandabackup:disk /amandabackup/dumps/amanda
[root@amanda1 ~]# chmod 750 /amandabackup/dumps/amanda

Kolejne kroki polegają na utworzeniu katalogów do przechowywania wirtualnych taśm zarchiwizowanych danych. Polecenia, które należy wydać jako użytkownik root:
[root@amanda1 ~]# mkdir -p /backup/vtapes
[root@amanda1 ~]# chown amandabackup:disk /backup/vtapes
[root@amanda1 ~]# chmod 750 /backup/vtapes

Następnie, jako użytkownik amandabackup, należy wydać następujące polecenia w celu utworzenia katalogów wirtualnych taśm:
bash-4.2$ mkdir -p /backup/vtapes/Codziennie1/slots
bash-4.2$ cd /backup/vtapes/Codziennie1/slots
bash-4.2$ for ((i=1; $i<=10; i++)); do mkdir slot$i;done
bash-4.2$ ln -s slot1 data

Warto teraz sprawdzić, również jako użytkownik amandabackup, czy wirtualne taśmy są w porządku:
bash-4.2$ amtape Codziennie1 show
amtape: scanning all 10 slots in changer:
slot 1: unlabeled volume
slot 2: unlabeled volume
slot 3: unlabeled volume
slot 4: unlabeled volume
slot 5: unlabeled volume
slot 6: unlabeled volume
slot 7: unlabeled volume
slot 8: unlabeled volume
slot 9: unlabeled volume
slot 10: unlabeled volume

Błąd: amtape: running as user "amandabackup" instead of "root"


Ten błąd pojawia się w przypadku gdy następuje próba uruchomienia aplikacji archiwizujących z pakietu Amanda przez użytkownika innego, niż użytkownik określony jako „dumpuser” w pliku amanda.conf dla danej konfiguracji serwera. Jeżeli po uruchomieniu aplikacji amtape nie wyświetlają się jakiekolwiek błędy, to można kontynuować konfigurację serwera Amanda.

Jako użytkownik amandabackup, pozostając w /backup/vtapes/Codziennie1/slots, należy nadać uprzednio utworzonym wirtualnym taśmom odpowiednie etykietki - w następujący sposób:
bash-4.2$ for ((i=1; $i<=10;i++)); do amlabel Codziennie1 Codziennie1-0$i slot $i; done
Reading label...
Found an empty tape.
Writing label 'Codziennie1-01'...
Checking label...
Success!
...
Po nadaniu etykiet warto się upewnić czy wszystko jest w porządku:
bash-4.2$ amtape Codziennie1 show
amtape: scanning all 10 slots in changer:
slot 10: date X label Codziennie1-010
slot 1: date X label Codziennie1-01
slot 2: date X label Codziennie1-02
slot 3: date X label Codziennie1-03
slot 4: date X label Codziennie1-04
slot 5: date X label Codziennie1-05
slot 6: date X label Codziennie1-06
slot 7: date X label Codziennie1-07
slot 8: date X label Codziennie1-08
slot 9: date X label Codziennie1-09
Następnie należy zresetować wirtualny streamer:
bash-4.2$ amtape Codziennie1 reset
changer is reset
Jako użytkownik amandabackup należy dodać następującą zawartość do pliku /etc/amanda/Codziennie1/disklist:
amanda1 //sphinx/DoArchiwizacji comp-user-tar
Kolejna czynność polega na skonfigurowaniu, jako użytkownik amandabackup, pliku /var/lib/amanda/.amandahosts, którego zawartość powinna wyglądać następująco:
localhost amandabackup admump amanda1 root amindexd amidxtaped amanda1 amandabackup admump
W tej chwili warto sprawdzić za pomocą narzędzia amcheck, czy wszystkie ustawienia systemu archiwizacji zostały dokonane prawidłowo. Należy pamiętać o uprzednim udostępnieniu odpowiedniego folderu użytkownikowi amandabackup w systemie Windows, w przeciwnym razie program amcheck poinformuje o problemie z dostępem do sieciowego folderu. Jak widać poniżej wszelkie ustawienia zostały dokonane prawidłowo i serwer Amanda jest w stanie poprawnie wykonywać ustawione archiwizacje danych.
bash-4.2$ amcheck Codziennie1
Amanda Tape Server Host Check
-----------------------------
slot 1: volume 'Codziennie1-01'
Will write to volume 'Codziennie1-01' in slot 1.
NOTE: skipping tape-writable test
NOTE: host info dir /etc/amanda/Codziennie1/curinfo/amanda1 does not exist
NOTE: it will be created on the next run.
NOTE: index dir /etc/amanda/Codziennie1/index/amanda1 does not exist
NOTE: it will be created on the next run.
Server check took 0.767 seconds
Amanda Backup Client Hosts Check
--------------------------------
Client check: 1 host checked in 0.130 seconds. 0 problems found.

(brought to you by Amanda 3.3.3)
Aby sprawdzić, czy na pewno ustawiona archiwizacja klienta Windows działa prawidłowo, wystarczy uruchomić działanie ręcznie, po uprzednim skopiowaniu przykładowych plików do udostępnianego użytkownikowi amandabackup folderze w systemie Windows.
bash-4.2$ amdump Codziennie1
W przypadku problemów z dostępem systemu Amanda do udostępnionego folderu sieciowego, warto sprawdzić jak sobie z tym radzi smbclient:
bash-4.2$ smbclient //sphinx/DoArchiwizacji -U amandabackup -W BIURO.LAN
Enter amandabackup's password:
Domain=[SPHINX] OS=[Windows 10 Pro 10243] Server=[Windows 10 Pro 6.4]
Po uruchomieniu narzędzia amdump zostaje wykonana archiwizacja Codziennie1 i serwer wysyła wiadomość email z odpowiednim powiadomieniem na adres pocztowy wskazany w pliku amanda.conf odpowiadającemu wykonanej archiwizacji. Wiadomość zawiera wiele informacji związanych z wykonaną archiwizacją.

Aby sprawdzić co zostało zarchiwizowane:

bash-4.2$ amadmin Codziennie1 find

date host disk lv tape or file file part status
2015-08-13 22:48:00 amanda1 //sphinx/DoArchiwizacji 0 Codziennie1-08 1 1/1 OK

Aby jednak archiwizacje miały większy sens, warto określić odpowiedni harmonogram działań za pomocą narzędzia crontab.

Dodawanie klienta Linux do bieżącej konfiguracji Amanda


Aby do aktualnej - przykładowej -  konfiguracji systemu archiwizacji Amanda dodać nowego klienta, tym razem Linux, wystarczy wykonać kilka prostych czynności:

1. Na maszynie Linux, która ma być archiwizowana na serwerze Amanda należy zainstalować oprogramowanie amanda-client;

2. Należy utworzyć plik konfiguracyjny xinetd dla zainstalowanego oprogramowania amanda-client - analogicznie do czynności wykonanej po stronie serwera archiwizacji;

3. Nazwa serwera archiwizacji powinna zostać dodana do pliku .amandahosts na maszynie klienckiej, a nazwa klienta powinna zostać dodana do pliku .amandahosts po stronie serwera. Należy posługiwać się odpowiednią składnią zawierającą nazwę hosta, użytkownika i oprogramowania:
amandaserver.przyklad.com użytkownik-archiwizator usługa(i)
4. Po stronie serwera należy uwzględnić katalogi klienta Linux, które mają być archiwizowane, w odpowiednim pliku .disklist, np:
kot-filemon.dom.net /home/kicia1 comp-user-tar
5. Po stronie klienta należy utworzyć odpowiedni plik amanda-client.conf, co umożliwi przywracanie danych z serwera Amanda, przykładowo:
# /etc/amanda/amanda-client.conf
#
conf "Codziennie1"
index_server "amanda"
tape_server "amanda"
auth "bsdtcp"

środa, 12 sierpnia 2015

Aktualizacja BIOSU

W niniejszym artykule opisuję przykładową procedurę aktualizacji oprogramowania BIOS. Do celów związanych z tematem wybrałem płytę główną ASUS P6T Deluxe, która pomimo swoich kilku ładnych lat, jest nadal bardzo popularnym i lubianym modelem wśród pasjonatów sprzętu IT. Płytę, którą znalazłem dziś przypadkowo na strychu, po przeprowadzonej i udanej aktualizacji BIOSu, postanowiłem zastosować w domowym serwerze plików z bardzo wydajnym, ale na dzisiejsze czasy już nie tak drogim jak niegdyś, procesorem Intel Core i7.

Uwaga! Aktualizacja BIOSu jest operacją krytyczną i nie należy jej przeprowadzać jeśli nie jesteśmy pewni co robimy! W trakcie aktualizacji BIOSU nie wolno wyłączać sprzętu, ponieważ grozi to nieodwracalnym uszkodzeniem układów płyty głównej. Aktualizację BIOSu przeprowadzamy zawsze na własne ryzyko!

Oprogramowanie RUFUS


Aktualizacja BIOSu wymaga uprzedniego uruchomienia komputera z bootowalnego nośnika MS-DOS. Kiedyś w tym celu stosowało się dyskietki, ale dziś trudno jest o dyskietki i odpowiednie dla nich napędy. Obecnie istnieje kilka popularnych aplikacji nadających się do tworzenia bootowalnych nośników USB z oprogramowaniem emulującym MS-DOS, lecz moim ulubionym rozwiązaniem jest od pewnego czasu Rufus. Aplikacja Rufus, oferująca wiele ciekawych opcji, świetnie nadaje się nie tylko do tworzenia bootowalnych nośników USB z systemem Free Dos, ale także można jej użyć do przygotowania bootowalnych nośników z wybranymi obrazami .iso, np. systemu Linux. Rufus obsługuje zarówno system partycjonowania MBR, jak również UEFI. W niniejszym przykładzie, w celu aktualizacji BIOSu dość popularnej płyty głównej, zastosowałem aplikację Rufus w wersji 2.2, a pobrałem ją z witryny http://rufus.akeo.ie/

Aktualne pliki BIOSu


Do przeprowadzenia aktualizacji BIOSu niezbędny jest plik z najnowszą wersją BIOSu oraz aplikacja zapisująca program w układzie płyty głównej. Plik z aktualną wersją BIOSu danej płyty głównej można zawsze pobrać z witryny producenta sprzętu, gdzie można przeważnie znaleźć także aplikację służącą do przeprogramowania układów płyty. W niniejszym przykładzie pliki związane z aktualizacją BIOSu płyty głównej ASUS P6T Deluxe pochodzą z oficjalnej witryny producenta.

Tworzenie bootowalnego nośnika USB z systemem operacyjnym FREE DOS


Aby utworzyć bootowalny nośnik USB z oprogramowaniem Free Dos, należy w poziomu Windows uruchomić program Rufus i wybrać przedstawione w poniższym obrazku opcje, po czym należy przystąpić do tworzenia nośnika klikając w przycisk START.

Rufus Free Dos
Rufus 2.2 - Tworzenie bootowalnego nośnika USB Free Dos


Proszę zwrócić uwagę, iż po potwierdzeniu operacji utworzenia bootowalnego nośnika, wszelkie znajdujące się na nośniku USB dane zostaną usunięte. W efekcie potwierdzenia operacji, utworzona przez program Rufus zawartość głównego katalogu bootowalnego nośnika USB powinna wyglądać następująco:
2015-08-11 22:15 [DIR] LOCALE
2015-08-11 22:15 266 CONFIG.SYS
2015-08-11 22:15 202 AUTOEXEC.BAT
2015-08-11 22:15 206 autorun.inf
2015-08-11 22:15 34 494 autorun.ico
4 File(s) 35 168 bytes
1 Dir(s) 4 033 347 584 bytes free

Kopiowanie plików BIOSu na bootowalny nośnik USB


Po utworzeniu bootowalnego nośnika USB należy do niego wrzucić wszelkie pliki niezbędne do aktualizacji BIOSu. Po skopiowaniu na nośnik USB plików związanych z aktualizacją BIOSu, czyli w naszym przypadku pliku z rozszerzeniem .ROM zawierającego nowy firmware oraz aplikacji AFU241, służącej do aktualizacji oprogramowania płyty głównej, zawartość dysku F:\ powinna wyglądać następująco:

2015-08-11 22:15 [DIR] LOCALE
2015-08-11 22:15 266 CONFIG.SYS
2015-08-11 22:15 202 AUTOEXEC.BAT
2015-08-11 22:15 206 autorun.inf
2015-08-11 22:15 34 494 autorun.ico
2010-11-08 16:59 2 097 152 P6T-AS~1.ROM
2009-04-14 18:32 53 345 AFUDOS241.exe
6 File(s) 2 185 665 bytes
1 Dir(s) 4 031 184 896 bytes free
W tym momencie wszelkie pliki niezbędne do wykonania aktualizacji BIOSu znajdują się już na bootowalnym nośniku USB i można przystąpić do aktualizacji starej wersji firmware płyty.

Aktualizacja BIOSu ASUS P6T Deluxe


Przed włożeniem nowo utworzonego bootowalnego nośnika do portu USB komputera, którego BIOS mamy zamiar aktualizować, warto się upewnić, że obecne ustawienia BIOSu umożliwiają uruchomienie sprzętu z wymiennego dysku USB. W tym celu, po wejściu do ustawień BIOSu (wciśnięty przycisk DEL podczas startu komputera) należy się upewnić, że obsługa USB jest włączona, a także ustawić prawidłową kolejność napędów bootowania, tak aby wymienny dysk (Removable Dev.) znajdował się w pierwszej kolejności.

Po udanym uruchomieniu komputera z bootowalnego nośnika USB Free Dos, na ekranie powinny pojawić się informacje związane z systemem operacyjnym Free Dos.

Free Dos
Free Dos

Aby kontynuować należy dokonać wyboru klawiatury.

Po dokonaniu wyboru klawiatury można rozpocząć aktualizację BIOSu.

Free Dos
Free Dos


Uwaga! Jak już pisałem wcześniej, aktualizacja BIOSu jest operacją krytyczną. Nie należy do niej podchodzić, jeśli nie jest się pewnym o co w tym chodzi!

Aby uruchomić aplikację służącą do aktualizacji BIOSu i przeprogramować układ płyty do wybranej wersji oprogramowania, należy wydać polecenie AFUDOS.EXE z przedstawionymi poniżej parametrami:

Asus AFUDOS.EXE
Asus AFUDOS.EXE



 
Programowanie BIOSu
Programowanie BIOSu

Asus P6T Deluxe
Aktualna wersja BIOSu ASUS P6T Deluxe
 To wszystko na dziś. Powodzenia!

niedziela, 9 sierpnia 2015

Jak zabezpieczyć domową sieć Wi-Fi

Wstęp


Bezpieczna sieć to podstawa bezpieczeństwa znajdujących się w niej komputerów i innych urządzeń. Luki w zabezpieczeniach sieci mogą nie tylko ułatwić hakerom dostęp do danych na dyskach, ale także umożliwić im przejęcie pełnej kontroli nad sprzętem. Hakerzy mogą w ten sposób, przykładowo, rozsyłać spam korzystając z naszych komputerów, bądź smartfonów lub włamywać się do innych sieci za pomocą naszego sprzętu.

W porównaniu z okablowanymi sieciami Ethernet, domowe sieci Wi-Fi stanowią wielkie ułatwienie, nie tylko dla osób właściwie z nich korzystających, ale także dla potencjalnych hakerów. Jak się bowiem okazuje, do słabo zabezpieczonych, bądź niewłaściwie skonfigurowanych domowych sieci Wi-Fi bardzo łatwo jest się włamać, o wiele łatwiej, niż do słabo zabezpieczonych komputerowych sieci okablowanych.

Aby w pełni cieszyć się dobrodziejstwami rozwiązań sieciowych Wi-Fi, bez narażania się na skutki uboczne hakerskich wyczynów, wystarczy zapoznać się z kilkoma bardzo prostymi, ale skutecznymi wskazówkami, które przedstawię w niniejszym artykule. Omówię głównie aspekty związane z funkcjami Wi-Fi urządzeń generujących sieć. Niezależnie od rodzaju urządzenia odpowiedzialnego za generowanie infrastruktury sieci Wi-Fi, a może być to przykładowo ruter z funkcją Wi-Fi, bądź punkt dostępowy Wi-Fi (AP), ale nie tylko, przedstawione przeze mnie porady są na tyle uniwersalne, że będzie można je w prawie każdym przypadku zastosować z powodzeniem.

Przed rozpoczęciem, czyli jak to wszystko zrobić


Aby zastosować poniżej przedstawione wskazówki, konieczny jest dostęp do panelu administracyjnego urządzenia generującego infrastrukturę sieci Wi-Fi, które mamy zamiar zabezpieczyć. Do urządzenia generującego Wi-Fi można się przeważnie dostać korzystając z przeglądarki internetowej, po wpisaniu w pasku adresów url odpowiedniej wartości IP. Fabrycznie ustawiony adres IP tego typu urządzeń to przeważnie 192.168.1.1, z maską podsieci 255.255.255.0, choć miałem okazję spotkać się z urządzeniami o fabrycznie ustawionych adresach 192.168.1.2, a także 192.168.0.1. Aby sprzęt Wi-Fi był widoczny dla przeglądarki, musi się on znajdować w tej samej podsieci co komputer, na którym uruchamiana jest przeglądarka.

Hasło do AP / rutera


Fabrycznie ustawione nazwa użytkownika i hasło do panelu administracyjnego rutera, bądź punktu dostępu Wi-Fi, widnieją generalnie w instrukcji obsługi sprzętu. Często producenci umieszczają te informacje dodatkowo na spodzie, bądź na którymś z boków urządzenia. Listy fabrycznych nazw użytkowników i haseł, odpowiadających konkretnym modelom urządzeń Wi-Fi znajdują się nie tylko w internecie, ale także w bazach danych popularnych i łatwo dostępnych aplikacji hakerskich, które stosowane są w celu włamania się do sieci Wi-Fi. Dlatego też, warto podjąć opisaną w tej sekcji i bardzo prostą czynność, która niestety często jest pomijana przez "administratorów" domowych sieci. Niezwłocznie po pierwszym udanym zalogowaniu się do panelu administracyjnego urządzenia dostępowego za pomocą fabrycznie ustawionego hasła i niezależnie od tego, czy chodzi o punkt dostępowy Wi-Fi (AP), czy też ruter z obsługą Wi-Fi, zmiana standardowego hasła admina to pierwsza czynność, którą należy wykonać. Nowo ustawione hasło dostępu do urządzenia powinno być trudne do odgadnięcia i składać się, w miarę możliwości, z różnego rodzaju znaków alfanumerycznych użytych na przemian. Przykładowo, trudnym do złamania hasłem może okazać się kombinacja hH7_=Z09cFg. W urządzeniach, które na to pozwalają, oprócz samego hasła warto ustawić nietypową nazwę użytkownika a uprawnieniami administracyjnymi, jak np. oOop1baba.

Zmiana hasła do rutera/AP Wi-FI
Pierwsze co należy zrobić: zmiana hasła dostępu do sprzętu generującego sieć Wi-Fi

Aktualizacja oprogramowania firmware rutera


Kolejnym ważnym krokiem, po zmianie standardowego hasła, a w miarę możliwości także nazwy użytkownika uprawnionego do działań administracyjnych na sieciowym sprzęcie Wi-Fi, należy sprawdzić czy oprogramowanie (firmware) rutera bądź AP jest aktualne. Informacje na ten temat można zawsze uzyskać na stronie producenta, a w przypadku ukazania się nowej wersji, oprogramowanie należy niezwłocznie uaktualnić. Jak tego dokonać zależy wyłącznie od zaleceń producenta. Nieaktualne oprogramowanie firmware może zawierać luki ułatwiające przejęcie kontroli nad sprzętem i urządzeniami znajdującymi się w sieci.

Bezpieczeństwo sieci Wi-Fi to także aktualne oprogramowanie Firmware
Aktualna wersja Firmware to podstawa bezpieczeństwa sieci Wi-Fi

Identyfikator sieci SSID


Zalecaną czynnością jest ukrycie identyfikatora SSID, bądź przynajmniej zmiana fabrycznie ustawionego identyfikatora SSID, który ułatwia hakerom identyfikację marki i modelu sprzętu, na inny. Jeśli nie mamy zamiaru ukrywać identyfikatora SSID, bo chcemy aby sieć była dobrze widoczna, to warto zmienić standardowy SSID na coś nietypowego.

SSID
Identyfikator SSID

Szyfrowanie danych


W przeciwieństwie do sieci okablowanych, do których osobom nieautoryzowanym nie sposób się dostać bez podłączenia komputera do odpowiedniego gniazdka sieciowego – do którego dostęp jest generalnie dobrze zabezpieczony, radiowy sygnał sieci Wi-Fi daje hakerom praktycznie nieograniczone możliwości. Obecne standardy Wi-Fi pozwalają jednak w łatwy sposób wymusić szyfrowanie danych przesyłanych w sieci. Szyfrowanie danych Wi-Fi uniemożliwia odczyt informacji, jakie przesyłane są w sieci, w tym także różnego rodzaju haseł, dlatego też zawsze warto takie szyfrowanie zastosować. Wśród powszechnie dostępnych standardów szyfrowania danych WEP, WPA i WPA2 najmniej bezpiecznym jest WEP, choć jego zastosowanie umożliwia przyłączanie do sieci także starszych urządzeń, które nie obsługują lepszego sposobu szyfrowania. WEP jest naprawdę łatwo złamać i wiele popularnych aplikacji bardzo dobrze sobie radzi z tym zadaniem. O wiele lepszym od WEP rozwiązaniem jest WPA (PSK), a najbezpieczniejszym, wśród powszechnie dostępnych protokołów szyfrujących Wi-Fi, jest aktualnie WPA2-PSK, którego szyfry okazują się być praktycznie niemożliwe do złamania. Szyfrowanie danych Wi-Fi wykonywane jest na podstawie klucza szyfrującego, który powinien być starannie dobrany, tak aby nie był łatwy do odgadnięcia. Zastosowanie odpowiedniego rodzaju szyfrowania danych, połączone z pozostałymi wskazówkami zawartymi w tym artykule, pozwala uzyskać wysoki poziom zabezpieczeń sieci Wi-Fi.

Szyfrowanie danych Wi-Fi
Szyfrowanie danych Wi-Fi. Najbezpieczniej z WPA2-PSK


Sygnał Wi-Fi


Poziom sygnału Wi-Fi w urządzeniu generującym sieć nie powinien być zbyt niski, ani zbyt wysoki. Za słaby sygnał może być przyczyną nieprawidłowego funkcjonowania całej sieci Wi-Fi, natomiast za mocny sygnał może stwarzać dodatkowe zagrożenie ewentualnych ataków hakerskich. Jeżeli znajdujemy się w małym mieszkaniu na osiedlu, warto zmniejszyć zasięg sygnału Wi-Fi w taki sposób, aby nie przenikał on niepotrzebnie do sąsiednich mieszkań, klatki schodowej bądź podwórka. Jak odpowiednio zmniejszyć sygnał sieci Wi-Fi? Jest na to kilka skutecznych sposobów: zmiana tryby pracy urządzenia na standard 802.11g (zamiast 802.11n czy 802.11b); umiejscowienie urządzenia w szafce; częściowe osłonięcie anteny folią aluminiową.

Filtrowanie adresów MAC


Filtrowanie adresów MAC na ruterze Wi-Fi, bądź urządzeniu typu AP pozwala w pewnym sensie ograniczyć nieautoryzowany dostęp do sieci Wi-FI. Jak to działa? W zależności od modelu urządzenia generującego sieć Wi-Fi, filtrowanie dostępu do sieci Wi-Fi oparte na adresach MAC (sprzętowy adres interfejsu sieciowego urządzeń) może oferować mniej lub bardziej zaawansowane funkcje. Jednak każde urządzenie wspierające taką możliwość pozwala wykluczyć z dostępu do sieci Wi-Fi urządzenia o adresach MAC nie znajdujących się na autoryzowanej liście. Niestety metoda sama w sobie nie daje stu procentowej pewności, ponieważ istnieją bardzo proste metody podmiany adresów MAC interfejsów sieciowych urządzeń, a także sposoby na odczytanie adresów MAC interfejsów sieciowych urządzeń korzystających z danej sieci Wi-Fi.

Wyłączenie funkcji WPS


Niektóre urządzenia generujące sieć Wi-Fi wyposażone są w funkcję WPS, która znacznie ułatwia przyłączenie się do sieci. Aby zapewnić wysoki poziom bezpieczeństwa sieci Wi-Fi funkcję WPS należy koniecznie wyłączyć korzystając w tym celu z panelu administracyjnego.

sobota, 8 sierpnia 2015

Cygwin cron w środowisku Windows 10 Pro

Wstęp


O zaletach oprogramowania Cygwin pisałem już w artykułach Linux w windzie? Cygwin! i Cygwin + rsync - bezpieczna i szybka archiwizacja danych. Nie będę więc rozpisywał się tutaj o tym czym Cygwin jest, bądź jak to oprogramowanie zainstalować w systemie Windows.

Skupię się tutaj na kilku ważnych wskazówkach, niezbędnych do uruchomienia usługi Cygwin cron w środowisku Windows 10 Pro. Skuteczna konfiguracja tej usługi może okazać się niekiedy uciążliwa i pracochłonna. Pomocne w rozwiązywaniu ewentualnych problemów z usługą Cygwin cron mogą okazać się: narzędzie cronevents, dziennik błędów w pliku /var/log/cron, a w ostateczności, narzędzie cronbug.

Cronevents


Narzędzie cronevents służy do wyświetlania zawartości dziennika systemu Windows, dotyczącej wydarzeń związanych z usługą Cygwin cron. W przypadku pojawienia się niejasności z usługą cron warto wywołać cronevents i sprawdzić zawartość dziennika.

XNOTE@sphinx ~ $ cronevents 2015/08/08 00:34:01 [cygrunsrv] /usr/sbin/cron: PID 3280: (XNOTE) CMD (/usr/bin/date > /home/XNOTE/data.txt)
2015/08/08 00:34:01 [cygrunsrv] /usr/sbin/cron: PID 3280: (CRON) error (can't switch user context)
2015/08/08 01:13:55 [cygrunsrv] cron: PID 6004: `cron' service stopped, exit status: 0
2015/08/08 01:14:00 [cygrunsrv] /usr/sbin/cron: PID 816: (CRON) STARTUP (V5.0)

Cronbug


Cronbug jest jedyną nadzieją w przypadku, gdy wszelkie inne strategie zawodzą. Wywołanie narzędzia cronbug umożliwia wygenerowanie dokładnego raportu o składnikach systemowych, ustawieniach i błędach, związanych z usługą Cygwin cron. Raport, wraz z opisem problemu, można wysłać do twórców oprogramowania Cygwin, w celu uzyskania pomocy.

Błąd: [cygrunsrv] /usr/sbin/cron: PID 3280: (CRON) error (can't switch user context)


Załóżmy, że udało nam się pozornie-prawidłowo zainstalować usługę Cygwin cron za pomocą narzędzia cron-config, przygotowaliśmy nasz pierwszy zaplanowany harmonogram, ale niestety nic się nie dzieje gdy nadchodzi czas zaplanowanych działań! Próbujemy kilka razy, podmieniamy czasy w harmonogramie, lecz nadal cisza. Zaglądamy do dziennika błędów w /var/log/cron, ale okazuje się, że plik jest całkiem pusty. Kolejnym krokiem jest cronevents, w którym zauważamy błąd "...(can't switch user context)". Co oznacza taka sytuacja i gdzie szukać pomocy w takim przypadku?

Powyższy błąd spowodowany jest rozbudowanym systemem zabezpieczeń Windows, w świetle którego usługa Cygwin cron standardowo nie posiada odpowiednich uprawnień by prawidłowo działać. Aby umożliwić usłudze prawidłową pracę należy podjąć kroki opisane poniżej.

 

Prawidłowa konfiguracja Cygwin cron


1. Za pomocą usługi cron-config standardowo konfigurujemy cron jako usługę (service);

2. W przypadku pojawienia się informacji o nieprawidłowych uprawnieniach do katalogów przerywamy pracę narzędzia cron-config i poprawiamy ręcznie uprawnienia wedle zaleceń programu;

3. Jako Administrator, bądź użytkownik z odpowiednimi uprawnieniami, z poziomu systemu Windows tworzymy konto użytkownika Windows dla usługi cron, o przykładowej nazwie cygrunsrv_user i dodajemy to konto do grupy Administratorów;

4. Jako Administrator, bądź użytkownik z odpowiednimi uprawnieniami, z wiersza poleceń systemu Windows 10 uruchamiamy Edytor Zasad Zabezpieczeń Lokalnych, wydając polecenie secpol.msc;

Edytor Zasad Zabezpieceń Lokalnych Windows
Edytor Zasad Zabezpieczeń Lokalnych w Windows 10 Pro

5. W Edytorze Zasad Zabezpieczeń Lokalnych przechodzimy do Zasady Lokalne->Przypisywanie praw Użytkownika;

6. Utworzonemu uprzednio użytkownikowi nadajemy następujące uprawnienia:

a. Logowanie w trybie usługi
b. Zamień token na poziomie procesu
c. Utwórz objekt tokenu

7. Przechodzimy do zarządzania komputerem, wybieramy Aplikacje i Usługi, a następnie klikamy w Usługi, w których odnajdujemy usługę Cron;

8. Klikając dwukrotnie w widniejącą na liście usługę Cron pojawiają się właściwości usługi, a wtedy przechodzimy do zakładki Logowanie. Zmieniamy sposób logowania się usługi na logowanie jako uprzednio utworzone przez nas konto:


Usługa cygwin cron Windows 10
Logowanie usługi cron jako utworzone przez nas konto

9. Z poziomu listy usług zatrzymujemy i ponownie uruchamiamy usługę cron, tak aby mogła się zalogować jako wybrany użytkownik;

10. Z poziomu Cygwin warto teraz wywołać narzędzie cronevents, aby sprawdzić czy wszystko poszło jak powinno:

2015/08/08 12:51:59 [cygrunsrv] cron: PID 3252: `cron' service stopped, exit status: 0
2015/08/08 12:52:03 [cygrunsrv] /usr/sbin/cron: PID 2924: (CRON) STARTUP (V5.0)
2015/08/08 12:52:04 [cygrunsrv] cron: PID 9504: `cron' service started