CHEF自動化 — IT的六個標準差工具

人類很容易出錯,而且往往會對重複性的作業感到厭倦

為什麼企業需要"自動化"?因為隨興行事是"秩序、標準化和品質"的大敵。而沒有自動化就無法產生秩序與邊準化,進而品質維持在高水準。

CEHF的Agent(稱為CHEF infra client)可以安裝Linux/Window OS中,不管該台VM(或實體機)是在地端、雲端(只要對外Https有開啟)。CHEF是一種DSC(desire state configuration)的CM(Configuration Management)工具,它可以與Terraform進行整合。Terraform(IaC)啟用Infra資源之後,CHEF接手後面的OS配置作業。

管理環境

Master / Client 分離

CHEF Infra架構如下圖所示。CHEF Infra為CHEF最基本底層服務,並提共Master(CHEF Server)與Clients(受管理的機器)分離的架構。

CHEF Infra

分為三個部分

  1. Workstation — 編寫與測試腳本的地方。可以是個人筆電或某台伺服器,Workstation在將腳本上傳到CHEF server之前可以模擬(Test Kitchen)整個對目標伺服器的佈署測試。
  2. CHEF Server— 所有腳本的儲存庫,可以主動將Scripts推向CHEF client(Push mode — Agentless based)
  3. Clients — 目標伺服器,CHEF client會定期去檢視CHEF server上面相對應的server role中應該有的相對應的狀態(Pull mode — Agent based)。CHEF Clientd可以是以下各項標的(如下圖)
CHEF架構

以上三個部分的通訊都是會通過驗證與加密。CHEF server會Workstation/Clients的Public key,所以如果沒有相對應的Private Key,哪將無法存取CHEF Server。使用的加密技術可以使用FIPS(Federal Information Processing Standards)來進行驗證,無法通過FIPS驗證的加密技術都不會被允許在CHEF中使用。更多的CHEF infra 的詳細組件介紹可以參閱CHEF.io的文件庫

PS: CHEF client可以直接支援(安裝)"Juniper/Arista/Cisco/F5"這幾類的網路產品,因為這幾個產品的都是OS based的操作軟體。如Cisco NX-OS系列的安裝說明手冊

服務選項

CHEF Server可以架設在雲端或自有機房中,CHEF也提供SaaS服務。若是自架CHEF解決方案,建議用CHEF Automate作為全面的自動化平台。CHEF Automate除了全面的管理作業自動化之外,還與CHEF其他工具整合提供

  • CHEF InSpec(Policy/Compliance as Code) —
    檢查目標機器是否合規或合於組織的政策,例如Application server role規定的Package是否安裝與Configuration是否正確,並呈現狀態報告(如下範例畫面)。

以下是一個Compliance as Code的範例

# 檢查作業系統是Redhat Enterprise 8.3以上
describe os.family do
it { should eq 'redhat' }
end

describe os.release do
it { should >= '8.3' }
end

# 檢查Apache Http server必須是最新版
describe package('httpd') do
it { should be_installed }
its('version') { should cmp >= '最新版本' } # 請將最新版本替換為實際的最新版本號碼
end

# 檢查Apache Http server的configuration只能開放https protocol
describe file('/etc/httpd/conf/httpd.conf') do
its('content') { should_not match(/Listen 80/) } # 檢查是否有設置HTTP的監聽端口
its('content') { should match(/Listen 443/) } # 檢查是否有設置HTTPS的監聽端口
end

另CHEF InSpec符合CIS(Center for Internet Security)的認證,並支援多種系統/產品的合規檢查。詳細清單請查閱CHEF官網CIS官方網站

  • CHEF Habitat(Application Virtualization) —
    應用程式的虛擬層,可將目前無法移植到新的OS的應用程式遷移過去。

可用性說明

高可用架構

CHEF Automate提供HA架構,搭配Load Balancer(例如NGINX、HA Proxy或其他商用LB)包含前端 CHEF Infra/Automate server(Application layer)與backend(DB layer)的 Cluster架構。當有任何一台Server損壞時都不會影響其平台服務。

防禦妥善

整個CHEF 架構分為三個層面,伺服器(包含OS)、開發過程中的"cookbooks與InSpec profiles"與執行過程中的"cookbooks與InSpec profiles"。伺服器(包含OS)的安全管理如同一般伺服器管理的安全實踐方法。

再來由於Configuration management這一類的工具也是程式開發的一種,組織也需要遵循DevSecOps的安全實踐。關於DevSecOps的概念與實踐請參閱本部落格"DevSecOps實行指南"與"多雲環境下的DevSecOps實行"一文。

在開發"cookbooks與InSpec profiles"的安全實踐

  1. 知悉Chef 代碼的來源,並在安全的儲存庫(例如Gitlab或 GitHub)中對對代碼進行版控。
  2. 在開發 Ruby 時遵循特定領域的最佳實踐,例如註釋、規模測試以及從 Chef 或其他Repo中提取secrets(如透過 SSH 參數來hard-code secrets)。
  3. 手動檢查代碼檔案,以確保我們希望 Ruby 執行的所有操作都在其中,而沒有其他內容。 如果我們不理解第三方代碼片段中的任何一行,請詢問原始篇編寫者或不要使用它。
  4. 使用 Chef 和其他自動化工具(例如 Test Kitchen 或SAST — static application security tools)進行代碼檢查和測試。
  5. 透過在Pre-production環境中測試代碼工件(cod artifacts)來左移(Shift left),這可以在在CHEF Workstation進行。
  6. Peer review— — 在沒有第二個同事(或資深人員)審核的情況下,不允許變跟操作。這與工作流程有關,CHEF可以與ServiceNow這一類的ITSM工具進行整合。

執行過程中的"cookbooks與InSpec profiles"的安全實踐

  1. 確保代碼內容已加密和簽名
  2. 使用身份驗證提供對 Chef 伺服器的特定基於角色的存取。 透過Automate,可以直接整合MFA工具。 對於內容存儲庫,設定正確的Access Level。
  3. 確保 Automate 中所有的Server都有最新的有效憑證,並且定期更換憑證。CHEF各節點的通訊都是需要憑證的,並且從Client來的每一次Request,CHEF infra都會對其進行驗證。
  4. 使用WAF和reverse Proxy來保護底層Server。 並將CHEF解決方案與其他環境隔離(例如利用Micro-segmentation)。
  5. 使用CHEF Inspec來檢查CHEF其本身的所有配置是否正確沒有Missconfiguration。

另外某些類型的資料(密碼、使用者帳戶資料和其他敏感項目)可以放置在Secrets(CHEF稱data bags)中,這些data bags位於 Chef Infra 伺服器上的安全位置(資料是有加密的)中,只有透過 Chef Infra 驗證的伺服器才能存取該data bags具有正確SSL 憑證的伺服器。

敏感資訊存取:

內部權限管理

可以使用Users/Teams/Roles/Policies等方式進行權限管理,這些管理方式的概念與一般的IAM(Identity and Access Management)的方式相同。

CHEF的IAM管理
Policies

我們甚至可以用CHEF Project的方式將CHEF中的各項資源(帳號、機器、腳本)等組合在一起。類似我們在CHEF中建立一個Sandbox或是Multitenancy的環境來進行管理。

外部權限管理介接

可以與LDAP)SAML進行介接。

LDAP支援的平台有:

  • Azure Active Directory
  • Microsoft Active Directory (MSAD)

SAML(Security Assertion Markup Language)支援的平台有:

  • Azure AD
  • Microsoft 365
  • Okta
  • OneLogin
  • Ping
  • Tivoli Federated Identity Manager

CHEF可以對嘗試登入失敗一定次數做出一些限制。

權限操作情境:

決定腳本執行權限

透過CHEF的IAM policy來決定那些User/Teams/Roles來可以對腳本的執行、刪除與對那些機器(可群組)有執行腳本的權限。以下是一個範例,當使用者是Frontend team並且server的role是web server可以執行(但不能刪除)腳本A與F

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"chef:ExecuteRecipe"
],
"Resource": [
"recipe:A",
"recipe:F"
],
"Condition": {
"StringEquals": {
"chef:ServerRole": "web server",
"chef:Team": "frontend"
}
}
},
{
"Effect": "Deny",
"Action": [
"chef:DeleteRecipe"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"chef:ServerRole": "web server",
"chef:Team": "frontend"
}
}
}
]
}

機器管理

目標機器和群組管理

CHEF對於自有機房可透過定期掃描(如網段)的方式來探索新機器與安裝Agent,也可以與Vmware的vCenter進行整合。對於雲端(AWS/Azure/GCP)中的VM,CHEF直接與雲端帳號整合。當雲端中有新機器產生時,CHEF可以透過API的方式排程探索相關VM資訊,並安裝Agent。若雲端中VM的Metadata(有Tag),可以根據該Tag自動分配到CHEF中定義好的群組。也可以根據該Tag決定要不要對該機器進行管理。

Dashboard和監控

CHEF Automate提供了用於監控和管理的儀表板,可以及時監控機器狀態和自動化工作流程。例如執行不成功的Server,Automate的Notifications使用ServiceNow、Slack或支援Webhook的方式進行通知。

腳本情境

排除特定機器執行腳本

在腳本中加入attribute來排除某個機器,例如以下範例。或是用CHEF Automate 的Project方式。

# 檢查並排除不符合條件的機器
if node['platform'] != 'redhat' || # 條件1:非Redhat OS
!(node['ipaddress'] =~ /^192\.168\.1\.\d+$/) || # 條件2:IP網段不在192.168.1/24之內
!node['firewall']['open_ports'].include?('443') # 條件3:防火牆沒有開啟443 port
return
end

# 在符合條件的機器上執行特定任務
# 例如:設置Apache HTTP Server監聽443 port
service 'httpd' do
action :enable
end

# 或者執行其他任務...

對單台機器執行多個腳本

使用Run-lists。Run-lists是定義 CHEF將目標機器配置為所需狀態的所有資訊。 Run-lists是:

  1. 按照Run-lists中定義的確切順序執行的角色和(或)腳本(recipes)的清單列表; 如果某個腳本在Run-lists中出現多次,Chef Infra Client 不會把重複出現的腳本重複執行
  2. 這會作為node object的一部分儲存在 Chef Server上
{
"name": "my_runlist",
"run_list": [
"recipe[A]",
"recipe[B]",
"recipe[C]",
"recipe[D]",
"recipe[E]",
"recipe[F]"
]
}

上面的範例中,CHEF會依序執行。並且會確認執行成功之後才會執行下一個。

對群組機器執行多個腳本

在CHEF Infra中使用Roles的方式將機器進行群組,並搭配上述的Run-list對其進行多腳本的執行。這與Automate 的Roles不同點是Infra使對機器群組,Automate的Roles是對帳號群組。

執行細節

併發處理(多台執行同一腳本)

CHEF採用Agent based(Pull mode)的方式來執行一個腳本多台機器。意思是CHEF Server不主動送出腳本資訊,而是Agent會回來CHEF server報到檢視並執行自己(該台Server)的Desired State(也就是宣告式的)。若環境規模如Meta(Facebook — 上萬台的Server)的環境,CHEF提拱兩種解決方案:

第一種,建立多台CHEF Infra/Automate Server(如上圖所示的HA)的架構,同一時間接受來自一萬個Client 更新要求。但二種,在CHEF Server上設定Policy來控制CHEF Infra client的行為,例如設定Client的運作間隔、限制同時運作的Client數量等(以下為一個Policy範例)。

# 將所有CHEF Infra Client分成20個批次
batch_count = 20

# 每個批次包含的Infra Client數量
clients_per_batch = 500

# 脚本的執行的時間(分鐘)
script_execution_time = 5

# 每10分鐘同时運行的Infra Client數量
clients_per_interval = 500

# 計算每個批次之間的時間間隔(分鐘)
interval_time = 10

# 計算總共需要的時間(分鐘)
total_time = batch_count * (script_execution_time + interval_time)

puts "總共需要的時間:#{total_time} 分鐘"

關於甚麼是宣告式(Declarative)代碼甚麼是命令式(Imperative)代碼,請參閱本部落格"Iac Part 4–定義一切都是代碼"一文。

執行鎖定(防止重複執行)

使用Guard語法
在Chef脚本中,可以使用Guard Clauses來檢查伺服器中某些特定條件是否已滿足(也就是Desired state),如果條件已滿足,則不執行脚本。例如,可以在脚本中加入某些條件來檢查某個檔案或Process是否存在,如果存在,則不執行脚本。

# 檢查OS是否為 Redhat Enterprise 最新版本
return if node['platform'] != 'redhat' || node['platform_version'].to_i < 8

# 檢查MySQL 是否已安裝且正在運行
mysql_installed_and_running = system('systemctl is-active mysql.service >/dev/null 2>&1')

# 檢查防火墙是否已開啟 TCP port 3306
firewall_opened_port_3306 = system('firewall-cmd --query-port=3306/tcp')

# 如果以上三个條件都滿足,則不執行脚本
return if mysql_installed_and_running && firewall_opened_port_3306

# 如果有任一條件不滿足,則執行脚本
execute 'your_script' do
command 'your_command_to_run'
action :run
end

排程腳本

我們可以使用CHEF Automate 的workflow的方式加上定期排程的方式。但由於CHEF是desired state的結構,除非該作業是一次性的。否則Client會定期對CHEF server報到,檢視應該達到的狀態。例如上一次現行狀態與從Server取得的最新狀態是否相符。如果沒有哪就應該執行缺失的部分。

一次性的作業理論上應該不存在。因為很容易產生"configuration drift"。並且違反一些IaC的原則,例如"讓一切都可重現"、"建立可拋棄的系統(是牛群而非寵物)"、"最小的差異"等。

workflow 'example_workflow' do
description 'An example workflow'

schedule '0 8 * * *' # 在每天 8:00 AM執行一次

sequence do
step 'step_1' do
description 'Step 1: Execute script A'
script 'A_script.sh'
end

step 'step_2' do
description 'Step 2: Execute script B'
script 'B_script.sh'
on_failure 'notify_failure'
end
end

notification 'notify_failure' do
description 'Notify when a step fails'
recipients ['admin@example.com']
action 'email'
end
end

執行序列

在CHEF Infra中,我們可以使用notifiessubscribes來根據前一個腳本的執行結果或條件來決定下一個腳本的執行與否(也可以用Run-lists)。這些可以在各個資源定義中進行設置,以達到根據需要動態調整執行順序的目的。

例如以下範例:

  1. A腳本執行後,若執行失敗則執行C腳本
  2. A腳本執行後,若執行成功則執行B腳本
  3. 若C腳本也執行失敗則使用CHEF automate發出通知
# A腳本的定義
execute 'A_script' do
command 'A_script_command'
notifies :run, 'execute[B_script]', :immediately
notifies :run, 'execute[C_script]', :delayed
end

# B腳本的定義
execute 'B_script' do
command 'B_script_command'
action :nothing
end

# C腳本的定義
execute 'C_script' do
command 'C_script_command'
action :nothing
only_if { !File.exist?('/path/to/some/file') } # 執行C腳本的條件:如果指定文件不存在(也可以檢查Server中的某個Process是不是在運行),表示A腳本執行失敗
notifies :run, 'ruby_block[notify_failure]', :delayed
end

# 通知失敗的動作定義
ruby_block 'notify_failure' do
block do
# 使用CHEF Automate發送通知的程式碼
# 例如:
# automate_url = 'http://chef-automate.example.com/api/v0/notifications'
# automate_token = 'your_automate_token'
# notification_message = 'A腳本執行失敗,C腳本被觸發'
# send_notification_to_automate(automate_url, automate_token, notification_message)
end
action :nothing
end

工作流程

CHEF Infra的內部作業流程是以Policy根據以下的屬性來支援組織的工作流程

  • 定義伺服器類型(By Role),例如“Web Server”或“DB server”
  • 以環境來定義流程,例如「Dev」、「Staging」或「Production」
  • 用Attribute來定義有關包含在Policy file中的伺服器的環境特定詳細資訊

另外組織的業務流程則可以與ServiceNow進行整合

整合之後可以在ServiceNow的CMDB中看到受CHEF所管理的伺服器(如下圖所示)。

執行結果的狀態與稽核

不論是哪一種腳本的執行,CHEF Automate都會儀表板可供查詢(如下圖)。不論是哪執行成功或失敗,都有詳細的執行內容紀錄可供查詢。CHEF Automate可以與Elasticsearch或AWS OpenSearch進行整合,以利歷史紀錄的查詢。

監控和事件接口

CHEF Automate的監控功能來監視錯誤、異常和腳本執行結果(如上圖的Event Feed功能),並可以其他平台介接來設置事件接口處理相關事件。CHEF Automate使用WebHook的方式與與其他事件平台進行整合,例如:

  • ServiceNow
  • Splunk
  • ELK
  • MinIO
  • Amazon S3

附註:Configuration Management Workflow

以下為一個IaC/CaC(Configuration as Code)的建議作業流程

規劃階段(Planning)

  • 範圍、目標、政策、標準、角色和責任
  • 流程提供以下服務:
    1.定義包含相關服務和基礎架構的CI(Configuration Item)
    2.控制CI的變更
    3.記錄並報告配置項的狀態
    4.依照可問責、可追溯、可審計的要求,驗證配置項的完整性和正確
  • 配置(Configuration)控制 ,包含"存取、保護、版控、建置(Build)和發布"
  • 用於在兩個或多個組織的公共邊界處的識別、記錄和管理 CI 和資訊的介面控制流程(例如,系統介面和版本)
  • 規劃和建立資源以控制數位資產和配置(Configuration)並維護配置管理系統
  • 執行配置管理的供應商和分包商的管理

配置識別(Configuration Identification)階段

在配置識別過程中,配置管理員選擇CI,記錄其識別特徵,並為所選項目(Item)給予唯一識別碼(通常是給tag或稱metadata)。 此流有助於確保高效率的資料儲存和檢索。

配置識別流程讓組織能執行以下作業:

  • 辨識與註冊 CIs
  • 給予唯一識別碼,以方便進行管理
  • 紀錄各CI之間的關係

配置控制階段

在配置控制流程中,配置管理員審查更新後的配置管理系統 (CMS — Configuration Management system) 的配置管理作業,並評估修改前和修改後狀態的組態。 配置管理員驗證資訊的正確性和完整性,並包含要修改的屬性的描述; 提出的修改符合配置管理政策; 並且配置詳細資訊在組態管理資料庫中得到更新。

配置狀態統計和報告階段

配置狀態統計和報告可確保在每個 CI 從測試到生產再到報廢的整個生命週期中記錄所有配置資料和文件。 配置資訊應保持最新,並可用於規劃、決策和管理已定義配置的變更。

配置狀態統計和報告需能追蹤以下 CI 狀態變更:

  • New items received (透過某種證明,例如數位簽章)
  • Installation of items
  • Transition from test to production
  • System down (基於events)
  • Retired or disposed items
  • Lost or stolen items
  • Unauthorized CIs and Version changes of CIs

組織應維護目前準確的配置記錄,以反映配置項的狀態、位置和版本的變更。 必須維護每個 CI 的歷史記錄。 CI 的變更可透過各種狀態進行追踪,例如"開發中、驗收測試、使用中、變更中、已撤回或已廢棄"。

如果需要,使用者、客戶、供應商和合作夥伴應該可以存取配置資訊,以協助進行規劃和決策。 例如,外部服務提供者可以使客戶和其他方可以存取配置資訊,以支援端到端服務中的其他服務管理流程(如ITSM)。 應為與廢棄 CI 相關的資料定義歸檔程序。

配置管理報告應可供所有相關利害關係人使用。 報告應涵蓋 CI 的標識和狀態,包括其版本和相關文件。 不同的利害關係人需要大量不同的報告(例如,稽核報告、軟體或平台的合規性報告)。

配置的驗證與稽核階段

驗證和稽核作業負責確保配置管理中資訊的準確性,並且所有CI 均在配置管理中標識和記錄。 該流程可以手動進行,也可以使用自動化的探索工具來進行。

驗證包括作為其他流程一部分的例行檢查。 稽核是定期、正式的檢查。 組織應該定期驗證和稽核配置(Configuration),以確保整個配置管理流程以及相關 IT 服務管理流程的正常運作。

”驗證和稽核”的目標是偵測和管理”原則、流程和程序”的所有例外情況,包括安全性和授權。 驗證過程可確保配置記錄準確完整,並且任何記錄的變更均已批准。 配置稽核有助於維護CMS的完整性。

配置和稽核流程還包括根據軟體使用政策定期檢視已安裝的軟體,以識別組織沒有核可的軟體(白名單式管理)。

配置驗證和稽核作業包括:

  • 確保baseline和標準與 IT 環境中的實際組件相符
  • 驗證其服務和產品是否根據文件的要求、標準或合約協議建構並記錄
  • 驗證任何 CI 是否存在正確且授權的版本,並且已正確識別和描述
  • 驗證 CI 的實際存在(例如,在儲存庫中)
  • 在發布之前檢查發布文件和配置管理是否存在
  • 確認當前環境符合預期並記錄在 CMS 中,並且所有變更請求均已核可
  • 檢查配置修改是否透過授權變更流程實施
  • 驗證每個 CI 是否存在 SLA
  • 驗證 CI 規範是否符合已定義好的配置政策與baseline
  • 驗證每個 CI 所需的所有文件是否可用(例如維護合約、授權記錄或保固)
  • 檢查資料品質的準確性和完整性
  • 針對發現的未經授權的更改發起事件

--

--

運用雲端服務加速企業數位轉型

我們協助您駕馭名為"雲端運算"的怪獸,馴服它為您所用。諮詢請來信jason.kao@suros.com.tw.