paint-brush
Ngoài đăng nhập: Triển khai ủy quyền chi tiết với ZITADELtừ tác giả@zitadel
3,959 lượt đọc
3,959 lượt đọc

Ngoài đăng nhập: Triển khai ủy quyền chi tiết với ZITADEL

từ tác giả ZITADEL20m2023/11/10
Read on Terminal Reader

dài quá đọc không nổi

Bài viết này đi sâu vào quá trình chuyển đổi từ kiểm soát truy cập dựa trên vai trò truyền thống sang bảo mật chi tiết hơn. ZITADEL tăng cường ủy quyền với các tính năng động và hỗ trợ tích hợp bên ngoài cho các nhu cầu phù hợp. Một ví dụ thực tế minh họa những nguyên tắc này trong thực tế. Đối với các nhà phát triển thực hành, bài viết đề cập đến cách triển khai mã đầy đủ bằng Python.
featured image - Ngoài đăng nhập: Triển khai ủy quyền chi tiết với ZITADEL
ZITADEL HackerNoon profile picture
0-item
1-item


Giới thiệu

Khi chúng ta hướng tới tư duy không tin cậy, hạn chế của các biện pháp bảo mật chi tiết như hệ thống RBAC truyền thống trở nên rõ ràng. Một phần thiết yếu của quá trình chuyển đổi sang mức độ tin cậy bằng 0 thường không được thảo luận là việc chuyển từ bảo mật chi tiết thô sang bảo mật chi tiết hơn.


Ủy quyền chi tiết giải quyết vấn đề này bằng cách truy cập dựa trên các thuộc tính như vai trò, hành động của người dùng và thậm chí cả bối cảnh như thời gian hoặc địa điểm và việc kiểm soát truy cập chi tiết như vậy là rất quan trọng đối với các ứng dụng hiện đại. Bài viết này thảo luận về cách ZITADEL đáp ứng nhu cầu về sự ủy quyền mang sắc thái như vậy.


Với các tính năng của ZITADEL như vai trò, siêu dữ liệu và hành động, người dùng có thể có được quyền kiểm soát truy cập rất chi tiết phù hợp với cài đặt không tin cậy. Ngoài ra, ZITADEL có thể hoạt động với các dịch vụ ủy quyền bên ngoài.

Cơ chế ủy quyền được cung cấp bởi ZITADEL

ZITADEL là một mã nguồn mở , giải pháp Quản lý quyền truy cập và nhận dạng (IAM) dựa trên nền tảng đám mây được viết bằng Go. ZITADEL có sẵn dưới dạng giải pháp SaaS và cũng là nguồn mở cho những ai đang tìm kiếm các tùy chọn tự lưu trữ, đảm bảo tính linh hoạt. Nó phục vụ cho cả trường hợp sử dụng B2C và B2B.


Mục tiêu chính của nó bao gồm cung cấp các tính năng chìa khóa trao tay để xác thực, ủy quyền, đăng nhập và đăng nhập một lần (SSO) đồng thời cho phép tùy chỉnh thông qua giao diện người dùng.


Nó đi kèm với một quy trình kiểm tra mở rộng để theo dõi tất cả các thay đổi, cho phép nhà phát triển mở rộng chức năng bằng mã (hành động) tùy chỉnh, hỗ trợ các tiêu chuẩn được công nhận rộng rãi như OIDC, OAuth, SAML và LDAP, nhấn mạnh tính dễ vận hành và khả năng mở rộng, đồng thời cung cấp các API toàn diện cho tích hợp đa năng.

Kiểm soát truy cập dựa trên vai trò (RBAC) và quyền truy cập được ủy quyền

ZITADEL sử dụng RBAC để quản lý quyền của người dùng, trong đó các quyền được gắn với các vai trò và người dùng được phân bổ các vai trò này. Điều này giúp đơn giản hóa việc quản lý quyền truy cập của người dùng dựa trên vai trò tổ chức của họ. Một tính năng bổ sung cho phép ủy quyền vai trò cho các tổ chức khác, tạo điều kiện chia sẻ quyền với các tổ chức bên ngoài.


Điều này đặc biệt có giá trị đối với các tổ chức được kết nối với nhau hoặc có thứ bậc.


Mặc dù các khả năng này cung cấp khả năng kiểm soát truy cập mạnh mẽ nhưng chúng có thể không đủ cho các nhu cầu ủy quyền phức tạp, do đó tầm quan trọng của việc khám phá ủy quyền chi tiết trong ZITADEL.

Tính năng hành động, siêu dữ liệu tùy chỉnh và xác nhận quyền sở hữu đối với kiểm soát truy cập dựa trên thuộc tính (ABAC)

ZITADEL tăng cường RBAC truyền thống bằng cách giới thiệu tính năng động của nó hành động tính năng kiểm soát truy cập dựa trên thuộc tính (ABAC). Không giống như RBAC cấp quyền truy cập dựa trên vai trò của người dùng, ABAC linh hoạt hơn, đánh giá các thuộc tính được liên kết với người dùng, hành động và tài nguyên trong các yêu cầu truy cập.


Với hành động của ZITADEL, các tập lệnh sau xác thực có thể được tạo để phân tích các thuộc tính người dùng cụ thể và chặn quyền truy cập khi cần thiết.


Các hành động cũng có thể thiết lập các xác nhận quyền sở hữu tùy chỉnh để tăng cường hệ thống ABAC, cho phép các mô hình ủy quyền nâng cao hạn chế quyền truy cập dựa trên các thuộc tính như vị trí, thời gian hoặc bất kỳ yếu tố có thể xác định nào.


ZITADEL cho phép quản trị viên hoặc nhà phát triển được phép thêm siêu dữ liệu tùy chỉnh cho người dùng và tổ chức, tăng cường khả năng kiểm soát truy cập chi tiết.


Nó hỗ trợ các khiếu nại tổng hợp bằng cách thu thập dữ liệu bổ sung từ các hệ thống bên ngoài như các công cụ CRM hoặc HR. ZITADEL cũng có thể quản lý các tài nguyên duy nhất, chẳng hạn như đơn đặt hàng vận chuyển hoặc thiết bị IoT và xác định quyền truy cập dựa trên các thuộc tính như Người dùng phụ, Vai trò, Xác nhận quyền sở hữu, IP, v.v.

Mở rộng khả năng hiện có của ZITADEL để kiểm soát truy cập chi tiết

Mặc dù có các tính năng toàn diện đi kèm với ZITADEL, nhưng có thể có những trường hợp cần có cách tiếp cận chi tiết hơn hoặc tùy chỉnh hơn.


Hiện tại, cách hiệu quả nhất để triển khai ủy quyền chi tiết trong ZITADEL là sử dụng logic ứng dụng tùy chỉnh cho các dự án nhỏ hơn hoặc cho các dự án quy mô lớn hơn, tận dụng công cụ có sẵn của bên thứ ba như Wart.dev , cerbos.dev , v.v.


Những công cụ này có thể tích hợp với ZITADEL, nâng cao hơn nữa khả năng ủy quyền chi tiết, sắc thái của bạn.

Một ví dụ thực tế

Giả sử có một Ứng dụng Phòng tin tức giả định trong một công ty truyền thông, ứng dụng này giao tiếp với API phụ trợ. Các nhà báo sử dụng nó để viết, trong khi các biên tập viên chỉnh sửa và xuất bản những bài viết này. API này, được viết bằng Python Flask trong ví dụ này, có các điểm cuối cụ thể và quyền truy cập vào các điểm cuối này tùy thuộc vào vai trò của người dùng và mức độ kinh nghiệm của họ. Các điểm cuối:


  • write_article : Chỉ dành cho nhà báo viết.


  • edit_article : Chỉ dành cho biên tập viên chỉnh sửa bài viết.


  • review_articles : Dành cho các nhà báo cấp cao và các biên tập viên trung cấp và cao cấp để đánh giá các bài viết.


  • publish_article : Dành cho các nhà báo trung cấp và cao cấp cũng như các biên tập viên cao cấp xuất bản. Trong nội bộ, API sử dụng JWT do ZITADEL cấp để kiểm tra xem ai đang đưa ra yêu cầu. Người dùng cần gửi JWT hợp lệ trong tiêu đề yêu cầu của họ. JWT này được lấy khi người dùng đăng nhập.


    JWT chứa thông tin về người dùng, như vai trò và trải nghiệm của họ. Thông tin này, có trong các xác nhận quyền sở hữu tùy chỉnh, là chìa khóa cho trường hợp sử dụng này. Phần phụ trợ quyết định xem người dùng có thể truy cập tài nguyên được yêu cầu hay không dựa trên thông tin này.

Logic ứng dụng

Sơ đồ 1: Tương tác của ủy quyền chi tiết ngoài đăng nhập



  • Giới thiệu người dùng : Trong quá trình giới thiệu người dùng, mỗi người dùng sẽ có một vai trò, ví dụ: journalist hoặc editor . Đây là chìa khóa vì nó quyết định ai sẽ có quyền truy cập gì trong quá trình thiết lập của chúng tôi. Quản lý Kinh nghiệm/Thâm niên: Bên cạnh các vai trò, trải nghiệm của người dùng (như junior , intermediatesenior trong ví dụ của chúng tôi) cũng được theo dõi. Nếu trải nghiệm của người dùng thay đổi, ZITADEL sẽ cập nhật trải nghiệm đó dưới dạng siêu dữ liệu. Nếu không có cấp độ kinh nghiệm nào được đề cập khi người dùng tham gia ZITADEL thì hệ thống sẽ chỉ coi đó là 'cấp dưới'.


  • Đăng nhập người dùng : Trước tiên người dùng phải đăng nhập để truy cập API. Sau khi đăng nhập thành công, ZITADEL sẽ trả lại mã thông báo chứa thông tin của người dùng.


  • Xác thực mã thông báo: Khi yêu cầu từ người dùng truy cập API, API sẽ xác thực mã thông báo bằng cách gọi điểm cuối xem xét nội bộ mã thông báo của ZITADEL. Mặc dù JWT có thể được xác thực cục bộ bằng JWKS, nhưng chúng tôi đã sử dụng phương pháp của ZITADEL để kiểm tra mã thông báo nhằm bảo mật tốt hơn và kiểm tra mã thông báo tức thì. Bằng cách này, chúng tôi có thể thu hồi mã thông báo ngay lập tức, quản lý chúng từ một nơi và gặp ít vấn đề bảo mật hơn. Nó giữ cho các biện pháp kiểm soát đăng nhập và truy cập API của chúng tôi luôn mạnh mẽ và cập nhật với máy chủ.


  • Kiểm soát truy cập chi tiết: Ứng dụng chịu trách nhiệm cấp quyền truy cập vào tài nguyên dựa trên vai trò và mức độ kinh nghiệm của người dùng. Nó sử dụng danh sách kiểm soát truy cập được xác định trước để ánh xạ từng điểm cuối tài nguyên tới vai trò của người dùng và cấp độ kinh nghiệm được phép truy cập chúng. Danh sách này đóng vai trò là sách quy tắc để cấp hoặc từ chối quyền truy cập vào tài nguyên.


  • Tách biệt các mối quan tâm : Trong thiết kế API này, người ta đặc biệt chú ý đến việc đảm bảo rằng logic nghiệp vụ và các quy tắc kiểm soát truy cập được tách biệt rõ ràng. Điều này rất quan trọng đối với khả năng bảo trì và khả năng mở rộng của ứng dụng. Bằng cách tách biệt logic kinh doanh và quy tắc truy cập, chúng tôi có được thiết kế mô-đun rõ ràng hơn.


    Điều này cho phép chúng tôi cập nhật các hoạt động kinh doanh và quy tắc truy cập mà không ảnh hưởng lẫn nhau. Điều này làm tăng khả năng bảo trì của mã và giúp quản lý dễ dàng hơn khi ứng dụng mở rộng quy mô.


    Ngoài ra, thiết kế này giúp hệ thống an toàn hơn vì các quy tắc truy cập được tách khỏi logic nghiệp vụ chính, giảm nguy cơ vô tình tạo ra các lỗ hổng bảo mật khi sửa đổi logic nghiệp vụ.

Thiết lập ZITADEL

1. Tạo tổ chức Media House, dự án phòng tin tức và API bài viết

  1. Tạo tổ chức Media House, đi tới Dự án và tạo một dự án mới có tên là Phòng tin tức.



  2. Trong dự án Newsroom, nhấp vào nút Mới để tạo ứng dụng mới.



  1. Thêm tên và chọn loại API .



  1. Chọn Cơ bản làm phương thức xác thực và nhấp vào Tiếp tục .



  1. Bây giờ hãy xem lại cấu hình của bạn và nhấp vào Tạo .



  1. Bây giờ bạn sẽ thấy Client ID của API và Client Secret . Sao chép chúng và lưu chúng. Nhấp vào Đóng .



  1. Khi bạn nhấp vào các URL ở bên trái, bạn sẽ thấy các URL OIDC có liên quan. Ghi lại URL của nhà phát hành , token_endpointintrospection_endpoint .



2. Tạo vai trò trong Dự án Phòng tin tức

  1. Ngoài ra, hãy ghi lại ID tài nguyên của dự án của bạn (đi tới dự án và sao chép ID tài nguyên)



  1. Chọn hộp kiểm Xác nhận vai trò trên Xác thực trên bảng thông tin dự án và nhấp vào Lưu .



  1. Đi tới Vai trò (từ menu bên trái) và nhấp vào Mới để thêm vai trò mới.



  1. Nhập vai trò biên tập viên , nhà báo như hình bên dưới rồi nhấn Lưu .



  1. Bây giờ bạn sẽ thấy các vai trò đã tạo.



3. Tạo người dùng trong Dự án Phòng tin tức

  1. Chuyển đến tab Người dùng trong tổ chức của bạn như hiển thị bên dưới và chuyển đến tab Người dùng dịch vụ . Chúng tôi sẽ tạo người dùng dịch vụ trong bản demo này. Để thêm người dùng dịch vụ, hãy nhấp vào nút Mới .


    Tạo người dùng dịch vụ


  2. Tiếp theo, thêm thông tin chi tiết về người dùng dịch vụ, chọn JWT cho Access Token Type và nhấp vào Create .


    Tạo người dùng dịch vụ


  3. Nhấp vào nút Hành động ở góc trên cùng bên phải. Chọn Tạo bí mật khách hàng từ menu thả xuống.




  4. Sao chép ID khách hàng và Bí mật khách hàng của bạn. Nhấp vào Đóng .



  5. Bây giờ, bạn có một người dùng dịch vụ cùng với thông tin xác thực khách hàng của họ.

4. Thêm ủy quyền cho người dùng

  1. Chuyển đến Ủy quyền . Bấm vào Mới .


  2. Chọn người dùng và dự án cần tạo ủy quyền. Nhấp vào Tiếp tục .



  3. Bạn có thể chọn một vai trò ở đây. Chọn vai trò nhà báo cho người dùng hiện tại. Nhấp vào Lưu .


    Thêm ủy quyền


  4. Bạn có thể thấy người dùng dịch vụ Lois Lane hiện có vai trò là nhà báo trong dự án Newsroom .



5. Thêm siêu dữ liệu cho người dùng

Bây giờ, hãy thêm siêu dữ liệu vào hồ sơ người dùng để cho biết cấp độ thâm niên của họ. Sử dụng 'experience_level' làm khóa và đối với giá trị của nó, hãy chọn từ 'cấp cơ sở', 'trung cấp' hoặc 'cấp cao'.


Mặc dù chúng tôi thường có thể cho rằng siêu dữ liệu này được đặt thông qua lệnh gọi API do ứng dụng HR thực hiện, nhưng để đơn giản và dễ hiểu, chúng tôi sẽ đặt siêu dữ liệu trực tiếp trong bảng điều khiển.


  1. Đi tới Siêu dữ liệu . Nhấp vào Chỉnh sửa .



  2. Cung cấp experience_level làm khóa và cấp cao làm giá trị. Nhấp vào biểu tượng lưu và nhấp vào nút Đóng .



  3. Người dùng hiện có siêu dữ liệu cần thiết được liên kết với tài khoản của họ.



  4. Bạn cũng có thể thêm một số người dùng dịch vụ khác với các vai trò và cấp độ trải nghiệm khác nhau (sử dụng siêu dữ liệu) để kiểm tra bản demo bằng các bước trước đó.


6. Tạo hành động để nắm bắt vai trò và siêu dữ liệu trong xác nhận quyền sở hữu tùy chỉnh

1. Nhấp vào Hành động . Bấm vào Mới để tạo hành động mới.



2. Trong phần Tạo hành động , đặt tên cho hành động giống với tên hàm, tức là, gánRoleAndExperienceClaims. Trong trường tập lệnh, sao chép/dán đoạn mã sau rồi nhấp vào Thêm .



 function assignRoleAndExperienceClaims(ctx, api) { // Check if grants and metadata exist if (!ctx.v1.user.grants || !ctx.v1.claims['urn:zitadel:iam:user:metadata']) { return; } // Decode experience level from Base64 - metadata is Base64 encoded let experience_encoded = ctx.v1.claims['urn:zitadel:iam:user:metadata'].experience_level; let experience = ''; try { experience = decodeURIComponent(escape(String.fromCharCode.apply(null, experience_encoded.split('').map(function(c) { return '0x' + ('0' + c.charCodeAt(0).toString(16)).slice(-2); })))); } catch (e) { return; // If decoding fails, stop executing the function } // Check if the experience level exists if (!experience) { return; } // Iterate through the user's grants ctx.v1.user.grants.grants.forEach(grant => { // Iterate through the roles of each grant grant.roles.forEach(role => { // Check if the user is a journalist if (role === 'journalist') { // Set custom claims with the user's role and experience level api.v1.claims.setClaim('journalist:experience_level', experience); } // Check if the user is an editor else if (role === 'editor') { // Set custom claims with the user's role and experience level api.v1.claims.setClaim('editor:experience_level', experience); } }); }); }


  1. GánRoleAndExperienceClaims bây giờ sẽ được liệt kê dưới dạng một hành động.



  1. Tiếp theo, chúng ta phải chọn Flow Type . Đi đến phần Dòng bên dưới. Chọn Mã thông báo bổ sung từ danh sách thả xuống.



  1. Bây giờ, bạn phải chọn một kích hoạt. Nhấp vào Thêm trình kích hoạt . Chọn việc tạo mã thông báo truy cập trước làm loại trình kích hoạt và chọn gánRoleAndExperienceClaims làm hành động liên quan.



  1. Và bây giờ, bạn sẽ thấy trigger được liệt kê.



Giờ đây, khi người dùng yêu cầu mã thông báo truy cập, hành động sẽ được thực thi, chuyển đổi vai trò của người dùng và siêu dữ liệu sang định dạng bắt buộc và thêm chúng làm xác nhận quyền sở hữu tùy chỉnh cho mã thông báo. Sau đó, xác nhận quyền sở hữu tùy chỉnh này có thể được các ứng dụng bên thứ ba sử dụng để quản lý quyền truy cập chi tiết của người dùng.

Thiết lập dự án API

Sao chép dự án từ GitHub:

Chạy lệnh bên dưới để sao chép dự án từ kho GitHub này:

  • git clone https://github.com/zitadel/example-fine-grained-authorization.git


Điều hướng đến Thư mục dự án:

Sau khi nhân bản, điều hướng đến thư mục dự án với

  • cd example-fine-grained-authorization .


Thiết lập môi trường Python:

Đảm bảo bạn đã cài đặt Python 3 và pip. Bạn có thể kiểm tra điều này bằng cách chạy

  • python3 --version
  • pip3 --version

trong thiết bị đầu cuối của bạn. Nếu bạn chưa cài đặt Python hoặc pip, bạn sẽ cần cài đặt chúng.


Tiếp theo, tạo môi trường ảo mới cho dự án này bằng cách chạy

  • python3 -m venv env .


Kích hoạt môi trường bằng cách chạy:

  • Trên Windows: .\env\Scripts\activate
  • Trên Unix hoặc MacOS: source env/bin/activate


Sau khi chạy lệnh này, thiết bị đầu cuối của bạn sẽ cho biết rằng bạn hiện đang làm việc trong môi trường ảo env.


Cài đặt phụ thuộc:

Với thiết bị đầu cuối trong thư mục dự án (thư mục chứa require.txt), hãy chạy

  • pip3 install -r requirements.txt

để cài đặt các phụ thuộc cần thiết.


Cấu hình các biến môi trường:

Dự án yêu cầu các biến môi trường nhất định. Điền vào tệp .env các giá trị chúng tôi đã truy xuất từ ZITADEL.

 PROJECT_ID="<YOUR PROJECT ID>" ZITADEL_DOMAIN="<YOUR INSTANCE DOMAIN eg https://instance-as23uy.zitadel.cloud>" ZITADEL_TOKEN_URL="<YOUR TOKEN URL eg https://instance-as23uy.zitadel.cloud/oauth/v2/token" CLIENT_ID="<YOUR SERVICE USER'S CLIENT ID FROM THE GENERATED CLIENT CREDENTIALS eg sj_Alice>" CLIENT_SECRET="<YOUR SERVICE USER'S SECRET FROM THE GENERATED CLIENT CREDENTIALS"> ZITADEL_INTROSPECTION_URL="<YOUR INTROSPECTION URL eg https://instance-as23uy.zitadel.cloud/oauth/v2/introspect>" API_CLIENT_ID="<THE CLIENT ID OF YOUR API APPLICATION FOR BASIC AUTH eg 324545668690006737@api>" API_CLIENT_SECRET="<THE CLIENT SECRET OF YOUR API APPLICATION FOR BASIC AUTH>"


Chạy ứng dụng:

API Flask (trong app.py ) sử dụng mã thông báo JWT và xác nhận quyền sở hữu tùy chỉnh để kiểm soát quyền truy cập chi tiết. Nó kiểm tra yêu cầu tùy chỉnh experience_level cho vai trò journalisteditor trong mọi yêu cầu, sử dụng thông tin này để quyết định xem người dùng đã xác thực có thể truy cập vào điểm cuối được yêu cầu hay không.


app.py

 from flask import Flask, jsonify from auth import token_required from access_control import authorize_access app = Flask(__name__) # Define the /write_article route. @app.route('/write_article', methods=['POST']) @token_required def write_article(): authorization = authorize_access('write_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article written successfully!"}), 200 # Define the /edit_article route. @app.route('/edit_article', methods=['PUT']) @token_required def edit_article(): authorization = authorize_access('edit_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article edited successfully!"}), 200 # Define the /review_article route. @app.route('/review_articles', methods=['GET']) @token_required def review_article(): authorization = authorize_access('review_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article review accessed successfully!"}), 200 # Define the /publish_article route. @app.route('/publish_article', methods=['POST']) @token_required def publish_article(): authorization = authorize_access('publish_article') if authorization is not True: return authorization # Resource-specific code goes here... return jsonify({"message": "Article published successfully!"}), 200 # Add more endpoints as needed... if __name__ == '__main__': app.run(debug=True)


auth.py

 import os import jwt import requests from functools import wraps from flask import request, jsonify, g ZITADEL_INTROSPECTION_URL = os.getenv('ZITADEL_INTROSPECTION_URL') API_CLIENT_ID = os.getenv('API_CLIENT_ID') API_CLIENT_SECRET = os.getenv('API_CLIENT_SECRET') # This function checks the token introspection and populates the flask.g variable with the user's token def token_required(f): @wraps(f) def decorated(*args, **kwargs): token = request.headers.get('Authorization') if not token: abort(401) # Return status code 401 for Unauthorized if there's no token else: token = token.split(' ')[1] # The token is in the format "Bearer <token>", we want to extract the actual token # Call the introspection endpoint introspection_response = requests.post( ZITADEL_INTROSPECTION_URL, auth=(API_CLIENT_ID, API_CLIENT_SECRET), data={'token': token} ) if not introspection_response.json().get('active', False): return jsonify({"message": "Invalid token"}), 403 # Decode the token and print it for inspection decoded_token = jwt.decode(token, options={"verify_signature": False}) print(f"\n\n***** Decoded Token: {decoded_token} \n\n******") # Add the decoded token to Flask's global context g.token = decoded_token return f(*args, **kwargs) return decorated


access_control.py (mã mẫu mô phỏng công cụ quy tắc)

 import base64 import jwt from flask import g, jsonify # The access_requirements dictionary represents your access control rules. access_requirements = { 'write_article': [{'role': 'journalist', 'experience_level': 'junior'}, {'role': 'journalist', 'experience_level': 'intermediate'}, {'role': 'journalist', 'experience_level': 'senior'}], 'edit_article': [{'role': 'editor', 'experience_level': 'junior'}, {'role': 'editor', 'experience_level': 'intermediate'}, {'role': 'editor', 'experience_level': 'senior'}], 'review_articles': [{'role': 'journalist', 'experience_level': 'senior'}, {'role': 'editor', 'experience_level': 'intermediate'}, {'role': 'editor', 'experience_level': 'senior'}], 'publish_article': [{'role': 'journalist', 'experience_level': 'intermediate'}, {'role': 'journalist', 'experience_level': 'senior'}, {'role': 'editor', 'experience_level': 'senior'}] # Add more endpoints as needed... } # This function checks if the user is authorized to access the given endpoint. def authorize_access(endpoint): # We assume that the token has already been decoded in auth.py decoded_token = g.token # Initialize role and experience_level variables role = None experience_level = None for claim, value in decoded_token.items(): if ':experience_level' in claim: role, _ = claim.split(':') experience_level = base64.b64decode(value).decode('utf-8') break # If there's no role in the token, return an error if not role: return jsonify({"message": "Missing role"}), 403 # If there's a role in the token but no experience level, default the experience level to 'junior' if role and not experience_level: experience_level = 'junior' # If there's no role or experience level in the token, return an error if not role or not experience_level: return jsonify({"message": "Missing role or experience level"}), 403 # Get the requirements for the requested endpoint endpoint_requirements = access_requirements.get(endpoint) # If the endpoint is not in the access control list, return an error if not endpoint_requirements: return jsonify({"message": "Endpoint not found in access control list"}), 403 # Check if the user's role and experience level meet the requirements for the requested endpoint for requirement in endpoint_requirements: required_role = requirement['role'] required_experience_level = requirement['experience_level'] # Experience level hierarchy experience_levels = ['junior', 'intermediate', 'senior'] if role == required_role and experience_levels.index(experience_level) >= experience_levels.index(required_experience_level): return True #return jsonify({"message": "Access denied"}), 403 return jsonify({"message": f"Access denied! You are a {experience_level} {role} and therefore cannot access {endpoint}"}), 403


Chạy ứng dụng Flask bằng cách thực thi:

python3 app.py


Nếu mọi thứ được thiết lập chính xác thì ứng dụng Flask của bạn sẽ chạy.


Dự án này đã được phát triển và thử nghiệm bằng Python 3, vì vậy hãy đảm bảo bạn đang sử dụng trình thông dịch Python 3.

Chạy và kiểm tra API

Chạy API

  1. Đảm bảo bạn đã sao chép kho lưu trữ và cài đặt các phần phụ thuộc cần thiết như được mô tả trước đó.


  2. Chạy tập lệnh client_credentials_token_generator.py để tạo mã thông báo truy cập.


    client_credentials_token_generator.py

     import os import requests import base64 from dotenv import load_dotenv load_dotenv() ZITADEL_DOMAIN = os.getenv("ZITADEL_DOMAIN") CLIENT_ID = os.getenv("CLIENT_ID") CLIENT_SECRET = os.getenv("CLIENT_SECRET") ZITADEL_TOKEN_URL = os.getenv("ZITADEL_TOKEN_URL") PROJECT_ID = os.getenv("PROJECT_ID") # Encode the client ID and client secret in Base64 client_credentials = f"{CLIENT_ID}:{CLIENT_SECRET}".encode("utf-8") base64_client_credentials = base64.b64encode(client_credentials).decode("utf-8") # Request an OAuth token from ZITADEL headers = { "Content-Type": "application/x-www-form-urlencoded", "Authorization": f"Basic {base64_client_credentials}" } data = { "grant_type": "client_credentials", "scope": f"openid profile email urn:zitadel:iam:org:project:id:{PROJECT_ID}:aud urn:zitadel:iam:org:projects:roles urn:zitadel:iam:user:metadata" } response = requests.post(ZITADEL_TOKEN_URL, headers=headers, data=data) if response.status_code == 200: access_token = response.json()["access_token"] print(f"Response: {response.json()}") print(f"Access token: {access_token}") else: print(f"Error: {response.status_code} - {response.text}")


    Mở terminal của bạn và điều hướng đến thư mục dự án, sau đó chạy tập lệnh bằng python3:

    python3 client_credentials_token_generator.py


  3. Nếu thành công, thao tác này sẽ in mã thông báo truy cập tới thiết bị đầu cuối của bạn. Đây là mã thông báo bạn sẽ sử dụng để xác thực yêu cầu của mình với API.


  4. Nếu bạn không khởi động API Flask trước đó, hãy chạy API bằng cách mở một thiết bị đầu cuối khác trong thư mục dự án và chạy:

    python3 app.py


  5. Máy chủ API hiện đang chạy và sẵn sàng chấp nhận yêu cầu.


Giờ đây, bạn có thể sử dụng cURL hoặc bất kỳ ứng dụng khách HTTP nào khác (như Postman) để gửi yêu cầu tới API. Hãy nhớ thay thế your_access_token trong các lệnh cuộn tròn bằng mã thông báo truy cập bạn nhận được ở bước 2.

Kiểm tra API

Tình huống 1: Biên tập viên trẻ cố gắng chỉnh sửa một bài viết (Thành công)


Người dùng có vai trò editor và cấp độ kinh nghiệm junior cố gắng gọi điểm cuối edit_article .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/edit_article


  • Kết quả mong đợi: {"message": "Article edited successfully"}


Tình huống 2: Biên tập viên trẻ cố gắng xuất bản một bài báo (Thất bại)

Người dùng có vai trò editor và cấp độ kinh nghiệm junior cố gắng gọi điểm cuối publish_article .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/publish_article


  • Kết quả mong đợi: {"message": "Access denied! You are a junior editor and therefore cannot access publish_article"}


Tình huống 3: Nhà báo cấp cao cố gắng viết một bài báo (Thành công)

Người dùng có vai trò journalist và cấp độ kinh nghiệm senior cố gắng gọi điểm cuối write_article .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/write_article

  • Kết quả mong đợi: {"message": "Article written successfully"}


Tình huống 4: Nhà báo trẻ cố gắng xem lại bài báo (Thất bại)

Người dùng có vai trò journalist và cấp độ kinh nghiệm 'cấp dưới' cố gắng gọi điểm cuối review_articles .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/review_articles


  • Kết quả mong đợi: {"message": "Access denied! You are a junior journalist and therefore cannot access review_articles"}


Tình huống 5: Biên tập viên cấp cao cố gắng đánh giá các bài viết (Thành công)

Người dùng có vai trò editor và cấp độ kinh nghiệm senior cố gắng truy cập điểm cuối review_articles .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/review_articles


  • Kết quả mong đợi: {"message": "Article reviewed successfully"}


Tình huống 6: Nhà báo trung cấp cố gắng xuất bản một bài báo (Thành công)

Người dùng có vai trò journalist và cấp độ kinh nghiệm intermediate cố gắng truy cập điểm cuối publish_article .

  • curl -H "Authorization: Bearer <your_access_token>" -X POST http://localhost:5000/publish_article


  • Kết quả mong đợi: {"message": "Article published successfully"}

Phần kết luận

Trong bài viết này, chúng tôi đã khám phá tầm quan trọng của việc chuyển từ RBAC truyền thống sang phương pháp ủy quyền chi tiết hơn, chi tiết hơn bằng cách sử dụng ZITADEL.


Chúng tôi đã đào sâu vào các tính năng của nó như hành động động cho ABAC, khả năng tích hợp với các công cụ của bên thứ ba và xem cách những khả năng này có thể được áp dụng thực tế trong tình huống thực tế.


Khi nhu cầu về an ninh mạng ngày càng tăng, các nền tảng như ZITADEL cung cấp các giải pháp cần thiết cho những thách thức ủy quyền phức tạp.