Keselamatan dan DBMS: perkara yang anda perlu ingat apabila memilih alat keselamatan

Keselamatan dan DBMS: perkara yang anda perlu ingat apabila memilih alat keselamatan

Nama saya Denis Rozhkov, saya ketua pembangunan perisian di syarikat Gazinformservice, dalam pasukan produk Jatoba. Perundangan dan peraturan korporat mengenakan keperluan tertentu untuk keselamatan storan data. Tiada siapa yang mahu pihak ketiga mendapat akses kepada maklumat sulit, jadi isu berikut adalah penting untuk mana-mana projek: pengenalan dan pengesahan, mengurus akses kepada data, memastikan integriti maklumat dalam sistem, mengelog peristiwa keselamatan. Oleh itu, saya ingin bercakap tentang beberapa perkara menarik mengenai keselamatan DBMS.

Artikel itu disediakan berdasarkan ucapan di @DatabasesMeetup, tersusun Penyelesaian Awan Mail.ru. Jika anda tidak mahu membaca, anda boleh menonton:


Artikel itu akan mempunyai tiga bahagian:

  • Bagaimana untuk menjamin sambungan.
  • Apakah audit tindakan dan cara merekodkan perkara yang berlaku di bahagian pangkalan data dan menyambung kepadanya.
  • Bagaimana untuk melindungi data dalam pangkalan data itu sendiri dan teknologi apa yang tersedia untuk ini.

Keselamatan dan DBMS: perkara yang anda perlu ingat apabila memilih alat keselamatan
Tiga komponen keselamatan DBMS: perlindungan sambungan, pengauditan aktiviti dan perlindungan data

Menjamin sambungan anda

Anda boleh menyambung ke pangkalan data sama ada secara langsung atau tidak langsung melalui aplikasi web. Sebagai peraturan, pengguna perniagaan, iaitu, orang yang bekerja dengan DBMS, berinteraksi dengannya secara tidak langsung.

Sebelum bercakap tentang melindungi sambungan, anda perlu menjawab soalan penting yang menentukan cara langkah keselamatan akan distrukturkan:

  • Adakah satu pengguna perniagaan bersamaan dengan satu pengguna DBMS?
  • sama ada akses kepada data DBMS disediakan hanya melalui API yang anda kawal, atau sama ada jadual diakses secara terus;
  • sama ada DBMS diperuntukkan kepada segmen dilindungi yang berasingan, siapa yang berinteraksi dengannya dan bagaimana;
  • sama ada lapisan pengumpulan/proksi dan perantaraan digunakan, yang boleh mengubah maklumat tentang cara sambungan dibina dan siapa yang menggunakan pangkalan data.

Sekarang mari lihat alat yang boleh digunakan untuk menjamin sambungan:

  1. Gunakan penyelesaian kelas firewall pangkalan data. Lapisan perlindungan tambahan akan, sekurang-kurangnya, meningkatkan ketelusan perkara yang berlaku dalam DBMS, dan secara maksimum, anda akan dapat memberikan perlindungan data tambahan.
  2. Gunakan dasar kata laluan. Penggunaannya bergantung pada cara seni bina anda dibina. Walau apa pun, satu kata laluan dalam fail konfigurasi aplikasi web yang bersambung ke DBMS tidak mencukupi untuk perlindungan. Terdapat beberapa alat DBMS yang membolehkan anda mengawal bahawa pengguna dan kata laluan memerlukan pengemaskinian.

    Anda boleh membaca lebih lanjut tentang fungsi penilaian pengguna di sini, anda juga boleh mengetahui tentang MS SQL Vulnerability Assessmen di sini

  3. Perkaya konteks sesi dengan maklumat yang diperlukan. Jika sesi itu legap, anda tidak faham siapa yang bekerja dalam DBMS dalam rangka kerjanya, anda boleh, dalam rangka kerja operasi yang dijalankan, menambah maklumat tentang siapa yang melakukan apa dan mengapa. Maklumat ini boleh dilihat dalam audit.
  4. Konfigurasikan SSL jika anda tidak mempunyai pemisahan rangkaian antara DBMS dan pengguna akhir; ia bukan dalam VLAN yang berasingan. Dalam kes sedemikian, adalah penting untuk melindungi saluran antara pengguna dan DBMS itu sendiri. Alat keselamatan juga tersedia dalam sumber terbuka.

Bagaimanakah ini akan menjejaskan prestasi DBMS?

Mari lihat contoh PostgreSQL untuk melihat cara SSL mempengaruhi beban CPU, meningkatkan pemasaan dan mengurangkan TPS, dan sama ada ia akan menggunakan terlalu banyak sumber jika anda mendayakannya.

Memuatkan PostgreSQL menggunakan pgbench ialah program mudah untuk menjalankan ujian prestasi. Ia melaksanakan satu urutan perintah berulang kali, mungkin dalam sesi pangkalan data selari, dan kemudian mengira kadar urus niaga purata.

Uji 1 tanpa SSL dan menggunakan SSL — sambungan diwujudkan untuk setiap transaksi:

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require 
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe --connect -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Uji 2 tanpa SSL dan menggunakan SSL — semua transaksi dilakukan dalam satu sambungan:

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres sslmode=require
sslrootcert=rootCA.crt sslcert=client.crt sslkey=client.key"

vs

pgbench.exe -c 10 -t 5000 "host=192.168.220.129 dbname=taskdb user=postgres"

Tetapan lain:

scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 5000
number of transactions actually processed: 50000/50000

Keputusan ujian:

 
TIADA SSL
SSL

Sambungan diwujudkan untuk setiap transaksi

purata kependaman
ms 171.915
ms 187.695

tps termasuk sambungan mewujudkan
58.168112
53.278062

tps tidak termasuk sambungan mewujudkan
64.084546
58.725846

CPU
24%
28%

Semua transaksi dilakukan dalam satu sambungan

purata kependaman
ms 6.722
ms 6.342

tps termasuk sambungan mewujudkan
1587.657278
1576.792883

tps tidak termasuk sambungan mewujudkan
1588.380574
1577.694766

CPU
17%
21%

Pada beban ringan, pengaruh SSL adalah setanding dengan ralat pengukuran. Jika jumlah data yang dipindahkan adalah sangat besar, keadaan mungkin berbeza. Jika kami mewujudkan satu sambungan bagi setiap transaksi (ini jarang berlaku, biasanya sambungan dikongsi antara pengguna), anda mempunyai bilangan sambungan/pemutus sambungan yang besar, kesannya mungkin lebih besar sedikit. Iaitu, mungkin terdapat risiko penurunan prestasi, bagaimanapun, perbezaannya tidak begitu besar untuk tidak menggunakan perlindungan.

Sila ambil perhatian bahawa terdapat perbezaan yang kuat jika anda membandingkan mod pengendalian: anda bekerja dalam sesi yang sama atau dalam yang berbeza. Ini boleh difahami: sumber dibelanjakan untuk mencipta setiap sambungan.

Kami mempunyai kes apabila kami menyambungkan Zabbix dalam mod amanah, iaitu, md5 tidak diperiksa, tidak ada keperluan untuk pengesahan. Kemudian pelanggan meminta untuk mendayakan mod pengesahan md5. Ini memberi beban berat pada CPU, dan prestasi menurun. Kami mula mencari cara untuk mengoptimumkan. Salah satu penyelesaian yang mungkin untuk masalah ini ialah melaksanakan sekatan rangkaian, membuat VLAN berasingan untuk DBMS, menambah tetapan untuk menjelaskan dengan jelas siapa yang menyambung dari mana dan mengalih keluar pengesahan. Anda juga boleh mengoptimumkan tetapan pengesahan untuk mengurangkan kos apabila mendayakan pengesahan, tetapi secara amnya penggunaan kaedah pengesahan yang berbeza mempengaruhi prestasi dan memerlukan mengambil kira faktor ini semasa mereka bentuk kuasa pengkomputeran pelayan (perkakasan) untuk DBMS.

Kesimpulan: dalam beberapa penyelesaian, walaupun nuansa kecil dalam pengesahan boleh menjejaskan projek dan ia adalah buruk apabila ini menjadi jelas hanya apabila dilaksanakan dalam pengeluaran.

Audit tindakan

Audit boleh bukan sahaja DBMS. Audit adalah tentang mendapatkan maklumat tentang perkara yang berlaku dalam segmen yang berbeza. Ini boleh sama ada tembok api pangkalan data atau sistem pengendalian di mana DBMS dibina.

Dalam DBMS peringkat Perusahaan komersial semuanya baik dengan pengauditan, tetapi dalam sumber terbuka - tidak selalu. Inilah yang PostgreSQL ada:

  • log lalai - pembalakan terbina dalam;
  • sambungan: pgaudit - jika pengelogan lalai tidak mencukupi untuk anda, anda boleh menggunakan tetapan berasingan yang menyelesaikan beberapa masalah.

Tambahan kepada laporan dalam video:

"Pengelogan pernyataan asas boleh disediakan oleh kemudahan pembalakan standard dengan log_statement = semua.

Ini boleh diterima untuk pemantauan dan kegunaan lain, tetapi tidak memberikan tahap butiran yang biasanya diperlukan untuk pengauditan.

Ia tidak mencukupi untuk mempunyai senarai semua operasi yang dilakukan pada pangkalan data.

Ia juga mungkin untuk mencari penyata khusus yang menarik minat juruaudit.

Pengelogan standard menunjukkan perkara yang diminta pengguna, manakala pgAudit memfokuskan pada butiran perkara yang berlaku apabila pangkalan data melaksanakan pertanyaan.

Sebagai contoh, juruaudit mungkin ingin mengesahkan bahawa jadual tertentu telah dibuat dalam tetingkap penyelenggaraan yang didokumenkan.

Ini mungkin kelihatan seperti tugas mudah dengan pengauditan asas dan grep, tetapi bagaimana jika anda diberikan contoh seperti ini (sengaja mengelirukan):

LAKUKAN$$
BEGIN
LAKUKAN 'CREATE TABLE import' || 'ant_table (id int)';
TAMAT$$;

Pengelogan standard akan memberi anda ini:

LOG: pernyataan: DO $$
BEGIN
LAKUKAN 'CREATE TABLE import' || 'ant_table (id int)';
TAMAT$$;

Nampaknya mencari jadual minat mungkin memerlukan beberapa pengetahuan kod dalam kes di mana jadual dicipta secara dinamik.

Ini tidak sesuai, kerana ia adalah lebih baik untuk hanya mencari mengikut nama jadual.

Di sinilah pgAudit berguna.

Untuk input yang sama, ia akan menghasilkan output ini dalam log:

AUDIT: SESI,33,1,FUNGSI,LAKUKAN,,,"LAKUKAN $$
BEGIN
LAKUKAN 'CREATE TABLE import' || 'ant_table (id int)';
TAMAT$$;"
AUDIT: SESI,33,2,DDL,BUAT JADUAL,JADUAL,public.important_table,CREATE TABLE important_table (id INT)

Bukan sahaja blok DO dilog, tetapi juga teks penuh CREATE TABLE dengan jenis pernyataan, jenis objek dan nama penuh, menjadikan carian lebih mudah.

Apabila mengelog penyata SELECT dan DML, pgAudit boleh dikonfigurasikan untuk log masukan berasingan bagi setiap perhubungan yang dirujuk dalam penyata.

Tiada penghuraian diperlukan untuk mencari semua pernyataan yang menyentuh jadual tertentu(*) ».

Bagaimanakah ini akan menjejaskan prestasi DBMS?

Mari jalankan ujian dengan pengauditan penuh didayakan dan lihat apa yang berlaku kepada prestasi PostgreSQL. Mari dayakan pengelogan pangkalan data maksimum untuk semua parameter.

Kami hampir tidak mengubah apa-apa dalam fail konfigurasi, perkara yang paling penting ialah menghidupkan mod debug5 untuk mendapatkan maklumat maksimum.

postgresql.conf

log_destination = 'stderr'
logging_collector = on
log_truncate_on_rotation = on
log_putaran_umur = 1d
log_rotation_size = 10MB
log_min_messages = nyahpepijat5
log_min_error_statement = nyahpepijat5
log_min_duration_statement = 0
debug_print_parse = hidup
debug_print_rewritten = hidup
debug_print_plan = hidup
debug_pretty_print = hidup
log_checkpoints = aktif
sambungan_log = hidup
log_disconnections = hidup
log_duration = on
log_hostname = on
log_lock_waits = hidup
log_replication_commands = hidup
log_temp_files = 0
log_timezone = 'Eropah/Moscow'

Pada DBMS PostgreSQL dengan parameter 1 CPU, 2,8 GHz, 2 GB RAM, 40 GB HDD, kami menjalankan tiga ujian beban menggunakan arahan:

$ pgbench -p 3389 -U postgres -i -s 150 benchmark
$ pgbench -p 3389 -U postgres -c 50 -j 2 -P 60 -T 600 benchmark
$ pgbench -p 3389 -U postgres -c 150 -j 2 -P 60 -T 600 benchmark

Keputusan ujian:

Tiada pembalakan
Dengan pembalakan

Jumlah masa pengisian pangkalan data
43,74 sec
53,23 sec

Ram
24%
40%

CPU
72%
91%

Ujian 1 (50 sambungan)

Bilangan transaksi dalam 10 minit
74169
32445

Urus niaga/saat
123
54

Latensi Purata
405 ms
925 ms

Ujian 2 (150 sambungan dengan 100 kemungkinan)

Bilangan transaksi dalam 10 minit
81727
31429

Urus niaga/saat
136
52

Latensi Purata
550 ms
1432 ms

Mengenai saiz

Saiz DB
2251 MB
2262 MB

Saiz log pangkalan data
0 MB
4587 MB

Intinya: audit penuh tidak begitu baik. Data daripada audit akan sama besar dengan data dalam pangkalan data itu sendiri, atau lebih. Jumlah pengelogan yang dijana semasa bekerja dengan DBMS adalah masalah biasa dalam pengeluaran.

Mari lihat parameter lain:

  • Kelajuan tidak banyak berubah: tanpa log - 43,74 saat, dengan log - 53,23 saat.
  • Prestasi RAM dan CPU akan terjejas, kerana anda perlu menjana fail audit. Ini juga ketara dalam produktiviti.

Apabila bilangan sambungan bertambah, secara semula jadi, prestasi akan merosot sedikit.

Dalam syarikat yang mempunyai audit adalah lebih sukar:

  • terdapat banyak data;
  • pengauditan diperlukan bukan sahaja melalui syslog dalam SIEM, tetapi juga dalam fail: jika sesuatu berlaku kepada syslog, mesti ada fail yang berdekatan dengan pangkalan data di mana data disimpan;
  • untuk pengauditan, rak berasingan diperlukan supaya tidak membazir pada cakera I/O, kerana ia mengambil banyak ruang;
  • Ia berlaku bahawa pekerja keselamatan maklumat memerlukan piawaian GOST di mana-mana, mereka memerlukan pengenalan negeri.

Mengehadkan akses kepada data

Mari kita lihat teknologi yang digunakan untuk melindungi data dan mengaksesnya dalam DBMS komersial dan sumber terbuka.

Apa yang biasanya anda boleh gunakan:

  1. Penyulitan dan pengeliruan prosedur dan fungsi (Pembungkusan) - iaitu alat dan utiliti berasingan yang menjadikan kod boleh dibaca tidak boleh dibaca. Benar, maka ia tidak boleh diubah atau difaktorkan semula. Pendekatan ini kadangkala diperlukan sekurang-kurangnya pada sisi DBMS - logik sekatan lesen atau logik kebenaran disulitkan tepat pada tahap prosedur dan fungsi.
  2. Mengehadkan keterlihatan data mengikut baris (RLS) ialah apabila pengguna yang berbeza melihat satu jadual, tetapi komposisi baris yang berbeza di dalamnya, iaitu sesuatu tidak boleh ditunjukkan kepada seseorang di peringkat baris.
  3. Mengedit data yang dipaparkan (Masking) ialah apabila pengguna dalam satu lajur jadual melihat sama ada data atau hanya asterisk, iaitu bagi sesetengah pengguna maklumat akan ditutup. Teknologi ini menentukan pengguna mana yang ditunjukkan berdasarkan tahap akses mereka.
  4. Keselamatan DBA/Aplikasi Kawalan capaian DBA/DBA adalah, sebaliknya, mengenai menyekat akses kepada DBMS itu sendiri, iaitu, pekerja keselamatan maklumat boleh dipisahkan daripada pentadbir pangkalan data dan pentadbir aplikasi. Terdapat beberapa teknologi sedemikian dalam sumber terbuka, tetapi terdapat banyak daripadanya dalam DBMS komersial. Mereka diperlukan apabila terdapat ramai pengguna yang mempunyai akses kepada pelayan itu sendiri.
  5. Mengehadkan akses kepada fail pada peringkat sistem fail. Anda boleh memberikan hak dan keistimewaan akses kepada direktori supaya setiap pentadbir mempunyai akses hanya kepada data yang diperlukan.
  6. Akses mandatori dan pembersihan memori - teknologi ini jarang digunakan.
  7. Penyulitan hujung ke hujung terus daripada DBMS ialah penyulitan sisi klien dengan pengurusan kunci di bahagian pelayan.
  8. Penyulitan data. Sebagai contoh, penyulitan kolumnar ialah apabila anda menggunakan mekanisme yang menyulitkan satu lajur pangkalan data.

Bagaimanakah ini mempengaruhi prestasi DBMS?

Mari lihat contoh penyulitan kolumnar dalam PostgreSQL. Terdapat modul pgcrypto, ia membolehkan anda menyimpan medan terpilih dalam bentuk yang disulitkan. Ini berguna apabila hanya beberapa data yang berharga. Untuk membaca medan yang disulitkan, pelanggan menghantar kunci penyahsulitan, pelayan menyahsulit data dan mengembalikannya kepada klien. Tanpa kunci, tiada siapa boleh melakukan apa-apa dengan data anda.

Mari uji dengan pgcrypto. Mari buat jadual dengan data yang disulitkan dan data biasa. Di bawah adalah arahan untuk membuat jadual, di baris pertama terdapat arahan yang berguna - mencipta sambungan itu sendiri dengan pendaftaran DBMS:

CREATE EXTENSION pgcrypto;
CREATE TABLE t1 (id integer, text1 text, text2 text);
CREATE TABLE t2 (id integer, text1 bytea, text2 bytea);
INSERT INTO t1 (id, text1, text2)
VALUES (generate_series(1,10000000), generate_series(1,10000000)::text, generate_series(1,10000000)::text);
INSERT INTO t2 (id, text1, text2) VALUES (
generate_series(1,10000000),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'),
encrypt(cast(generate_series(1,10000000) AS text)::bytea, 'key'::bytea, 'bf'));

Seterusnya, mari cuba buat sampel data dari setiap jadual dan lihat pemasaan pelaksanaan.

Memilih daripada jadual tanpa fungsi penyulitan:

psql -c "timing" -c "select * from t1 limit 1000;" "host=192.168.220.129 dbname=taskdb
user=postgres sslmode=disable" > 1.txt

Jam randik dihidupkan.

  id | teks1 | teks2
——+——-+——-
1 | 1 | 1
2 | 2 | 2
3 | 3 | 3
...
997 | 997 | 997
998 | 998 | 998
999 | 999 | 999
1000 | 1000 | 1000
(1000 baris)

Masa: 1,386 ms

Pemilihan daripada jadual dengan fungsi penyulitan:

psql -c "timing" -c "select id, decrypt(text1, 'key'::bytea, 'bf'),
decrypt(text2, 'key'::bytea, 'bf') from t2 limit 1000;"
"host=192.168.220.129 dbname=taskdb user=postgres sslmode=disable" > 2.txt

Jam randik dihidupkan.

  id | nyahsulit | menyahsulit
——+—————+————
1 | x31 | x31
2 | x32 | x32
3 | x33 | x33
...
999 | x393939 | x393939
1000 | x31303030 | x31303030
(1000 baris)

Masa: 50,203 ms

Keputusan ujian:

 
Tanpa penyulitan
Pgcrypto (nyahsulit)

Contoh 1000 baris
1,386 ms
50,203 ms

CPU
15%
35%

Ram
 
+ 5%

Penyulitan mempunyai kesan besar terhadap prestasi. Ia dapat dilihat bahawa pemasaan telah meningkat, kerana operasi penyahsulitan data yang disulitkan (dan penyahsulitan biasanya masih dibungkus dalam logik anda) memerlukan sumber yang ketara. Iaitu, idea untuk menyulitkan semua lajur yang mengandungi beberapa data penuh dengan penurunan prestasi.

Walau bagaimanapun, penyulitan bukan peluru perak yang menyelesaikan semua masalah. Data yang dinyahsulit dan kunci penyahsulitan semasa proses menyahsulit dan menghantar data terletak pada pelayan. Oleh itu, kunci boleh dipintas oleh seseorang yang mempunyai akses penuh kepada pelayan pangkalan data, seperti pentadbir sistem.

Apabila terdapat satu kunci untuk keseluruhan lajur untuk semua pengguna (walaupun bukan untuk semua, tetapi untuk pelanggan set terhad), ini tidak selalunya baik dan betul. Itulah sebabnya mereka mula melakukan penyulitan hujung ke hujung, dalam DBMS mereka mula mempertimbangkan pilihan untuk menyulitkan data pada sisi klien dan pelayan, dan storan peti besi kunci yang sama muncul - produk berasingan yang menyediakan pengurusan utama pada DBMS sebelah.

Keselamatan dan DBMS: perkara yang anda perlu ingat apabila memilih alat keselamatan
Contoh penyulitan sedemikian dalam MongoDB

Ciri keselamatan dalam DBMS komersial dan sumber terbuka

Fungsi
Jenis
Dasar Kata Laluan
Audit
Melindungi kod sumber prosedur dan fungsi
RLS
Penyulitan

Oracle
komersial
+
+
+
+
+

MsSql
komersial
+
+
+
+
+

Jatoba
komersial
+
+
+
+
sambungan

PostgreSQL
percuma
sambungan
sambungan
-
+
sambungan

MongoDb
percuma
-
+
-
-
Tersedia dalam MongoDB Enterprise sahaja

Jadual masih jauh dari lengkap, tetapi keadaannya ialah: dalam produk komersial, masalah keselamatan telah diselesaikan untuk masa yang lama, dalam sumber terbuka, sebagai peraturan, beberapa jenis alat tambah digunakan untuk keselamatan, banyak fungsi hilang , kadangkala anda perlu menambah sesuatu. Sebagai contoh, dasar kata laluan - PostgreSQL mempunyai banyak sambungan yang berbeza (1, 2, 3, 4, 5), yang melaksanakan dasar kata laluan, tetapi, pada pendapat saya, tiada satu pun daripadanya meliputi semua keperluan segmen korporat domestik.

Perkara yang perlu dilakukan jika anda tidak mempunyai apa yang anda perlukan di mana-mana sahaja? Sebagai contoh, anda ingin menggunakan DBMS khusus yang tidak mempunyai fungsi yang diperlukan oleh pelanggan.

Kemudian anda boleh menggunakan penyelesaian pihak ketiga yang berfungsi dengan DBMS yang berbeza, contohnya, Crypto DB atau Garda DB. Jika kita bercakap tentang penyelesaian dari segmen domestik, maka mereka tahu tentang GOST lebih baik daripada dalam sumber terbuka.

Pilihan kedua ialah menulis apa yang anda perlukan sendiri, melaksanakan akses data dan penyulitan dalam aplikasi pada peringkat prosedur. Benar, ia akan menjadi lebih sukar dengan GOST. Tetapi secara umum, anda boleh menyembunyikan data seperti yang diperlukan, memasukkannya ke dalam DBMS, kemudian mendapatkannya dan menyahsulitnya seperti yang diperlukan, betul-betul di peringkat aplikasi. Pada masa yang sama, segera fikirkan tentang bagaimana anda akan melindungi algoritma aplikasi ini. Pada pendapat kami, ini harus dilakukan di peringkat DBMS, kerana ia akan berfungsi lebih cepat.

Laporan ini pertama kali dibentangkan di @Pertemuan Pangkalan Data oleh Mail.ru Cloud Solutions. Tengok video persembahan lain dan melanggan pengumuman acara di Telegram Sekitar Kubernetes di Mail.ru Group.

Apa lagi yang perlu dibaca mengenai topik tersebut:

  1. Lebih daripada Ceph: Storan blok awan MCS.
  2. Bagaimana untuk memilih pangkalan data untuk projek supaya anda tidak perlu memilih lagi.

Sumber: www.habr.com

Tambah komen