練習 - 使用祕密保護 Webhook 承載

已完成

在本練習中,您將使用祕密來保護您的 Webhook 承載,並了解如何使用 Azure 函式來驗證承載是否確實來自 GitHub。

取得您的 Azure 函式的金鑰

  1. 在 Azure 入口網站中,回到您在課程模組的第一個練習中所建立的函式應用程式。

  2. 在左側的功能表窗格中,選取 [函式] 下的 [函式]。 [函數應用程式] 的 [函式] 窗格隨即出現。

  3. 選取您建立的 HttpTrigger1。 您函式的 [HtttpTrigger1] 窗格隨即顯示。

  4. 在左側功能表窗格中,於 [開發人員] 底下,選取 [程式碼 + 測試]。 會針對您的函式顯示 [編碼 + 測試] 窗格。

  5. 在您函式的 index.js JavaScript 檔案中,於檔案開頭處 module.exports 陳述式上方,新增對 crypto-js 程式碼程式庫的參考。

    const Crypto = require('crypto');
    
  6. 在頂端功能列上,選取 [儲存][記錄] 窗格會顯示在該窗格的底部。

  7. 在左側功能表窗格中,於 [開發人員] 底下,選取 [函式金鑰]。 會針對您的函式顯示 [函式金鑰] 窗格。

  8. [值] 資料行底下,選取 [顯示值] 連結。

  9. 選取 [複製到剪貼簿] 圖示,並儲存此金鑰以便在下一個步驟中使用。

  10. 在左側功能表窗格中,於 [開發人員] 底下,選取 [程式碼 + 測試]。 會針對您的函式顯示 [編碼 + 測試] 窗格。

  11. 在程式碼區塊中,在 context.log 陳述式之後,新增下列程式碼。 將 <default key> 取代為您剛複製到剪貼簿的預設金鑰:

    const hmac = Crypto.createHmac("sha1", "<default key>");
    const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
    

    此程式碼會使用 GitHub 相同機制計算金鑰的雜湊。

  12. 新增另一個將 sha1= 加到金鑰的開頭的 const,使其符合要求標頭中 x-hub-signature 的格式。 將下列程式碼新增至您的函式。

    const shaSignature = `sha1=${signature}`;
    
  13. 新增下列程式碼,以從要求標頭擷取 GitHub 簽章:

    const gitHubSignature = req.headers['x-hub-signature'];
    
  14. 比較兩個字串。 如果相符合,就處理要求,如下所示:

    if (!shaSignature.localeCompare(gitHubSignature)) {
        // Existing code
        if (req.body.pages[0].title) {
            ...
        }
        else {
            ...
        }
    }
    
  15. 如果字串不相符,就傳回 HTTP 401 (未經授權) 回應,其中包含告知傳送者簽章不相符的訊息。

    if (!shaSignature.localeCompare(gitHubSignature))
    {
        ...
    }
    else {
        context.res = {
            status: 401,
            body: "Signatures don't match"
        };
    }
    
    

    完整的 函式如下所示:

    const Crypto = require('crypto');
    
    module.exports = async function (context, req) {
        context.log('JavaScript HTTP trigger function processed a request.');
    
        const hmac = Crypto.createHmac("sha1", "<default key>");
        const signature = hmac.update(JSON.stringify(req.body)).digest('hex');
        const shaSignature =  `sha1=${signature}`;
        const gitHubSignature = req.headers['x-hub-signature'];
    
        if (!shaSignature.localeCompare(gitHubSignature)) {
            if (req.body.pages[0].title) {
                context.res = {
                    body: "Page is " + req.body.pages[0].title + ", Action is " + req.body.pages[0].action + ", Event Type is " + req.headers['x-github-event']
                };
            }
            else {
                context.res = {
                    status: 400,
                    body: ("Invalid payload for Wiki event")
                }
            }
        }
        else {
            context.res = {
                status: 401,
                body: "Signatures don't match"
            };
        }
    };
    
  16. 在頂端功能列上,選取 [儲存]。 會出現 [記錄] 窗格並顯示一個「已連接!」的陳述。

更新 Webhook 祕密

  1. 在 GitHub 入口網站中,切換到您的 GitHub 帳戶。

  2. 選取您的存放庫。

  3. 在頂端功能列中,選取 [Settings] (設定)。 [設定] 窗格隨即出現。

  4. 在側邊欄中,選取 [Webhooks]。 [Webhooks] 窗格隨即出現。

  5. 按一下 Webhook 旁邊的 [Edit] \(編輯\)。

  6. [祕密] 文字方塊中,輸入您先前在本練習中所儲存之函式的預設金鑰。

  7. 向下捲動至頁面底部,然後選取 [更新 Webhook][Webhooks/管理 Webhook] 窗格隨即出現。

測試 Webhook 和 Azure 函式

  1. 選取 [Recent Deliveries] \(最近的傳遞項目\) 索引標籤。

  2. 選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。

  3. 按一下 [Redeliver] \(重新傳遞\)。 在 [重新傳遞承載?] 對話方塊中,選取 [是,重新傳遞此承載]

    此動作會模擬您再次編輯您的 Wiki 頁面。

  4. 選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。

  5. [標頭] 區段中,您會看到 x-hub-signature。 您也會看到回應碼為 200,表示已成功處理要求。

    Request URL: https://testwh123456.azurewebsites.net/api/HttpTrigger1?code=aUjXIpqdJ0ZHPQuB0SzFegxGJu0nAXmsQBnmkCpJ6RYxleRaoxJ8cQ%3D%3D
    Request method: POST
    content-type: application/json
    Expect:
    User-Agent: GitHub-Hookshot/16496cb
    X-GitHub-Delivery: ce122460-6aae-11e9-99d4-de6a298a424a
    X-GitHub-Event: gollum
    X-Hub-Signature: sha1=<hash of default key>
    

測試無效簽章

  1. 在 GitHub 入口網站的 [Webhook] 頁面上,選取 [設定] 索引標籤。

  2. [祕密] 測試方塊中,選取 [變更祕密]

  3. 輸入隨機字串、向下捲動,然後選取 [Update webhook] \(更新 Webhook\)。

    Webhook 所使用的金鑰不再符合 Azure 函式預期的金鑰。

  4. 選取 [Recent Deliveries] \(最近的傳遞項目\) 索引標籤。

  5. 選取省略符號 (...) 按鈕,以選取最新 (最上面) 的傳遞項目。

  6. 選取 [重新傳遞],然後在出現的 [重新傳遞承載] 對話方塊中,選取 [是,重新傳遞此承載]

  7. 這次,您會看到回應碼為 401,表示要求未經授權。

  8. 選取省略符號按鈕 (...),以選取最新 (頂端) 的傳遞項目 (重新傳遞)。

  9. 選取 [回應] 索引標籤,然後在 [本文] 區段中,確認出現「簽章不相符」的訊息。