sns: Begin work on Amazon SNS message handling
In order to prevent arbitrary clients from using the provisioner to retrieve WireGuard keys and Kubernetes bootstrap tokens, access to those resources *must* be restricted to the EC2 machines created by the Kubernetes Cloud Autoscaler. The key to the authentication process will be SNS notifications from AWS to indicate when new EC2 instances are created; everything that the provisioner does will be associated with an instance it discovered through an SNS notification. SNS messages are signed using PKCS#1 v1.5 RSA-SHA1, with a public key distributed in an X.509 certificate. To ensure that messages received are indeed from AWS, the provisioner will need to verify those signatures. Messages with missing or invalid signatures will be considered unsafe and ignored. The `model::sns` module includes the data structures that represent SNS messages. The `sns::sig` module includes the primitive operations for implementing signature verification.master
parent
90e5bd65ca
commit
196a43c49c
|
@ -2,6 +2,640 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf6690c370453db30743b373a60ba498fc0d6d83b11f4abfd87a84a075db5dd4"
|
||||
dependencies = [
|
||||
"asn1-rs-derive",
|
||||
"asn1-rs-impl",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-derive"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asn1-rs-impl"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea2b2456fd614d856680dcd9fcc660a51a820fa09daef2e49772b56a193c8474"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-bigint"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"crypto-bigint",
|
||||
"pem-rfc7468",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der-parser"
|
||||
version = "8.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42d4bc9b0db0a0df9ae64634ac5bdefb7afcb534e182275ca0beadbe486701c1"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"displaydoc",
|
||||
"nom",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"rusticata-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dynk8s-provisioner"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"log",
|
||||
"rsa",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"x509-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libm",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oid-registry"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d4bda43fd1b844cbc6e6e54b5444e2b1bc7838bce59ad205902cccbb26d6761"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320"
|
||||
dependencies = [
|
||||
"der",
|
||||
"pkcs8",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0"
|
||||
dependencies = [
|
||||
"der",
|
||||
"spki",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"digest",
|
||||
"num-bigint-dig",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"smallvec",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusticata-macros"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cf2781a4ca844dd4f9b608a1791eea19830df0ad3cdd9988cd05f1c66ccb63a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "x509-parser"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8"
|
||||
dependencies = [
|
||||
"asn1-rs",
|
||||
"base64",
|
||||
"data-encoding",
|
||||
"der-parser",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"oid-registry",
|
||||
"rusticata-macros",
|
||||
"thiserror",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
|
||||
|
|
|
@ -4,3 +4,10 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
base64 = "0.13.0"
|
||||
log = "0.4.17"
|
||||
rsa = "0.6.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.85"
|
||||
sha1 = "0.10.2"
|
||||
x509-parser = "0.14.0"
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
mod model;
|
||||
mod sns;
|
||||
|
||||
#[doc(hidden)]
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
//! The dynk8s provisioner data model
|
||||
pub mod sns;
|
|
@ -0,0 +1,78 @@
|
|||
//! Amazon SNS message types
|
||||
//!
|
||||
//! These message types are defined in the [Parsing message formats][0] page of
|
||||
//! the AWS Documentation.
|
||||
//!
|
||||
//! [0]: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html
|
||||
use serde::Deserialize;
|
||||
|
||||
/// SNS Subscription confirmation message
|
||||
///
|
||||
/// See also: [HTTP/HTTPS subscription confirmation JSON format][0]
|
||||
///
|
||||
/// [0]: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html#http-subscription-confirmation-json
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct SubscriptionConfirmationMessage {
|
||||
#[serde(rename = "Type")]
|
||||
pub message_type: String,
|
||||
#[serde(rename = "MessageId")]
|
||||
pub message_id: String,
|
||||
pub token: String,
|
||||
pub topic_arn: String,
|
||||
pub message: String,
|
||||
#[serde(rename = "SubscribeURL")]
|
||||
pub subscribe_url: String,
|
||||
pub timestamp: String,
|
||||
pub signature_version: String,
|
||||
pub signature: String,
|
||||
#[serde(rename = "SigningCertURL")]
|
||||
pub signing_cert_url: String,
|
||||
}
|
||||
|
||||
/// SNS Notification message
|
||||
///
|
||||
/// See also: [HTTP/HTTPS notification JSON format][0]
|
||||
///
|
||||
/// [0]: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html#http-notification-json
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct NotificationMessage {
|
||||
#[serde(rename = "Type")]
|
||||
pub message_type: String,
|
||||
#[serde(rename = "MessageId")]
|
||||
pub message_id: String,
|
||||
pub topic_arn: String,
|
||||
pub message: String,
|
||||
#[serde(default)]
|
||||
pub subject: Option<String>,
|
||||
pub timestamp: String,
|
||||
pub signature_version: String,
|
||||
pub signature: String,
|
||||
#[serde(rename = "SigningCertURL")]
|
||||
pub signing_cert_url: String,
|
||||
}
|
||||
|
||||
/// SNS Unsubscribe confirmation message
|
||||
///
|
||||
/// See also: [HTTP/HTTPS unsubscribe confirmation JSON format][0]
|
||||
///
|
||||
/// [0]: https://docs.aws.amazon.com/sns/latest/dg/sns-message-and-json-formats.html#http-unsubscribe-confirmation-json
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct UnsubscribeConfirmationMessage {
|
||||
#[serde(rename = "Type")]
|
||||
pub message_type: String,
|
||||
#[serde(rename = "MessageId")]
|
||||
pub message_id: String,
|
||||
pub token: String,
|
||||
pub topic_arn: String,
|
||||
pub message: String,
|
||||
#[serde(rename = "SubscribeURL")]
|
||||
pub subscribe_url: String,
|
||||
pub timestamp: String,
|
||||
pub signature_version: String,
|
||||
pub signature: String,
|
||||
#[serde(rename = "SigningCertURL")]
|
||||
pub signing_cert_url: String,
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
//! Amazon Simple Notification Service (SNS) utilities
|
||||
pub mod sig;
|
|
@ -0,0 +1,406 @@
|
|||
//! Amazon Simple Notification Service message signature verification
|
||||
//!
|
||||
//! Messages sent by Amazon SNS are signed to allow recipients to
|
||||
//! verify that they originated from Amazon and have not been spoofed.
|
||||
//! This verification process is particularly important for HTTP/HTTPS
|
||||
//! notifications, since these could easily be forged by untrusted
|
||||
//! third parties; the message format is simple and well documented.
|
||||
//!
|
||||
//! This module provides the [`SignatureVerifier`] trait as well as
|
||||
//! implementations of it for the two common SNS message types:
|
||||
//! subscription confirmation and notification.
|
||||
//!
|
||||
//! For additional information about the SNS message signature
|
||||
//! verification process, see [Verifying the signatures of Amazon SNS
|
||||
//! messages][0] in the AWS documentation.
|
||||
//!
|
||||
//! [0]: https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html
|
||||
use std::fmt;
|
||||
|
||||
use log::debug;
|
||||
use rsa::hash::Hash;
|
||||
use rsa::padding::PaddingScheme;
|
||||
use rsa::pkcs8::DecodePublicKey;
|
||||
use rsa::{PublicKey, RsaPublicKey};
|
||||
use sha1::{Digest, Sha1};
|
||||
use x509_parser::error::{PEMError, X509Error};
|
||||
use x509_parser::pem::Pem;
|
||||
|
||||
use crate::model::sns::*;
|
||||
|
||||
/// Error type for message signature verification issues
|
||||
#[derive(Debug)]
|
||||
pub enum SignatureError {
|
||||
/// An error occurred while decoding a base64 string (e.g. the signature
|
||||
/// field of a message payload)
|
||||
Base64DecodeError(base64::DecodeError),
|
||||
/// The signature could not be verified using the provided RSA key
|
||||
VerificationError(rsa::errors::Error),
|
||||
/// The RSA public key could not be loaded
|
||||
PkiError(rsa::pkcs8::spki::Error),
|
||||
/// The X.509 certificate could not be parsed
|
||||
X509Error(x509_parser::nom::Err<x509_parser::error::X509Error>),
|
||||
/// The PEM structure could not be decoded
|
||||
PEMError(PEMError),
|
||||
/// No certificate was provided for signature verification
|
||||
NoCertificate,
|
||||
/// The message specified an unsupported signature version
|
||||
UnsupportedVersion(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for SignatureError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Base64DecodeError(e) => write!(f, "{}", e),
|
||||
Self::VerificationError(e) => write!(f, "{}", e),
|
||||
Self::PkiError(e) => write!(f, "{}", e),
|
||||
Self::X509Error(e) => write!(f, "{}", e),
|
||||
Self::PEMError(e) => write!(f, "{}", e),
|
||||
Self::NoCertificate => write!(f, "No certificate supplied"),
|
||||
Self::UnsupportedVersion(v) => {
|
||||
write!(f, "Unsupported signature version: {}", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for SignatureError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match self {
|
||||
Self::Base64DecodeError(e) => Some(e),
|
||||
Self::VerificationError(e) => Some(e),
|
||||
Self::PkiError(e) => Some(e),
|
||||
Self::X509Error(e) => Some(e),
|
||||
Self::PEMError(e) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<base64::DecodeError> for SignatureError {
|
||||
fn from(e: base64::DecodeError) -> Self {
|
||||
Self::Base64DecodeError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rsa::errors::Error> for SignatureError {
|
||||
fn from(e: rsa::errors::Error) -> Self {
|
||||
Self::VerificationError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<rsa::pkcs8::spki::Error> for SignatureError {
|
||||
fn from(e: rsa::pkcs8::spki::Error) -> Self {
|
||||
Self::PkiError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<x509_parser::nom::Err<X509Error>> for SignatureError {
|
||||
fn from(e: x509_parser::nom::Err<X509Error>) -> Self {
|
||||
Self::X509Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PEMError> for SignatureError {
|
||||
fn from(e: PEMError) -> Self {
|
||||
Self::PEMError(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for SNS message signature verification
|
||||
///
|
||||
/// The provided [`SignatureVerifier::verify`] method verifies the message
|
||||
/// signature by using the data provided by the
|
||||
/// [`SignatureVerifier::as_plaintext`] and [`SignatureVerifier::signature`]
|
||||
/// methods.
|
||||
pub trait SignatureVerifier {
|
||||
/// Return the plaintext version of the message (string to sign)
|
||||
fn as_plaintext(&self) -> String;
|
||||
/// Return the message signature as an array of bytes
|
||||
fn signature(&self) -> Result<Vec<u8>, base64::DecodeError>;
|
||||
/// Return the signature version
|
||||
fn signature_version(&self) -> Option<&str>;
|
||||
|
||||
/// Verify the message signature
|
||||
///
|
||||
/// This method verifies the signature of the message using the public key
|
||||
/// included in the supplied certificate. The certificate is usually
|
||||
/// fetched from the URL included in the message body.
|
||||
fn verify<C: AsRef<[u8]>>(&self, cert: C) -> Result<(), SignatureError> {
|
||||
let ver = self.signature_version();
|
||||
match ver {
|
||||
Some("1") => {
|
||||
debug!("Verifying message using signature version 1");
|
||||
verify_sig_rsa_sha1(
|
||||
&self.as_plaintext(),
|
||||
&self.signature()?,
|
||||
cert,
|
||||
)
|
||||
}
|
||||
Some(v) => {
|
||||
return Err(SignatureError::UnsupportedVersion(v.into()))
|
||||
}
|
||||
None => {
|
||||
return Err(SignatureError::UnsupportedVersion(
|
||||
"No version specified".into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SignatureVerifier for SubscriptionConfirmationMessage {
|
||||
fn as_plaintext(&self) -> String {
|
||||
let mut s = String::new();
|
||||
s.push_str("Message\n");
|
||||
s.push_str(&self.message);
|
||||
s.push('\n');
|
||||
s.push_str("MessageId\n");
|
||||
s.push_str(&self.message_id);
|
||||
s.push('\n');
|
||||
s.push_str("SubscribeURL\n");
|
||||
s.push_str(&self.subscribe_url);
|
||||
s.push('\n');
|
||||
s.push_str("Timestamp\n");
|
||||
s.push_str(&self.timestamp);
|
||||
s.push('\n');
|
||||
s.push_str("Token\n");
|
||||
s.push_str(&self.token);
|
||||
s.push('\n');
|
||||
s.push_str("TopicArn\n");
|
||||
s.push_str(&self.topic_arn);
|
||||
s.push('\n');
|
||||
s.push_str("Type\n");
|
||||
s.push_str(&self.message_type);
|
||||
s.push('\n');
|
||||
s
|
||||
}
|
||||
|
||||
fn signature(&self) -> Result<Vec<u8>, base64::DecodeError> {
|
||||
base64::decode(&self.signature)
|
||||
}
|
||||
|
||||
fn signature_version(&self) -> Option<&str> {
|
||||
Some(&self.signature_version)
|
||||
}
|
||||
}
|
||||
|
||||
impl SignatureVerifier for NotificationMessage {
|
||||
fn as_plaintext(&self) -> String {
|
||||
let mut s = String::new();
|
||||
s.push_str("Message\n");
|
||||
s.push_str(&self.message);
|
||||
s.push('\n');
|
||||
s.push_str("MessageId\n");
|
||||
s.push_str(&self.message_id);
|
||||
s.push('\n');
|
||||
if let Some(subject) = &self.subject {
|
||||
s.push_str("Subject\n");
|
||||
s.push_str(subject);
|
||||
s.push('\n');
|
||||
}
|
||||
s.push_str("Timestamp\n");
|
||||
s.push_str(&self.timestamp);
|
||||
s.push('\n');
|
||||
s.push_str("TopicArn\n");
|
||||
s.push_str(&self.topic_arn);
|
||||
s.push('\n');
|
||||
s.push_str("Type\n");
|
||||
s.push_str(&self.message_type);
|
||||
s.push('\n');
|
||||
s
|
||||
}
|
||||
|
||||
fn signature(&self) -> Result<Vec<u8>, base64::DecodeError> {
|
||||
base64::decode(&self.signature)
|
||||
}
|
||||
|
||||
fn signature_version(&self) -> Option<&str> {
|
||||
Some(&self.signature_version)
|
||||
}
|
||||
}
|
||||
|
||||
impl SignatureVerifier for UnsubscribeConfirmationMessage {
|
||||
fn as_plaintext(&self) -> String {
|
||||
let mut s = String::new();
|
||||
s.push_str("Message\n");
|
||||
s.push_str(&self.message);
|
||||
s.push('\n');
|
||||
s.push_str("MessageId\n");
|
||||
s.push_str(&self.message_id);
|
||||
s.push('\n');
|
||||
s.push_str("SubscribeURL\n");
|
||||
s.push_str(&self.subscribe_url);
|
||||
s.push('\n');
|
||||
s.push_str("Timestamp\n");
|
||||
s.push_str(&self.timestamp);
|
||||
s.push('\n');
|
||||
s.push_str("Token\n");
|
||||
s.push_str(&self.token);
|
||||
s.push('\n');
|
||||
s.push_str("TopicArn\n");
|
||||
s.push_str(&self.topic_arn);
|
||||
s.push('\n');
|
||||
s.push_str("Type\n");
|
||||
s.push_str(&self.message_type);
|
||||
s.push('\n');
|
||||
s
|
||||
}
|
||||
|
||||
fn signature(&self) -> Result<Vec<u8>, base64::DecodeError> {
|
||||
base64::decode(&self.signature)
|
||||
}
|
||||
|
||||
fn signature_version(&self) -> Option<&str> {
|
||||
Some(&self.signature_version)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the RSA public key from a PEM-encoded certificate
|
||||
fn key_from_cert_pem<C: AsRef<[u8]>>(
|
||||
cert: C,
|
||||
) -> Result<RsaPublicKey, SignatureError> {
|
||||
for pem in Pem::iter_from_buffer(cert.as_ref()) {
|
||||
let pem = pem?;
|
||||
let x509 = pem.parse_x509()?;
|
||||
return Ok(RsaPublicKey::from_public_key_der(x509.public_key().raw)?);
|
||||
}
|
||||
Err(SignatureError::NoCertificate)
|
||||
}
|
||||
|
||||
/// Verify the signature of a byte array with RSA-SHA1, using the public key
|
||||
/// found in the provided PEM-encoded X.509 certificate
|
||||
fn verify_sig_rsa_sha1<T, C, S>(
|
||||
txt: T,
|
||||
sig: S,
|
||||
cert: C,
|
||||
) -> Result<(), SignatureError>
|
||||
where
|
||||
T: AsRef<[u8]>,
|
||||
S: AsRef<[u8]>,
|
||||
C: AsRef<[u8]>,
|
||||
{
|
||||
let key = key_from_cert_pem(cert.as_ref())?;
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(txt.as_ref());
|
||||
let hashed = hasher.finalize();
|
||||
let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1));
|
||||
Ok(key.verify(padding, &hashed, sig.as_ref())?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use serde_json;
|
||||
|
||||
const TEST_CERT: &str = r#"-----BEGIN CERTIFICATE-----
|
||||
MIIF2zCCBMOgAwIBAgIQCbogXPgKeqHy9lOwcjGKpTANBgkqhkiG9w0BAQsFADBG
|
||||
MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRUwEwYDVQQLEwxTZXJ2ZXIg
|
||||
Q0EgMUIxDzANBgNVBAMTBkFtYXpvbjAeFw0yMjA2MjkwMDAwMDBaFw0yMzA2MDMy
|
||||
MzU5NTlaMBwxGjAYBgNVBAMTEXNucy5hbWF6b25hd3MuY29tMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5YzF4g9Y8VUo4F8DVUcQ2pylVpAiPNyyq2VY
|
||||
5ybkw+jt7ZAKpmdnGKPdFKCfI0TuZvUBABJ6I8yz0Zw2b8oDNmF+W+9cRZ0+G2VU
|
||||
9fakJa0jRrgJBnVecjFKoGDU9YwjDXTfT4LEGWFm8PFsvsyT3cm/4yxIY2Ds4GLm
|
||||
g9ymrXBKFR41qNaRCTKU1VQ+WDXLAHpW8EfIBjIqDg0dncYGu/u0Qx3W/BVy6BPl
|
||||
xMH7exn7wJA1GO6VnDPyyKQ2fwR5ks2omE+J3qRmMYAcQCfjSDAfLw3t4oIPKK1R
|
||||
nRCdK6pgoSFxphF9QlKXn1rmNprC+MbnVnRe0CEymqhGngiQiQIDAQABo4IC7TCC
|
||||
AukwHwYDVR0jBBgwFoAUWaRmBlKge5WSPKOUByeWdFv5PdAwHQYDVR0OBBYEFMJb
|
||||
o6szSbq+Fu1RMn9G6ujEaVEIMBwGA1UdEQQVMBOCEXNucy5hbWF6b25hd3MuY29t
|
||||
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||
PQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5zY2ExYi5hbWF6b250cnVzdC5j
|
||||
b20vc2NhMWItMS5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwdQYIKwYBBQUHAQEE
|
||||
aTBnMC0GCCsGAQUFBzABhiFodHRwOi8vb2NzcC5zY2ExYi5hbWF6b250cnVzdC5j
|
||||
b20wNgYIKwYBBQUHMAKGKmh0dHA6Ly9jcnQuc2NhMWIuYW1hem9udHJ1c3QuY29t
|
||||
L3NjYTFiLmNydDAMBgNVHRMBAf8EAjAAMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFr
|
||||
AWkAdgDoPtDaPvUGNTLnVyi8iWvJA9PL0RFr7Otp4Xd9bQa9bgAAAYGtmiE9AAAE
|
||||
AwBHMEUCIELrqLuolvf1v8v/E4niiCqlo8f2+H17RVBANsyL71BJAiEA0m/JNE5l
|
||||
6hhBBedPEGpohM8s3ruGQh8lt09MZcsfT2MAdwA1zxkbv7FsV78PrUxtQsu7ticg
|
||||
JlHqP+Eq76gDwzvWTAAAAYGtmiEaAAAEAwBIMEYCIQDEqcEbX5emS67nngXRHOIg
|
||||
Zev/O4uqg1ZfgEvzaBqd7QIhAMmiWF8jFp71BVZMGwJxLifkyNT7lLEFH/SKBzXk
|
||||
aHFLAHYAs3N3B+GEUPhjhtYFqdwRCUp5LbFnDAuH3PADDnk2pZoAAAGBrZohUgAA
|
||||
BAMARzBFAiEAuUV+F7cNwWZFU2loPe7oVpVdM2dwxncLm9gJF7fv/9ICIF2xc324
|
||||
XAWRWEVosNUKY4nOiwzhVAT69/cPdEoK3En2MA0GCSqGSIb3DQEBCwUAA4IBAQAi
|
||||
YYozz0Q1hAmQf1nDyqoGzsZQCpEjGh0CrhP8FktRzEthA67dwI8qsrTzmswsotne
|
||||
nTn0dmg5esNSFwCamxDIKguCK1Bty6F7lE1Ow6WDjmFRoNvateP59Pjh6NT3IdEN
|
||||
QPBy5CfaQ4nkRKmzgtZQ71y3GdqfhWskfcXSQIzwi9LpF684a+tbV4jNLghyiSYk
|
||||
3W6jorBvXRqNXF68JsQJz27oUaJywJXJ0LtrLRJ640vhd41T0rY/RMhemvCWSDKF
|
||||
fM9rUbiv3laMUnh/Viea8UA//fYheXHkE0ZnjdKEdWV6jX0T2DqYu0ieso+Hy/aw
|
||||
Az407vZW083P5WFSIT26
|
||||
-----END CERTIFICATE-----
|
||||
"#;
|
||||
|
||||
const TEST_MSG: &str = r#"{
|
||||
"Type" : "SubscriptionConfirmation",
|
||||
"MessageId" : "5506049a-38a4-4af5-b1e2-e1c4de84c009",
|
||||
"Token" : "2336412f37fb687f5d51e6e2425dacbba7f97a62baf67e3ffa0b3da7071d369eb88d52257631cc33d52b277c7f215a6160215838db9eb1332ba95cf0418bbb0cf7037c4ab353be5f46441cb837c0cc6877623cbde0238813d4a64fce01ef705d3b8f1c3bdc86aa2f183e960ec112c984",
|
||||
"TopicArn" : "arn:aws:sns:us-east-2:566967686773:dchtest1",
|
||||
"Message" : "You have chosen to subscribe to the topic arn:aws:sns:us-east-2:566967686773:dchtest1.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
|
||||
"SubscribeURL" : "https://sns.us-east-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-2:566967686773:dchtest1&Token=2336412f37fb687f5d51e6e2425dacbba7f97a62baf67e3ffa0b3da7071d369eb88d52257631cc33d52b277c7f215a6160215838db9eb1332ba95cf0418bbb0cf7037c4ab353be5f46441cb837c0cc6877623cbde0238813d4a64fce01ef705d3b8f1c3bdc86aa2f183e960ec112c984",
|
||||
"Timestamp" : "2022-08-31T21:17:09.115Z",
|
||||
"SignatureVersion" : "1",
|
||||
"Signature" : "uPd8FxfVtenWUtcOF7iBNI6YQ6uHqGMlbc1U8/KesvnA9p2/3XEK6MJhaLcgOmLfpBhbljRFcEWPK2xBWsagX6uUk5d5mCQRkE/N+IfezLg/Q8vwTUw3rhVXZge7gl8NCCpqia1xQoSo8PbMkfAb9sw6YoytJopaPrRzvxHRTdUmyTVw2vrl8yxHD2OTRVYKpKv6Pg1Pf0VXdZq07xMRaqF2zTFK+LNYBJ74wrJRg1zLe6xfscwQytUpKf8vFHyPhP2QZWxi/mJ6YIowvXh0cElGyjox3jLxEoQ+K0jARrQSAhOBufHzd35BOAm0b7JES/YMYE58NxYHkXmoX3u1Cg==",
|
||||
"SigningCertURL" : "https://sns.us-east-2.amazonaws.com/SimpleNotificationService-56e67fcb41f6fec09b0196692625d385.pem"
|
||||
}
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn test_subscriptionconfirmation_as_plaintext() {
|
||||
let msg: SubscriptionConfirmationMessage =
|
||||
serde_json::from_str(TEST_MSG).unwrap();
|
||||
assert_eq!(
|
||||
msg.as_plaintext(),
|
||||
r#"Message
|
||||
You have chosen to subscribe to the topic arn:aws:sns:us-east-2:566967686773:dchtest1.
|
||||
To confirm the subscription, visit the SubscribeURL included in this message.
|
||||
MessageId
|
||||
5506049a-38a4-4af5-b1e2-e1c4de84c009
|
||||
SubscribeURL
|
||||
https://sns.us-east-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-east-2:566967686773:dchtest1&Token=2336412f37fb687f5d51e6e2425dacbba7f97a62baf67e3ffa0b3da7071d369eb88d52257631cc33d52b277c7f215a6160215838db9eb1332ba95cf0418bbb0cf7037c4ab353be5f46441cb837c0cc6877623cbde0238813d4a64fce01ef705d3b8f1c3bdc86aa2f183e960ec112c984
|
||||
Timestamp
|
||||
2022-08-31T21:17:09.115Z
|
||||
Token
|
||||
2336412f37fb687f5d51e6e2425dacbba7f97a62baf67e3ffa0b3da7071d369eb88d52257631cc33d52b277c7f215a6160215838db9eb1332ba95cf0418bbb0cf7037c4ab353be5f46441cb837c0cc6877623cbde0238813d4a64fce01ef705d3b8f1c3bdc86aa2f183e960ec112c984
|
||||
TopicArn
|
||||
arn:aws:sns:us-east-2:566967686773:dchtest1
|
||||
Type
|
||||
SubscriptionConfirmation
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_from_cert() {
|
||||
key_from_cert_pem(TEST_CERT).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_key_from_cert_empty() {
|
||||
match key_from_cert_pem("") {
|
||||
Err(SignatureError::NoCertificate) => (),
|
||||
_ => panic!("unexpected result"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_msg() {
|
||||
let msg: SubscriptionConfirmationMessage =
|
||||
serde_json::from_str(TEST_MSG).unwrap();
|
||||
msg.verify(TEST_CERT).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_msg_invalid() {
|
||||
let mut msg: SubscriptionConfirmationMessage =
|
||||
serde_json::from_str(TEST_MSG).unwrap();
|
||||
msg.topic_arn = msg.topic_arn.replace("1", "2");
|
||||
msg.verify(TEST_CERT).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_msg_unsupported_version() {
|
||||
let mut msg: SubscriptionConfirmationMessage =
|
||||
serde_json::from_str(TEST_MSG).unwrap();
|
||||
msg.signature_version = "2".into();
|
||||
msg.verify(TEST_CERT).unwrap_err();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue