mTLS và Trusted CA trong Service Mesh
Trong Service Mesh, Trusted CA (Certificate Authority) được sử dụng để cấp phát và quản lý chứng chỉ số cho các dịch vụ trong hệ thống. Một Trusted CA đảm bảo rằng các chứng chỉ số này được tin cậy, giúp đảm bảo tính bảo mật và xác thực giữa các dịch vụ trong Service Mesh. Cụ thể:
Xác thực (Authentication): Trusted CA cấp các chứng chỉ số cho các dịch vụ để đảm bảo rằng mỗi dịch vụ có thể xác thực danh tính của mình với các dịch vụ khác. Khi một dịch vụ gửi yêu cầu tới dịch vụ khác, chứng chỉ số được sử dụng để xác thực rằng yêu cầu đó đến từ một nguồn tin cậy.
Mã hóa (Encryption): Các chứng chỉ số được cấp bởi Trusted CA cũng hỗ trợ mã hóa dữ liệu truyền qua lại giữa các dịch vụ. Điều này đảm bảo rằng dữ liệu không bị đọc lén hay giả mạo trong quá trình truyền tải.
Toàn vẹn (Integrity): Trusted CA giúp đảm bảo rằng dữ liệu không bị thay đổi trong quá trình truyền tải. Các chứng chỉ số cung cấp cơ chế để xác minh tính toàn vẹn của dữ liệu.
Tin cậy (Trust): Bằng cách sử dụng một CA đáng tin cậy, các dịch vụ trong Service Mesh có thể tin tưởng rằng các chứng chỉ mà chúng nhận được từ các dịch vụ khác là hợp lệ và không bị giả mạo.
Để thiết lập mTLS (mutual TLS) giữa hai service A và B sử dụng Trusted CA, quy trình bắt tay truyền dữ liệu có thể được mô tả như sau:
Cấp phát chứng chỉ:
Trusted CA cấp phát chứng chỉ số và khóa bí mật cho cả service A và service B.
Mỗi dịch vụ sẽ có một chứng chỉ số (certificate) và một khóa bí mật (private key).
Thiết lập kết nối:
ClientHello: Service A (client) gửi một thông điệp ClientHello tới service B (server) để bắt đầu kết nối TLS. Thông điệp này chứa các thông tin về các phiên bản TLS và các bộ mật mã mà service A hỗ trợ.
ServerHello: Service B trả lời bằng thông điệp ServerHello, trong đó chứa các thông tin về phiên bản TLS và bộ mật mã mà service B chọn sử dụng cho kết nối này.
Trao đổi chứng chỉ:
Server Certificate: Service B gửi chứng chỉ của mình (đã được ký bởi Trusted CA) tới service A. Service A sử dụng chứng chỉ của Trusted CA để xác thực chứng chỉ của service B.
Client Certificate: Service A gửi chứng chỉ của mình (đã được ký bởi Trusted CA) tới service B. Service B sử dụng chứng chỉ của Trusted CA để xác thực chứng chỉ của service A.
Xác thực lẫn nhau:
Xác thực service B: Service A kiểm tra chứng chỉ của service B để đảm bảo nó được ký bởi Trusted CA và chưa hết hạn.
Xác thực service A: Service B kiểm tra chứng chỉ của service A để đảm bảo nó được ký bởi Trusted CA và chưa hết hạn.
Trao đổi khóa:
Pre-Master Secret: Service A tạo ra một Pre-Master Secret, mã hóa nó bằng khóa công khai của service B (lấy từ chứng chỉ của service B), và gửi nó tới service B.
Master Secret: Cả hai dịch vụ sử dụng Pre-Master Secret để tính toán ra một Master Secret, sau đó sử dụng Master Secret này để tạo ra các khóa mã hóa phiên (session keys).
Thiết lập phiên mã hóa:
Finished Messages: Cả service A và service B đều gửi một thông điệp “Finished” để xác nhận rằng bắt tay TLS đã hoàn tất và rằng tất cả các thông điệp trước đó đã được trao đổi chính xác và không bị thay đổi.
Mã hóa phiên: Từ đây, tất cả dữ liệu trao đổi giữa service A và service B đều được mã hóa bằng khóa phiên được tạo ra từ Master Secret.
Truyền dữ liệu:
- Sau khi bắt tay TLS hoàn tất và kết nối bảo mật được thiết lập, cả hai dịch vụ có thể trao đổi dữ liệu một cách an toàn và mã hóa.
Tóm lại, quá trình bắt tay TLS giữa service A và service B thông qua Trusted CA đảm bảo rằng cả hai dịch vụ đều có thể xác thực lẫn nhau và thiết lập một kênh truyền dữ liệu an toàn và được mã hóa.
2. Triển khai hai service A và B
Chúng ta sẽ triển khai hai service đơn giản sử dụng NGINX và HTTPBin, mỗi service sẽ có một Pod riêng biệt.
Deployment và Service cho Service A (NGINX)
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
selector:
app: nginx
Deployment và Service cho Service B (HTTPBin)
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
labels:
app: httpbin
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
spec:
ports:
- port: 80
selector:
app: httpbin
3. Triển khai Service Mesh Policy cho mTLS
Trong Istio, chúng ta cần tạo các tài nguyên PeerAuthentication
và DestinationRule
để yêu cầu và thực thi mTLS giữa các dịch vụ.
PeerAuthentication cho mTLS
PeerAuthentication định nghĩa chính sách bảo mật cho các dịch vụ trong Mesh. Chúng ta sẽ yêu cầu mTLS giữa tất cả các dịch vụ.
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
DestinationRule để áp dụng mTLS
DestinationRule chỉ định cách thức Istio sẽ quản lý lưu lượng đi giữa các dịch vụ. Trong ví dụ này, chúng ta sẽ áp dụng mTLS cho các yêu cầu đến httpbin
.
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
namespace: default
spec:
host: httpbin
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
4. Triển khai VirtualService để định tuyến lưu lượng
VirtualService giúp định tuyến lưu lượng đến các dịch vụ trong Mesh. Ví dụ, chúng ta sẽ định tuyến lưu lượng HTTP đến httpbin
:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
namespace: default
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
port:
number: 80
5. Kiểm tra kết nối mTLS
Khi đã triển khai các dịch vụ và cấu hình mTLS, bạn có thể kiểm tra bằng cách gửi yêu cầu từ nginx
(Service A) đến httpbin
(Service B). Đảm bảo rằng mTLS được áp dụng và chỉ cho phép các dịch vụ trong Mesh kết nối với nhau.
Bạn có thể sử dụng công cụ curl
bên trong Pod của nginx
để gửi yêu cầu đến httpbin
:
kubectl exec -it <nginx-pod-name> -- curl http://httpbin:80/status/200
Nếu mTLS được thiết lập đúng cách, yêu cầu này sẽ thành công và trả về mã trạng thái 200 OK
.
6. Đảm bảo mTLS hoạt động
Bạn có thể kiểm tra mTLS bằng cách sử dụng Istio's Prometheus metrics hoặc các công cụ giám sát khác để xác nhận rằng mTLS đang được thực thi giữa các dịch vụ.
Trong Istio, có ba chế độ chính liên quan đến mTLS (mutual TLS) khi cấu hình bảo mật giữa các dịch vụ trong Service Mesh: PERMISSIVE
, ISTIO_MUTUAL
, và STRICT
. Mỗi chế độ được sử dụng trong các trường hợp khác nhau, nhằm điều chỉnh cách thức mã hóa và xác thực các kết nối giữa các dịch vụ.
1. PERMISSIVE
Mô tả: Chế độ này cho phép cả kết nối được mã hóa mTLS và không mã hóa. Điều này có nghĩa là nếu dịch vụ gửi yêu cầu có mTLS, nó sẽ được chấp nhận. Ngược lại, nếu yêu cầu không có mTLS (giao tiếp thuần túy HTTP), nó cũng sẽ được chấp nhận.
Trường hợp sử dụng:
PERMISSIVE
thường được sử dụng trong quá trình chuyển đổi dần dần từ các kết nối không bảo mật sang mTLS. Điều này cho phép một hệ thống dần dần áp dụng mTLS mà không làm gián đoạn các dịch vụ hiện tại.Tính năng:
Hỗ trợ cả mTLS và không mTLS.
Dễ dàng trong quá trình nâng cấp hệ thống.
Ví dụ PeerAuthentication với chế độ PERMISSIVE:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: PERMISSIVE
2. ISTIO_MUTUAL
Mô tả:
ISTIO_MUTUAL
là chế độ dành riêng cho Istio, nơi cả server và client đều sử dụng chứng chỉ do Istio quản lý để thực hiện mTLS. Istio sẽ tự động cấp và quản lý chứng chỉ này thông quaistiod
, và sử dụng nó để thiết lập kết nối mTLS giữa các dịch vụ. Chế độ này yêu cầu tất cả các kết nối phải sử dụng mTLS với chứng chỉ do Istio cấp phát.Trường hợp sử dụng:
ISTIO_MUTUAL
là chế độ được sử dụng khi bạn muốn triển khai mTLS một cách tự động với ít sự can thiệp thủ công, sử dụng các chứng chỉ được quản lý hoàn toàn bởi Istio.Tính năng:
Tự động quản lý chứng chỉ bởi Istio.
Chỉ sử dụng chứng chỉ từ Istio.
Ví dụ DestinationRule với chế độ ISTIO_MUTUAL:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: httpbin
namespace: default
spec:
host: httpbin
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
3. STRICT
Mô tả:
STRICT
là chế độ bảo mật cao nhất, yêu cầu tất cả các kết nối đến dịch vụ phải được mã hóa và xác thực bằng mTLS. Nếu một yêu cầu không sử dụng mTLS, kết nối sẽ bị từ chối. Chế độ này đảm bảo rằng tất cả dữ liệu trao đổi giữa các dịch vụ trong Mesh đều được mã hóa và bảo vệ chống lại các cuộc tấn công từ bên ngoài.Trường hợp sử dụng:
STRICT
thường được sử dụng trong các môi trường có yêu cầu bảo mật nghiêm ngặt, nơi mọi kết nối đều phải được mã hóa và xác thực. Đây là chế độ cuối cùng trong quá trình chuyển đổi sang mTLS sau khi các dịch vụ đã được cấu hình để hỗ trợ mTLS hoàn toàn.Tính năng:
Chỉ cho phép các kết nối được mã hóa mTLS.
Không cho phép giao tiếp không mã hóa.
Ví dụ PeerAuthentication với chế độ STRICT:
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: STRICT
So sánh các chế độ
Chế độ | Mô tả | Sử dụng mTLS | Không mã hóa (Plaintext) |
PERMISSIVE | Cho phép cả mTLS và không mTLS. | Có, nếu được hỗ trợ. | Có |
ISTIO_MUTUAL | Sử dụng mTLS với chứng chỉ được quản lý bởi Istio. | Bắt buộc | Không |
STRICT | Bắt buộc phải sử dụng mTLS cho tất cả các kết nối. | Bắt buộc | Không |
Tóm lại:
PERMISSIVE: Chuyển đổi dần dần, hỗ trợ cả mTLS và không mTLS.
ISTIO_MUTUAL: Sử dụng mTLS với chứng chỉ do Istio quản lý.
STRICT: Yêu cầu mTLS cho mọi kết nối, không cho phép giao tiếp không mã hóa.
Chọn chế độ tùy thuộc vào tình huống và yêu cầu bảo mật của hệ thống.