---
title: "Cách bảo mật MongoDB trên Ubuntu 20.04"
description: "Cách bảo mật MongoDB trên Ubuntu 20.04"
url: https://cloudfly.vn/techblog/cach-bao-mat-mongodb-tren-ubuntu-2004
image: https://media.cloudfly.vn/posts/cach-bao-mat-MongoDB-tren-buntu-20.04.png
---

# Cách bảo mật MongoDB trên Ubuntu 20.04

## Giới thiệu

MongoDB là một document database được sử dụng trong nhiều ứng dụng web hiện đại. Nó được phân loại là NoSQL database, vì nó không dựa vào cấu trúc cơ sở dữ liệu quan hệ dựa trên bảng truyền thống. Thay vào đó, nó sử dụng các tài liệu giống như JSON với các lược đồ động (dynamic schemas).

MongoDB không bật xác thực theo mặc định, nghĩa là bất kỳ người dùng nào có quyền truy cập vào máy chủ nơi cơ sở dữ liệu được cài đặt đều có thể thêm và xóa dữ liệu mà không bị hạn chế. Để bảo vệ lỗ hổng này, bài viết này sẽ hướng dẫn bạn cách tạo người dùng quản trị và kích hoạt xác thực. Sau đó, bạn sẽ kiểm tra để xác nhận rằng chỉ người dùng quản trị này mới có quyền truy cập vào cơ sở dữ liệu.

## Điều kiện tiên quyết

Để hoàn thành hướng dẫn này, bạn sẽ cần những điều sau đây:

* Một máy chủ chạy Ubuntu 20.04. Máy chủ này phải có non-root administrative user và tường lửa được thiết lập cấu hình bằng UFW. Thiết lập điều này bằng cách làm theo hướng dẫn thiết lập máy chủ ban đầu của chúng tôi cho Ubuntu 20.04.
* MongoDB được cài đặt trên máy chủ của bạn. Hướng dẫn này đã được xác thực bằng MongoDB phiên bản <^>4.4<^>, mặc dù nó thường hoạt động với các phiên bản MongoDB cũ hơn. Để cài đặt Mongo trên máy chủ của bạn, hãy làm theo hướng dẫn của chúng tôi về Cách cài đặt MongoDB trên Ubuntu 20.04.

## Bước 1 — Thêm Administrative User

Kể từ khi phát hành phiên bản <^>3.0<^>, MongoDB daemon được thiết lập cấu hình để chỉ chấp nhận các kết nối từ Unix socket cục bộ và nó không tự động mở ra Internet rộng hơn. Tuy nhiên, xác thực vẫn bị tắt theo mặc định. Điều này có nghĩa là bất kỳ người dùng nào có quyền truy cập vào máy chủ cài đặt MongoDB cũng có quyền truy cập đầy đủ vào cơ sở dữ liệu.

Bước đầu tiên để bảo vệ lỗ hổng này, bạn sẽ tạo một người dùng quản trị (administrative user). Sau đó, bạn sẽ bật xác thực và kết nối với tư cách người dùng quản trị này để truy cập cơ sở dữ liệu.

Để thêm người dùng quản trị, trước tiên bạn phải kết nối với Mongo shell. Vì xác thực bị tắt nên bạn có thể làm như vậy bằng lệnh `mongo` mà không có bất kỳ tùy chọn nào khác:
```command
mongo
```

Sẽ có một số đầu ra phía trên Mongo shell prompt. Bởi vì bạn chưa kích hoạt xác thực, điều này sẽ bao gồm một cảnh báo rằng kiểm soát truy cập không được kích hoạt cho cơ sở dữ liệu, và quyền truy cập đọc và ghi vào dữ liệu cũng như cấu hình của cơ sở dữ liệu không bị hạn chế:
```
[secondary_label Output]
MongoDB shell version v<^>4.4.0<^>

 . . . 

2020-06-09T13:26:51.391+0000 I  CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2020-06-09T13:26:51.391+0000 I  CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.

 . . .

> 
```

Những cảnh báo này sẽ biến mất sau khi bạn kích hoạt xác thực, nhưng hiện tại chúng có nghĩa là bất kỳ ai có thể truy cập máy chủ Ubuntu của bạn cũng có thể kiểm soát cơ sở dữ liệu của bạn.

Để minh họa, hãy chạy lệnh `show dbs` của Mongo:
```custom_prefix(>)
show dbs
```

Lệnh này trả về danh sách mọi cơ sở dữ liệu trên máy chủ. Tuy nhiên, khi bật xác thực, danh sách sẽ thay đổi dựa trên vai trò của Mongo user hoặc mức độ truy cập của nó đối với một số cơ sở dữ liệu nhất định. Tuy nhiên, vì xác thực bị vô hiệu hóa nên nó sẽ trả về mọi cơ sở dữ liệu hiện có trên hệ thống mà không bị hạn chế:
```
[secondary_label Output]
admin   0.000GB
config  0.000GB
local   0.000GB
```

Trong kết quả ví dụ này, chỉ có cơ sở dữ liệu mặc định xuất hiện. Tuy nhiên, nếu bạn có bất kỳ cơ sở dữ liệu nào chứa dữ liệu nhạy cảm trên hệ thống của mình, bất kỳ người dùng nào cũng có thể tìm thấy chúng bằng lệnh này.

Là một phần của việc giảm thiểu lỗ hổng này, bước này tập trung vào việc thêm người dùng quản trị. Để thực hiện việc này, trước tiên bạn phải kết nối với cơ sở dữ liệu `admin`. Đây là nơi lưu trữ thông tin về người dùng, như tên người dùng, mật khẩu và vai trò của họ:
```custom_prefix(>)
use admin
```

```
[secondary_label Output]
switched to db admin
```

MongoDB được cài đặt sẵn một số phương thức JavaScript-based shell mà bạn có thể sử dụng để quản lý cơ sở dữ liệu của mình. Một trong số đó, phương thức `db.createUser`, được sử dụng để tạo người dùng mới trên cơ sở dữ liệu mà phương thức này được chạy.

Bắt đầu phương thức `db.createUser`:
```custom_prefix(>)
db.createUser(
```

Phương pháp này yêu cầu bạn chỉ định tên người dùng và mật khẩu cho user, cũng như bất kỳ vai trò nào bạn muốn người dùng có. Nhớ lại rằng MongoDB lưu trữ dữ liệu của nó trong các tài liệu giống như JSON. Như vậy, khi bạn tạo một người dùng mới, tất cả những gì bạn đang làm là tạo một tài liệu để chứa dữ liệu người dùng thích hợp dưới dạng các trường riêng lẻ.

Cũng như đối tượng trong JSON, tài liệu trong MongoDB bắt đầu và kết thúc bằng dấu ngoặc nhọn (`{` và `}`). Để bắt đầu thêm người dùng, hãy nhập dấu ngoặc nhọn mở:

<$>[note]
**Lưu ý:** Mongo sẽ không đăng ký phương thức `db.createUser` là hoàn tất cho đến khi bạn nhập dấu ngoặc đơn đóng. Cho đến khi bạn làm như vậy, lời nhắc sẽ thay đổi từ dấu lớn hơn (`>`) thành dấu chấm lửng (`...`).
<$>

```custom_prefix(...)
{
```

Tiếp theo, nhập trường `user:` với tên người dùng bạn muốn làm giá trị trong dấu ngoặc kép theo sau là dấu phẩy. Ví dụ dưới đây chỉ định tên người dùng **AdminSammy**, nhưng bạn có thể nhập bất kỳ tên người dùng nào bạn muốn:
```custom_prefix(...)
user: "<^>AdminSammy<^>",
```

Tiếp theo, nhập trường `pwd` với phương thức `passwordPrompt()` làm giá trị. Khi bạn thực thi phương thức `db.createUser`, phương thức `passwordPrompt()` sẽ nhắc bạn nhập mật khẩu của mình. Cách này an toàn hơn cách khác, đó là nhập mật khẩu của bạn ở dạng văn bản rõ ràng như bạn đã làm với tên người dùng của mình.

<$>[note]
**Lưu ý:** Phương thức `passwordPrompt()` chỉ tương thích với MongoDB phiên bản <^>4.2<^> trở lên. Nếu bạn đang sử dụng phiên bản MongoDB cũ hơn, thì bạn sẽ phải viết mật khẩu của mình ở dạng văn bản rõ ràng, tương tự như cách bạn viết tên người dùng của mình:
```custom_prefix(...)
pwd: "<^>password<^>",
```
<$>

Đảm bảo cũng theo dõi trường này bằng dấu phẩy:
```custom_prefix(...)
pwd: passwordPrompt(),
```

Sau đó, nhập các vai trò mà bạn muốn người dùng quản trị của mình có. Bởi vì bạn đang tạo một người dùng quản trị, tối thiểu bạn nên cấp cho họ vai trò `userAdminAnyDatabase` trên cơ sở dữ liệu `admin`. Điều này sẽ cho phép người dùng quản trị tạo và sửa đổi người dùng và vai trò mới. Vì người dùng quản trị có vai trò này trong cơ sở dữ liệu `admin`, điều này cũng sẽ cấp cho họ quyền truy cập superuser vào toàn bộ cluster.

Ngoài ra, ví dụ sau cũng cấp cho người dùng quản trị vai trò `readWriteAnyDatabase`. Điều này cấp cho người dùng quản trị khả năng đọc và sửa đổi dữ liệu trên bất kỳ cơ sở dữ liệu nào trong cụm ngoại trừ cơ sở dữ liệu `config` và `local`, phần lớn được sử dụng nội bộ:
```custom_prefix(...)
roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
```

Sau đó, nhập dấu ngoặc nhọn để biểu thị phần cuối của tài liệu:
```custom_prefix(...)
}
```

Sau đó, nhập dấu ngoặc đơn đóng để đóng và thực thi phương thức `db.createUser`:
```custom_prefix(...)
)
```

Tất cả cùng nhau, đây là phương thức `db.createUser` của bạn sẽ trông như thế nào:
```custom_prefix(>)
db.createUser(
... {
... user: "<^>AdminSammy<^>",
... pwd: passwordPrompt(),
... roles: [ { role: "userAdminAnyDatabase", db: "admin" }, "readWriteAnyDatabase" ]
... }
... )
```

Nếu cú pháp của mỗi dòng là chính xác, phương thức sẽ thực thi đúng cách và bạn sẽ được nhắc nhập mật khẩu:
```
[secondary_label Output]
Enter password:
```

Nhập một mật khẩu mạnh mà bạn chọn. Sau đó, bạn sẽ nhận được xác nhận rằng người dùng đã được thêm vào:
```
[secondary_label Output]
Successfully added user: {
	"user" : "<^>AdminSammy<^>",
	"roles" : [
		{
			"role" : "userAdminAnyDatabase",
			"db" : "admin"
		},
		"readWriteAnyDatabase"
	]
}
```

Sau đó, bạn có thể thoát ứng dụng khách MongoDB:
```custom_prefix(>)
exit
```

Tại thời điểm này, người dùng của bạn sẽ được phép nhập thông tin đăng nhập. Tuy nhiên, họ sẽ không bắt buộc phải làm như vậy cho đến khi bạn kích hoạt xác thực và khởi động lại MongoDB daemon.

## Bước 2 — Kích hoạt xác thực

Để bật xác thực, bạn phải chỉnh sửa `mongod.conf`, tệp cấu hình của MongoDB. Khi bạn kích hoạt nó và khởi động lại dịch vụ Mongo, người dùng vẫn có thể kết nối với cơ sở dữ liệu mà không cần xác thực. Tuy nhiên, họ sẽ không thể đọc hoặc sửa đổi bất kỳ dữ liệu nào cho đến khi họ cung cấp tên người dùng và mật khẩu chính xác.

Mở tệp cấu hình bằng trình soạn thảo văn bản ưa thích của bạn. Ở đây, chúng tôi sẽ sử dụng `nano`:
```command
sudo nano /etc/mongod.conf
```

Cuộn xuống để tìm phần `security` đã nhận xét:
```nginx
[label /etc/mongod.conf]
. . .
#security:

#operationProfiling:

. . .
```

Bỏ ghi chú dòng này bằng cách xóa dấu thăng (`#`):
```nginx
[label /etc/mongod.conf]
. . .
security:

#operationProfiling:

. . .
```

Sau đó, thêm tham số `authorization` và đặt thành `enabled`. Khi bạn hoàn thành, các dòng sẽ trông như thế này:
```nginx
[label /etc/mongod.conf]
. . .
security:
  <^>authorization: enabled<^>
. . . 
```

Lưu ý rằng dòng `security:` không có khoảng trắng ở đầu, trong khi dòng `authorization:` được thụt vào với hai khoảng trắng.

Sau khi thêm những dòng này, hãy lưu và đóng tệp. Nếu bạn đã sử dụng `nano` để mở tệp, hãy làm như vậy bằng cách nhấn `CTRL + X`, `Y`, rồi `ENTER`.

Sau đó khởi động lại daemon để những thay đổi mới này có hiệu lực:
```command
sudo systemctl restart mongod
```

Tiếp theo, hãy kiểm tra trạng thái của dịch vụ để đảm bảo rằng dịch vụ đã khởi động lại đúng cách:
```command
sudo systemctl status mongod
```

Nếu lệnh `restart` thành công, bạn sẽ nhận được đầu ra cho biết dịch vụ `mongod` đang hoạt động và mới được bắt đầu:
```
[secondary_label Output]
● mongod.service - MongoDB Database Server
     Loaded: loaded (/lib/systemd/system/mongod.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2020-06-09 22:06:20 UTC; 7s ago
       Docs: https://docs.mongodb.org/manual
   Main PID: 15370 (mongod)
     Memory: 170.1M
     CGroup: /system.slice/mongod.service
             └─15370 /usr/bin/mongod --config /etc/mongod.conf

Jun 09 22:06:20 <^>your_host<^> systemd[1]: Started MongoDB Database Server.
```

Sau khi xác minh rằng daemon đã được sao lưu và chạy, bạn có thể kiểm tra xem cài đặt xác thực mà bạn đã thêm có hoạt động như mong đợi hay không.

## Bước 3 — Kiểm tra cài đặt xác thực

Để bắt đầu kiểm tra xem các yêu cầu xác thực mà bạn đã thêm ở bước trước có hoạt động chính xác hay không, hãy bắt đầu bằng cách kết nối mà không chỉ định bất kỳ thông tin đăng nhập nào để xác minh rằng hành động của bạn thực sự bị hạn chế:
```command
mongo
```

Bây giờ bạn đã kích hoạt xác thực, không có cảnh báo nào bạn gặp phải trước đây sẽ xuất hiện:
```
[secondary_label Output]
MongoDB shell version v<^>4.4.0<^>
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("5d50ed96-f7e1-493a-b4da-076067b2d898") }
MongoDB server version: <^>4.4.0<^>
> 
```

Xác nhận xem quyền truy cập của bạn có bị hạn chế hay không bằng cách chạy lại lệnh `show dbs`:
```custom_prefix(>)
show dbs
```

Nhớ lại từ Bước 1 rằng có ít nhất một vài cơ sở dữ liệu mặc định trên máy chủ của bạn. Tuy nhiên, trong trường hợp này, lệnh sẽ không có bất kỳ đầu ra nào vì bạn chưa được xác thực là người dùng có đặc quyền.

Vì lệnh này không trả về bất kỳ thông tin nào nên có thể nói rằng cài đặt xác thực đang hoạt động như mong đợi. Bạn cũng sẽ không thể tạo người dùng hoặc thực hiện các tác vụ đặc quyền khác mà không cần xác thực trước.

Hãy tiếp tục và thoát khỏi MongoDB shell:

<$>[note]
**Lưu ý:** Thay vì chạy lệnh `exit` sau đây như bạn đã làm trước đó trong Bước 1, một cách khác để đóng shell là chỉ cần nhấn `CTRL + C`.
<$>

```custom_prefix(>)
exit
```

Tiếp theo, hãy đảm bảo rằng người dùng quản trị của bạn có thể xác thực đúng cách bằng cách chạy lệnh `mongo` sau để kết nối với tư cách là người dùng này. Lệnh này bao gồm cờ `-u`, đứng trước tên của người dùng mà bạn muốn kết nối. Đảm bảo thay thế **AdminSammy** bằng tên người dùng của administrative user của riêng bạn. Nó cũng bao gồm cờ `-p`, cờ này sẽ nhắc bạn nhập mật khẩu của người dùng và chỉ định `admin` làm cơ sở dữ liệu xác thực nơi tên người dùng được chỉ định được tạo:
```command
mongo -u <^>AdminSammy<^> -p --authenticationDatabase admin
```

Nhập mật khẩu của người dùng khi được nhắc, sau đó bạn sẽ được đưa vào shell. Khi đó, hãy thử phát lại lệnh `show dbs`:
```custom_prefix(>)
show dbs
```

Lần này, vì bạn đã xác thực đúng cách, lệnh sẽ trả về thành công danh sách tất cả các cơ sở dữ liệu hiện có trên máy chủ:
```
[secondary_label Output]
admin   0.000GB
config  0.000GB
local   0.000GB
```

Điều này xác nhận rằng xác thực đã được kích hoạt thành công.

## Kết luận

Bằng cách hoàn thành hướng dẫn này, bạn đã thiết lập một administrative MongoDB user mà bạn có thể sử dụng để tạo và sửa đổi những người dùng và vai trò mới, đồng thời quản lý phiên bản MongoDB của bạn. Bạn cũng đã thiết lập cấu hình phiên bản MongoDB của mình để yêu cầu người dùng xác thực bằng tên người dùng và mật khẩu hợp lệ trước khi họ có thể tương tác với bất kỳ dữ liệu nào.

Để biết thêm thông tin về cách quản lý MongoDB users, hãy xem tài liệu chính thức về chủ đề này. Bạn cũng có thể muốn tìm hiểu thêm về cách xác thực hoạt động trên MongoDB.

Ngoài ra, nếu bạn dự định tương tác với phiên bản MongoDB của mình từ xa, bạn có thể làm theo hướng dẫn của chúng tôi về Cách thiết lập cấu hình quyền truy cập từ xa cho MongoDB trên Ubuntu 20.04.
