1. 程式人生 > >使用fdopen對python程序產生的檔案進行許可權最小化配置

使用fdopen對python程序產生的檔案進行許可權最小化配置

# 需求背景 用python進行檔案的建立和讀寫操作時,我們很少關注所建立的檔案的許可權配置。對於一些安全性較高的系統,如果我們建立的檔案許可權其他使用者或者同一使用者組裡的其他使用者有可讀許可權的話,有可能導致不必要的資訊洩漏的風險。因此,除了建立一個更加安全和隱私的個人環境之外(如容器環境等),我們還可以對生成的檔案的配置進行許可權最小化處理。 # 常用方法及其缺陷分析 常用的python檔案建立和讀寫方法,是直接通過內建的`open`函式建立一個檔案。這裡如果是使用`with`語法來建立的,結束語句後會自動關閉被開啟的物件。而如果是直接使用`open`函式來定義一個物件,則需要在任務結束時手動的執行`close`操作。以下演示內建函式`open`的用法及其檔案操作屬性,首先建立一個名為`file-test.py`的檔案: ```python # file-test.py with open('test1.txt', 'w') as file: file.write('hello world!') ``` 該任務的內容為:在當前目錄下建立一個名為`test1.txt`的檔案,清空該檔案的內容後,在檔案中寫入`hello world!`這個字串。接下來用`python3`執行該檔案: ```bash [dechin@dechin-manjaro os_security]$ python3 file-test.py [dechin@dechin-manjaro os_security]$ ll 總用量 8 -rw-r--r-- 1 dechin dechin 83 1月 25 13:43 file-test.py -rw-r--r-- 1 dechin dechin 12 1月 25 13:43 test1.txt ``` 這裡我們發現,在執行之後成功產生了`test1.txt`這個檔案,其許可權配置為`644`,與前面建立的`file-test.py`保持一致。在不清楚內建函式`open`的實現原理時,原本以為這個產生的檔案許可權配置是與當前的`py`檔案保持一致的。然而經過進一步的測試,將`py`檔案的許可權配置為`440`之後再重新執行該檔案: ```bash [dechin@dechin-manjaro os_security]$ chmod 440 file-test.py [dechin@dechin-manjaro os_security]$ ll 總用量 8 -r--r----- 1 dechin dechin 83 1月 25 13:43 file-test.py -rw-r--r-- 1 dechin dechin 12 1月 25 13:43 test1.txt [dechin@dechin-manjaro os_security]$ rm test1.txt [dechin@dechin-manjaro os_security]$ python3 file-test.py [dechin@dechin-manjaro os_security]$ ll 總用量 8 -r--r----- 1 dechin dechin 83 1月 25 13:43 file-test.py -rw-r--r-- 1 dechin dechin 12 1月 25 13:44 test1.txt ``` 這裡從測試結果我們可以看出,python的內建函式`open`產生的檔案型別是與源`py`檔案無關的。關於這裡`py`檔案的執行是否需要可執行許可權,可以參考這篇[部落格](https://www.cnblogs.com/dechinphy/p/excutable.html)。 # 改進後的python檔案建立方法 通過`fdopen`這個庫以及特殊的許可權指定,我們可以設定生成檔案的訪問許可權,以下直接展示一個python程式碼案例: ```python # fdopen-test.py import os import stat file_name = 'test2.txt' flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL mode = stat.S_IRUSR | stat.S_IWUSR with os.fdopen(os.open(file_name, flags, mode), 'w') as file: file.write('hello world!') ``` 執行之後我們可以發現,當前目錄下生成了一個名為`test2.txt`的檔案,其許可權配置為`600`, 對照於我們在程式碼中設定的`mode = stat.S_IRUSR | stat.S_IWUSR`。這裡我們先對其中的一些引數作一個解釋:`os.O_WRONLY`表示以只寫的方式開啟,`os.O_CREAT`表示建立並開啟一個新檔案,`os.O_EXCL`表示如果檔案已存在則報錯。而`mode`中所配置的許可權分別對應`rwx`配置,其中`USR,GRP,OTH`又分別對`使用者、使用者組、其他使用者`進行了細分的配置,從而我們就可以通過改變`mode`引數來實現所有種類的許可權配置。 我們可以嘗試將上述用例中的`mode`作一個調整,比如新增一個可執行許可權變為`700`: ```python # fdopen-test.py import os import stat file_name = 'test3.txt' flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR with os.fdopen(os.open(file_name, flags, mode), 'w') as file: file.write('hello world!') ``` 又或者,我們需要為使用者組裡的其他使用者新增可訪問許可權,比如`640`許可權: ```python # fdopen-test.py import os import stat file_name = 'test4.txt' flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP with os.fdopen(os.open(file_name, flags, mode), 'w') as file: file.write('hello world!') ``` 甚至我們也可以寫出系統原生的`644`檔案許可權: ```python # fdopen-test.py import os import stat file_name = 'test5.txt' flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL mode = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH with os.fdopen(os.open(file_name, flags, mode), 'w') as file: file.write('hello world!') ``` 最後,讓我們一起看下上面這些python示例執行後得到的結果: ```bash [dechin@dechin-manjaro os_security]$ ll 總用量 28 -rw-r--r-- 1 dechin dechin 269 1月 25 14:58 fdopen-test.py -r--r----- 1 dechin dechin 84 1月 25 14:11 file-test.py -rw-r--r-- 1 dechin dechin 12 1月 25 13:44 test1.txt -rw------- 1 dechin dechin 12 1月 25 14:44 test2.txt -rwx------ 1 dechin dechin 12 1月 25 14:48 test3.txt -rw-r----- 1 dechin dechin 12 1月 25 14:56 test4.txt -rw-r--r-- 1 dechin dechin 12 1月 25 14:58 test5.txt ``` 從結果中我們可以看出,所有產生的檔案`test*.txt`都按照我們預期的檔案許可權配置生成,到這裡我們就完成了所有預期的目標。 # 總結概要 使用python進行檔案的建立和讀寫時,常規的內建函式`open`得到的結果會是一個`644`許可權的檔案,這不一定能夠滿足很多對安全性需求較高的執行環境的要求。因此我們可以通過`fdopen`來對所建立的檔案進行進一步的許可權約束,具體的操作方法可以在`mode`中定義一系列的許可權配置,比如帶有`USR`的表示當前用來執行python檔案的使用者,帶有`GRP`的表示用來執行python檔案的整個使用者組,而`OTH`則表示其他的所有的使用者。這當中尤其是`OTH`這個選項往往是不必要開放的許可權,我們也可以根據具體的場景需求對建立的檔案許可權進行配置。這裡還有一點補充介紹的是,`os.O_EXCL`這個指令的開啟表示如果存在同名檔案就無法建立,需要先使用`os.remove`操作刪除原檔案後再進行新的檔案操作,避免檔案許可權被覆蓋或者重用,從而導致建立的新檔案許可權配置與我們所預期的不符合。 # 參考連結 1. [fdopen使用方法的問答](https://www.itranslater.com/qa/details/2582528972349244416) 2. [os.open()各配置引數解釋](https://www.runoob.com/python3/python3-os-open.html) # 版權宣告 本文首發連結為:https://www.cnblogs.com/dechinphy/p/fdopen.html 作者ID:DechinPhy 更多原著文章請參考:https://www.cnblogs.com/de