微軟在 Azure 上面提供了 Private Link 這一個服務,可以將 Azure 上的 Pass 變成私有的服務,僅能透過 Private Link 才可以連線到,從外部網路是無法直接連線到,如此對於資安有較大要求的情境,就可以設計出僅在特定網路下才可以連線的架構,但是在這樣的架構下也會產生額外的需求,比如說 App Service 的部署,在這個情境下就不能像之前文章「使用 Visual Studio 部署網站到 App Service」的方式直接部署上去,因為這時候是無法從外部網路直接連線到 App Service 的,而解決的辦法最簡單的方式就是建立一台跳板機 VM,設定和 Private Link 同一個虛擬網路,再透過這一台機器進行部署,但是這樣的方式就得在每次要部署時候在連到跳板機器再去部署,還是不夠方便,因此我們可以透過 Azure DevOps 自動化部署,後面文章就來說明實做設定的流程了。
前言
微軟在 Azure 上面提供了 Private Link 這一個服務,可以將 Azure 上的 Pass 變成私有的服務,僅能透過 Private Link 才可以連線到,從外部網路是無法直接連線到,如此對於資安有較大要求的情境,就可以設計出僅在特定網路下才可以連線的架構,但是在這樣的架構下也會產生額外的需求,比如說 App Service 的部署,在這個情境下就不能像之前文章「使用 Visual Studio 部署網站到 App Service」的方式直接部署上去,因為這時候是無法從外部網路直接連線到 App Service 的,而解決的辦法最簡單的方式就是建立一台跳板機 VM,設定和 Private Link 同一個虛擬網路,再透過這一台機器進行部署,但是這樣的方式就得在每次要部署時候在連到跳板機器再去部署,還是不夠方便,因此我們可以透過 Azure DevOps 自動化部署,後面文章就來說明實做設定的流程了。
實做
建立 App Service
首先第一個是建立要我們的 App Service 站台,流程上還算簡單,就不逐步說明了,只有一點要特別說明的項目,就是在 App Service Plan 的規格上需要是 Premium 規格,因為這個規格才可以支援 Private Link。
建立好之後也先確定用原本服務網址是可以連上去的。
建立跳板 VM
再來建立一台 VM 做為未來的跳板機器使用,這邊我就單純建立一台 Windows 2022 的 VM,並開通 3389 Port,作為之後連線使用,假設要安全性更高,針對這一台 VM 可以不設定 Public IP,未來可以透過 VPN 或是 Express Route,而這部分設定又是另一個範圍的,就不在本次的討論裡面。
要特別提醒的是因為我們開通的 3389 Port,為了最基本的安全性,請至少要設定特定 IP 才可以連線,避免機器被直接攻擊。
建立 Private Link
接下來是建立 Private Link,搜尋 Private Link 就可以找到這一個服務,點選建立。
建立新的私人端點。
一如其它服務的基本資料,設定訂閱、資源群組、名稱等。
接下來選擇前面建立的 App Service,資源類型選擇 Microsoft.Web/sites
,下面就可以選擇的到我們建立的 App Service。
如果建立的 App Service 不是像前面說的 Premium 方案的話就會出現錯誤了。
接下來設定虛擬網路,這邊記得選擇前面建立的 VM 的虛擬網路,這樣才會再同一個網域內才有辦法連線到,如果是不同虛擬網路的話,不然需要再透過其它方式(VPN、Peeering等)連接多個虛擬網路。另外也會建立一個私人 DNS,之後會需要透過這一個 DNS 來解析我們服務的網址才有辦法正確連線。
接下來就可以開始建立服務了,服務建立好之後我們去再連線我們的 App Service 就會顯示 403 的錯誤畫面了。
這時候如果透過我們的跳板機器去連線的話,是可以正確連線到我們的 App Service 的。
這時候如果在 VM 裡面查詢 DNS 記錄的話也會發現站台 IP 是對應到虛擬 IP 的範圍,和我們建立起來的私人 DNS 上面設定一致。
設定 Azure DevOps Agent pools
再來是設定 Azure DevOps Agent pools,我們要將前面建立的跳板 VM 設定成 Azure DevOps 未來 CI/CD 時候使用的建置和部署機器,而前面我們已經確保 VM 可以正確連到 Private Link 之後的 App Service 了,再來就可以透過此機器來部署到 App Service。
首先取得 access tokens,後面設定上會需要用到。
先點選下方的 Show All scopes,才會出現所有的權限選項,然後選則 Agent Pool 的 Read & manage。
然後就可以複製 Access token 起來備用。
在 Azure DevOps 專案內點選 Project Setting → Agent Pools →Add Pool。
Pool type 我們選擇 Self-hosted
。
點選進入剛剛建立的 Pool ,來新增 agent。
這時候不同作業有不同的設定指令,因為前面我們建立的 VM 是 Windows 的,就使用 Windows 的方式來設定,下載安裝的壓縮包放到 VM 之後按照指令來安裝。第一段參數是解壓縮,可以直接透過 windows 程式來解壓縮就好,然後就執行設定和安裝指令。
首先執行設定指令 .\config.cmd
,第一個是設定 Server Url ,網址格式為https://dev.azure.com/{your-organization}
,驗證方式就用預設的, Access Token 如同前面取得的 Token,然後輸入 Agent pool name 等資訊,後面則還有詢問是否設定成服務執行,之後重開機就會變成背景服務自動啟動並執行,到這邊就設定好了,就可以啟動 Agent 服務了。
執行 .\run.cmd
來啟動服務,正確的連線上了。
回到 Azure DevOps 檢查, Agent 設定完成,且為連線狀態。
這邊還要另外確認 VM 是否有安裝相對應的套件,因為內建有 dotnet 但是並沒有 .NET 6,所以我另外安裝了 .NET 6。
設定 Azure DevOps Pipelines
再來就是設定 Pipeline 來做自動化的部署了。
先建立服務連線,設定連線到 Azure 訂閱。點選 Project Setting → Service connections 來建立新設定。
連線類型選擇 Azure Resource Manager。
接下來就用預設值的自動建立服務主體的方式。
接下來會帶出目前登入帳號底下有權限的 Azure 訂閱,選擇我們要部署的 App Service 所在的訂閱和資源群組就可以完成連線的設定。
再來點選 Pipelines 來建立新的設定。
選擇用傳統的方式來建立,就會有 UI 可以來協助設定。
選擇存放原始碼的 Repository。
再來我們用空的範本來設定。
先設定好我們前面建立好的 Agent Pool。
再來依序新增 4 個 Job,因為範例程式為 .NET 6 所以選擇 detnet 的指令來做設定。
再來是 Azure App Service Deploy 設定,訂閱的部分就選擇前面建立的服務連線,會帶出底下的 App Service,以及選擇前一個 Job 發佈的檔案位置。
最後就把設定儲存並執行。
如果要在每次 commit 之後自動觸發的話,就到 Triggers 選擇 Enable continuous integration。
之後等待 Job 完成就會部署到 App Service 了。
這時候再到站台重新整理就可以看到我們的站台自動部署上去了。
結論
本文主要針對的情境是 .NET 開發的站台,如果是其它語言的話,就要注意 VM 裡面是否有安裝對應的 SDK 可以編譯和部署程式,簡單的測試方式就是連到該 VM 直接下指令做編譯和部署,看是否會有錯誤,如果沒有的話只需要針對 Pipeline 去修改對應的執行指令,打包成 App Service 支援的部署格式就可以完成整個流程了。