-
Notifications
You must be signed in to change notification settings - Fork 0
/
github.rs
68 lines (59 loc) · 2.26 KB
/
github.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
// Copyright 2023 Oxide Computer Company
use async_trait::async_trait;
use dropshot::{RequestContext, ServerContext};
use hex::FromHexError;
use hmac_ext::Hmac;
use http::header::ToStrError;
use sha2::Sha256;
use thiserror::Error;
use crate::hmac::HmacSignatureVerifier;
#[derive(Debug)]
pub struct GitHubWebhookVerification;
#[derive(Debug, Error)]
pub enum GitHubWebhookVerificationError {
#[error("Failed to find key to verify requests with")]
FailedToFindKey,
#[error("Incoming request did not include a signature header")]
RequestIsMissingSignature,
#[error("Failed to decode signature header {0}")]
FailedToDecodeHeader(#[from] FromHexError),
#[error("Failed to parse signature header {0}")]
FailedToParseHeader(#[from] ToStrError),
}
#[async_trait]
impl HmacSignatureVerifier for GitHubWebhookVerification {
type Algo = Hmac<Sha256>;
type Error = GitHubWebhookVerificationError;
async fn key<Context: ServerContext>(
_: &RequestContext<Context>,
) -> Result<Vec<u8>, Self::Error> {
Ok(std::env::var("GITHUB_WEBHOOK_KEY")
.map(|key| key.into_bytes())
.map_err(|_| {
tracing::warn!("Failed to find webhook key for verifying GitHub webhooks");
GitHubWebhookVerificationError::FailedToFindKey
})?)
}
async fn signature<Context: ServerContext>(
rqctx: &RequestContext<Context>,
) -> Result<Vec<u8>, Self::Error> {
let signature = rqctx
.request
.headers()
.get("X-Hub-Signature-256")
.ok_or(GitHubWebhookVerificationError::RequestIsMissingSignature)
.and_then(|header_value| Ok(header_value.to_str()?))
.and_then(|header| {
tracing::debug!(?header, "Found GitHub signature header");
Ok(hex::decode(header.trim_start_matches("sha256="))?)
})
.map_err(|err| {
tracing::info!(?err, "GitHub webhook is missing a well-formed signature");
err
})?;
Ok(signature)
}
}