Android Network Security Configuration - part2
Để có thể tiện theo dõi các bạn có thể xem phần 1 tại đây. Đây là phần 2, tiếp nối phần 1 mình sẽ nói tiếp về Domain configuration và Debug overrides trong Network Security Configuration Domain configuration Ở phần trước chúng ta đã chỉnh định cấu hình network security mở mức base-config, đã ...
Để có thể tiện theo dõi các bạn có thể xem phần 1 tại đây.
Đây là phần 2, tiếp nối phần 1 mình sẽ nói tiếp về Domain configuration và Debug overrides trong Network Security Configuration
Domain configuration
Ở phần trước chúng ta đã chỉnh định cấu hình network security mở mức base-config, đã thử áp dụng cấu hình cho tất cả các kết nối mà ứng dụng cố gắng thực hiện kết nối đến.
Ở phần này bạn có thể override một cấu hình cụ thể nào đó bằng cách chỉ định cho từng domain-config element. Một domain-config có thể chỉ định các option tuỳ chỉnh cho những domain cụ thể.
Hãy thử cấu hình network security cho app của mình như sau:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="false" /> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">localhost</domain> </domain-config> </network-security-config>
Theo như cấu hình này chỉ định thì phần base-config sẽ apply cho tất cả các domain trừ một thằng là "localhost" và các subdomain của nó, thằng "localhost" sẽ được apply theo cấu hình khác đã được chỉ định.
Ở file network_security_config này thì base-config sẽ ngăn cản cleartext traffic cho toàn bộ domain, nhưng ta đã thực hiện overrides rule cleartextTrafficPermitted và cho phép thằng "localhost" ngoài vòng pháp luật không bị ảnh hưởng gì cả.
Test using a local HTTP server
Bây giờ ứng dụng có thể truy cập localhost sử dụng cleartext, hãy thử khởi động một local web server và thực hiện test access protocol.
Chúng ta có thể sử dụng một http-server Node.JS module thể thiết lập một basic web server rất là cơ bản thôi, và thực hiện cung cấp data cho app của chúng ta:
- Open terminal và install http-server:
npm install http-server -g
- Điều hướng thư mục mà bạn sẽ checkout code đến thư mục server/:
cd server/
- Khởi động web server và cung cấp các file được đặt ở thư mục data/:
http-server ./data -p 8080
- Mở web browser và thực hiện truy cập đến http://localhost:8080 để xác verify rằng bạn có thể access vào "posts.json" file:
- Tiếp theo, chuyển tiếp cổng 8080 từ device đến local machine. Thực hiện run command sau trong một của sổ terminal khác:
adb reverse tcp:8080 tcp:8080
Bây giờ app của bạn đã có thể truy cập vào "localhost:8080" từ device Android.
- Chuyển URL sang server localhost trong file gradle.properties
gradle.properties
postsUrl="http://localhost:8080/posts.json"
- Thực hiện run app và check xem data đã có thể lấy về từ local machine hay chưa. Bạn có thể chỉnh sửa lại data/posts.json file để xác định chắc rằng đúng là data đã có thể get về.
Aside - domain configuration
Các tuỳ chọn cấu hình được áp dụng cho các domain cụ thể được define trong domain-config element. Element này có thể chứa nhiều domain cụ thể khác nhau và đều được apply domain-config rule đã chỉ định. Nếu mà nhiều domain-config element cùng chứa các domain tương tự nhau thì Network Security Configuration sẽ lựa chọn một configuration để apply cho URL dựa trên number of matching characters. Configuration nào mà chứa nhiều domain entry mà match characters nhất thì sẽ được sử dụng.
Một domain configuration có thể áp dụng cho nhiều domain cũng như cả subdomain.
Config dưới đây là một ví dụ về Network Security Configuration chứa nhiều domain:
<network-security-config> <domain-config> <domain includeSubdomains="true">secure.example.com</domain> <domain includeSubdomains="true">cdn.example.com</domain> <trust-anchors> <certificates src="@raw/trusted_roots"/> </trust-anchors> </domain-config> </network-security-config>
Debug overrides
Trong quá trình dev, xây dựng ứng dụng thì bạn có thể phải thực hiện kết nối vào local web hoặc test environment để check kết nối, giống như các bước phía trên mà chúng ta đã thực hiện.
Debug-override option trong Network Security Configuration sẽ giúp bạn thực hiện setting các tuỳ chỉnh network cần thiết khi app chạy ở debug mode, điều này khá là tiện lợi và an toàn khi bạn có nhu cầu test app.
Enable SSL on the local web server
Ở phía trên, chúng ta đã thực hiện khởi toạ một local service cung cấp data thông qua HTTP trên port 8080. Bây giờ chúng ta sẽ thực hiện gen một SSL certificate để sử dụng nó cung cấp data qua HTTPS.
- Tạo một certificate bằng cách thay đổi thư mục server/ trên terminal theo command sau:
# Run these commands from inside the server/ directory! # Create a certificate authority openssl genrsa -out root-ca.privkey.pem 2048 # Sign the certificate authority openssl req -x509 -new -nodes -key root-ca.privkey.pem -days 100 -out root-ca.cert.pem -subj "/C=US/O=Debug Cert/CN=localhost" # create DER format crt for Android openssl x509 -outform der -in root-ca.cert.pem -out debug_certificate.crt
Điều này sẽ tạo một certificate authority, signs và tạo một certificate theo định dạng DER format mà Android yêu cầu.
- Thực hiện start web service sử dụng certificate vừa được tạo:
http-server ./data --ssl --cert root-ca.cert.pem --key root-ca.privkey.pem
Update the backend URL
Thực hiện update gradle.properties file:
gradle.properties
postsUrl="https://localhost:8080/posts.json"
Sau đó thì run app thôi.
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
Khi này ứng dụng có thể không truy cập vào web server được vì web server đang sử dụng một self-signed certificate và nó thì không được trusted bởi hệ thống. Nhưng không vì vậy mà ta tắt HTTPS, ta sẽ thực hiện add self-signed certificate cho localhost domain trong bước tiếp theo.
Reference a custom certificate authority
Web server hiện tại đang cung cấp data và sử dụng một self-signed certificate authority (CA) và có điều là certificate này default không được accept bởi hệ thống. Nếu bạn thử truy cập bằng web browser thì sẽ dễ dàng thấy một security warning: https://localhost:8080
Vì vậy ta sẽ thực hiện sử dụng một vài option debug-override trong network security configuration để whitelist self-signed certificate authority (CA) kia cho localhost domain.
- Chỉnh sửa file xml/network_security_config.xml như sau:
res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="false" /> <domain-config> <domain includeSubdomains="true">localhost</domain> <trust-anchors> <certificates src="system" /> <certificates src="@raw/debug_certificate" /> </trust-anchors> </domain-config> </network-security-config>
Thực hiện disable cleartext network traffic và enables the system-provided certificate authority cũng file certificate được lưu trữ ở thư mục res/raw.
- Tiếp theo, copy file "debug_certificate.crt" từ thư mục server/ vào thư mục res/raw resources ở bên Android Studio. Bạn có thể copy, kéo thả các kiểu hoặc xài command như sau:
mkdir ../SecureConfig/app/src/main/res/raw/ cp debug_certificate.crt ../SecureConfig/app/src/main/res/raw/
Và sau đó kiểm tra lại trong thư mục res/raw trong app của bạn
Run the app
Thực hiện compile lại app và run và check lại kết quả. Bây giờ app đã có thể truy cập vào localhost server thông qua HTTPS bằng cách sử dụng một self-signed debug certificate.
Nếu sau khi thực hiện các bước trên mà bạn vẫn gặp lỗi thì hãy check logcat output và đảm bảo rằng http-server đã được config đúng. Ngoài ra cũng cần kiểm tra xem file debug_certificate.crt có được lưu trữ đúng thư mục hay không res/raw/debug_certificate.crt.
Và đây là kết quả
Debug overrides option khá là tiện lợi, giúp ích nhiều trong quá trình phát triển app cũng như test app. Nếu bạn có biết đến phần mềm Charles Proxy - một ứng dụng để xác định các request, các gói tin của app, và được QA sử dụng khá phổ để check request - response của ứng dụng, bạn có thể tham khảo cấu hình dưới đây để sử dụng Charles với ứng dụng Android của bạn:
<network-security-config> <base-config> <trust-anchors> <certificates src="system"/> </trust-anchors> </base-config> <debug-overrides> <trust-anchors> <certificates src="user"/> </trust-anchors> </debug-overrides> </network-security-config>
Như vậy toàn bộ cơ bản về Android Network Security Configuration đã được mình trình bày. Rất mong nó có thể giúp ích cho bạn.