├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── build.rs ├── envop-agent.service ├── proto └── envop.proto └── src ├── bin ├── envop-agent.rs └── envop.rs └── lib.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | test: 9 | name: Run test 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | - macos-latest 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: actions-rs/toolchain@v1 20 | with: 21 | profile: minimal 22 | toolchain: stable 23 | - uses: Swatinem/rust-cache@v1 24 | - uses: arduino/setup-protoc@v1 25 | with: 26 | version: '3.x' 27 | - name: Run cargo test 28 | uses: actions-rs/cargo@v1 29 | with: 30 | command: test 31 | lint: 32 | name: Run lint 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v3 36 | - uses: actions-rs/toolchain@v1 37 | with: 38 | profile: minimal 39 | toolchain: stable 40 | components: rustfmt, clippy 41 | - uses: Swatinem/rust-cache@v1 42 | - name: Run cargo fmt 43 | uses: actions-rs/cargo@v1 44 | with: 45 | command: fmt 46 | args: --all -- --check 47 | - uses: arduino/setup-protoc@v1 48 | with: 49 | version: '3.x' 50 | - name: Run cargo clippy 51 | uses: actions-rs/cargo@v1 52 | with: 53 | command: clippy 54 | args: -- -D warnings 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ansi_term" 7 | version = "0.12.1" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 10 | dependencies = [ 11 | "winapi", 12 | ] 13 | 14 | [[package]] 15 | name = "anyhow" 16 | version = "1.0.65" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" 19 | 20 | [[package]] 21 | name = "async-stream" 22 | version = "0.3.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" 25 | dependencies = [ 26 | "async-stream-impl", 27 | "futures-core", 28 | ] 29 | 30 | [[package]] 31 | name = "async-stream-impl" 32 | version = "0.3.3" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" 35 | dependencies = [ 36 | "proc-macro2", 37 | "quote", 38 | "syn", 39 | ] 40 | 41 | [[package]] 42 | name = "async-trait" 43 | version = "0.1.57" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f" 46 | dependencies = [ 47 | "proc-macro2", 48 | "quote", 49 | "syn", 50 | ] 51 | 52 | [[package]] 53 | name = "atty" 54 | version = "0.2.14" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 57 | dependencies = [ 58 | "hermit-abi", 59 | "libc", 60 | "winapi", 61 | ] 62 | 63 | [[package]] 64 | name = "autocfg" 65 | version = "1.1.0" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 68 | 69 | [[package]] 70 | name = "axum" 71 | version = "0.5.16" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043" 74 | dependencies = [ 75 | "async-trait", 76 | "axum-core", 77 | "bitflags", 78 | "bytes", 79 | "futures-util", 80 | "http", 81 | "http-body", 82 | "hyper", 83 | "itoa", 84 | "matchit", 85 | "memchr", 86 | "mime", 87 | "percent-encoding", 88 | "pin-project-lite", 89 | "serde", 90 | "sync_wrapper", 91 | "tokio", 92 | "tower", 93 | "tower-http", 94 | "tower-layer", 95 | "tower-service", 96 | ] 97 | 98 | [[package]] 99 | name = "axum-core" 100 | version = "0.2.8" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b" 103 | dependencies = [ 104 | "async-trait", 105 | "bytes", 106 | "futures-util", 107 | "http", 108 | "http-body", 109 | "mime", 110 | "tower-layer", 111 | "tower-service", 112 | ] 113 | 114 | [[package]] 115 | name = "base64" 116 | version = "0.13.0" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 119 | 120 | [[package]] 121 | name = "bitflags" 122 | version = "1.3.2" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 125 | 126 | [[package]] 127 | name = "bytes" 128 | version = "1.2.1" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" 131 | 132 | [[package]] 133 | name = "cfg-if" 134 | version = "1.0.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 137 | 138 | [[package]] 139 | name = "clap" 140 | version = "3.2.22" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" 143 | dependencies = [ 144 | "atty", 145 | "bitflags", 146 | "clap_derive", 147 | "clap_lex", 148 | "indexmap", 149 | "once_cell", 150 | "strsim", 151 | "termcolor", 152 | "textwrap", 153 | ] 154 | 155 | [[package]] 156 | name = "clap_derive" 157 | version = "3.2.18" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" 160 | dependencies = [ 161 | "heck", 162 | "proc-macro-error", 163 | "proc-macro2", 164 | "quote", 165 | "syn", 166 | ] 167 | 168 | [[package]] 169 | name = "clap_lex" 170 | version = "0.2.4" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 173 | dependencies = [ 174 | "os_str_bytes", 175 | ] 176 | 177 | [[package]] 178 | name = "either" 179 | version = "1.8.0" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" 182 | 183 | [[package]] 184 | name = "envop" 185 | version = "0.2.0" 186 | dependencies = [ 187 | "anyhow", 188 | "clap", 189 | "libc", 190 | "nix", 191 | "prost", 192 | "rpassword", 193 | "secrecy", 194 | "serde", 195 | "serde_json", 196 | "tempfile", 197 | "tokio", 198 | "tokio-stream", 199 | "tonic", 200 | "tonic-build", 201 | "tower", 202 | "tracing", 203 | "tracing-subscriber", 204 | ] 205 | 206 | [[package]] 207 | name = "fastrand" 208 | version = "1.8.0" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" 211 | dependencies = [ 212 | "instant", 213 | ] 214 | 215 | [[package]] 216 | name = "fixedbitset" 217 | version = "0.4.2" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 220 | 221 | [[package]] 222 | name = "fnv" 223 | version = "1.0.7" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 226 | 227 | [[package]] 228 | name = "futures-channel" 229 | version = "0.3.24" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" 232 | dependencies = [ 233 | "futures-core", 234 | ] 235 | 236 | [[package]] 237 | name = "futures-core" 238 | version = "0.3.24" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" 241 | 242 | [[package]] 243 | name = "futures-sink" 244 | version = "0.3.24" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" 247 | 248 | [[package]] 249 | name = "futures-task" 250 | version = "0.3.24" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" 253 | 254 | [[package]] 255 | name = "futures-util" 256 | version = "0.3.24" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" 259 | dependencies = [ 260 | "futures-core", 261 | "futures-task", 262 | "pin-project-lite", 263 | "pin-utils", 264 | ] 265 | 266 | [[package]] 267 | name = "getrandom" 268 | version = "0.2.7" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 271 | dependencies = [ 272 | "cfg-if", 273 | "libc", 274 | "wasi", 275 | ] 276 | 277 | [[package]] 278 | name = "h2" 279 | version = "0.3.14" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" 282 | dependencies = [ 283 | "bytes", 284 | "fnv", 285 | "futures-core", 286 | "futures-sink", 287 | "futures-util", 288 | "http", 289 | "indexmap", 290 | "slab", 291 | "tokio", 292 | "tokio-util", 293 | "tracing", 294 | ] 295 | 296 | [[package]] 297 | name = "hashbrown" 298 | version = "0.12.3" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 301 | 302 | [[package]] 303 | name = "heck" 304 | version = "0.4.0" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 307 | 308 | [[package]] 309 | name = "hermit-abi" 310 | version = "0.1.19" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 313 | dependencies = [ 314 | "libc", 315 | ] 316 | 317 | [[package]] 318 | name = "http" 319 | version = "0.2.8" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 322 | dependencies = [ 323 | "bytes", 324 | "fnv", 325 | "itoa", 326 | ] 327 | 328 | [[package]] 329 | name = "http-body" 330 | version = "0.4.5" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 333 | dependencies = [ 334 | "bytes", 335 | "http", 336 | "pin-project-lite", 337 | ] 338 | 339 | [[package]] 340 | name = "http-range-header" 341 | version = "0.3.0" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" 344 | 345 | [[package]] 346 | name = "httparse" 347 | version = "1.8.0" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 350 | 351 | [[package]] 352 | name = "httpdate" 353 | version = "1.0.2" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 356 | 357 | [[package]] 358 | name = "hyper" 359 | version = "0.14.20" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" 362 | dependencies = [ 363 | "bytes", 364 | "futures-channel", 365 | "futures-core", 366 | "futures-util", 367 | "h2", 368 | "http", 369 | "http-body", 370 | "httparse", 371 | "httpdate", 372 | "itoa", 373 | "pin-project-lite", 374 | "socket2", 375 | "tokio", 376 | "tower-service", 377 | "tracing", 378 | "want", 379 | ] 380 | 381 | [[package]] 382 | name = "hyper-timeout" 383 | version = "0.4.1" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" 386 | dependencies = [ 387 | "hyper", 388 | "pin-project-lite", 389 | "tokio", 390 | "tokio-io-timeout", 391 | ] 392 | 393 | [[package]] 394 | name = "indexmap" 395 | version = "1.9.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 398 | dependencies = [ 399 | "autocfg", 400 | "hashbrown", 401 | ] 402 | 403 | [[package]] 404 | name = "instant" 405 | version = "0.1.12" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 408 | dependencies = [ 409 | "cfg-if", 410 | ] 411 | 412 | [[package]] 413 | name = "itertools" 414 | version = "0.10.5" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 417 | dependencies = [ 418 | "either", 419 | ] 420 | 421 | [[package]] 422 | name = "itoa" 423 | version = "1.0.3" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" 426 | 427 | [[package]] 428 | name = "lazy_static" 429 | version = "1.4.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 432 | 433 | [[package]] 434 | name = "libc" 435 | version = "0.2.133" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" 438 | 439 | [[package]] 440 | name = "log" 441 | version = "0.4.17" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 444 | dependencies = [ 445 | "cfg-if", 446 | ] 447 | 448 | [[package]] 449 | name = "matchers" 450 | version = "0.1.0" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 453 | dependencies = [ 454 | "regex-automata", 455 | ] 456 | 457 | [[package]] 458 | name = "matchit" 459 | version = "0.5.0" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb" 462 | 463 | [[package]] 464 | name = "memchr" 465 | version = "2.5.0" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 468 | 469 | [[package]] 470 | name = "memoffset" 471 | version = "0.6.5" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 474 | dependencies = [ 475 | "autocfg", 476 | ] 477 | 478 | [[package]] 479 | name = "mime" 480 | version = "0.3.16" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 483 | 484 | [[package]] 485 | name = "mio" 486 | version = "0.8.4" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" 489 | dependencies = [ 490 | "libc", 491 | "log", 492 | "wasi", 493 | "windows-sys", 494 | ] 495 | 496 | [[package]] 497 | name = "multimap" 498 | version = "0.8.3" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" 501 | 502 | [[package]] 503 | name = "nix" 504 | version = "0.25.0" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" 507 | dependencies = [ 508 | "autocfg", 509 | "bitflags", 510 | "cfg-if", 511 | "libc", 512 | "memoffset", 513 | "pin-utils", 514 | ] 515 | 516 | [[package]] 517 | name = "num_cpus" 518 | version = "1.13.1" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 521 | dependencies = [ 522 | "hermit-abi", 523 | "libc", 524 | ] 525 | 526 | [[package]] 527 | name = "once_cell" 528 | version = "1.15.0" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" 531 | 532 | [[package]] 533 | name = "os_str_bytes" 534 | version = "6.3.0" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" 537 | 538 | [[package]] 539 | name = "percent-encoding" 540 | version = "2.2.0" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 543 | 544 | [[package]] 545 | name = "petgraph" 546 | version = "0.6.2" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143" 549 | dependencies = [ 550 | "fixedbitset", 551 | "indexmap", 552 | ] 553 | 554 | [[package]] 555 | name = "pin-project" 556 | version = "1.0.12" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" 559 | dependencies = [ 560 | "pin-project-internal", 561 | ] 562 | 563 | [[package]] 564 | name = "pin-project-internal" 565 | version = "1.0.12" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" 568 | dependencies = [ 569 | "proc-macro2", 570 | "quote", 571 | "syn", 572 | ] 573 | 574 | [[package]] 575 | name = "pin-project-lite" 576 | version = "0.2.9" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 579 | 580 | [[package]] 581 | name = "pin-utils" 582 | version = "0.1.0" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 585 | 586 | [[package]] 587 | name = "ppv-lite86" 588 | version = "0.2.16" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 591 | 592 | [[package]] 593 | name = "prettyplease" 594 | version = "0.1.19" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "a49e86d2c26a24059894a3afa13fd17d063419b05dfb83f06d9c3566060c3f5a" 597 | dependencies = [ 598 | "proc-macro2", 599 | "syn", 600 | ] 601 | 602 | [[package]] 603 | name = "proc-macro-error" 604 | version = "1.0.4" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 607 | dependencies = [ 608 | "proc-macro-error-attr", 609 | "proc-macro2", 610 | "quote", 611 | "syn", 612 | "version_check", 613 | ] 614 | 615 | [[package]] 616 | name = "proc-macro-error-attr" 617 | version = "1.0.4" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 620 | dependencies = [ 621 | "proc-macro2", 622 | "quote", 623 | "version_check", 624 | ] 625 | 626 | [[package]] 627 | name = "proc-macro2" 628 | version = "1.0.44" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" 631 | dependencies = [ 632 | "unicode-ident", 633 | ] 634 | 635 | [[package]] 636 | name = "prost" 637 | version = "0.11.0" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "399c3c31cdec40583bb68f0b18403400d01ec4289c383aa047560439952c4dd7" 640 | dependencies = [ 641 | "bytes", 642 | "prost-derive", 643 | ] 644 | 645 | [[package]] 646 | name = "prost-build" 647 | version = "0.11.1" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "7f835c582e6bd972ba8347313300219fed5bfa52caf175298d860b61ff6069bb" 650 | dependencies = [ 651 | "bytes", 652 | "heck", 653 | "itertools", 654 | "lazy_static", 655 | "log", 656 | "multimap", 657 | "petgraph", 658 | "prost", 659 | "prost-types", 660 | "regex", 661 | "tempfile", 662 | "which", 663 | ] 664 | 665 | [[package]] 666 | name = "prost-derive" 667 | version = "0.11.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364" 670 | dependencies = [ 671 | "anyhow", 672 | "itertools", 673 | "proc-macro2", 674 | "quote", 675 | "syn", 676 | ] 677 | 678 | [[package]] 679 | name = "prost-types" 680 | version = "0.11.1" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "4dfaa718ad76a44b3415e6c4d53b17c8f99160dcb3a99b10470fce8ad43f6e3e" 683 | dependencies = [ 684 | "bytes", 685 | "prost", 686 | ] 687 | 688 | [[package]] 689 | name = "quote" 690 | version = "1.0.21" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" 693 | dependencies = [ 694 | "proc-macro2", 695 | ] 696 | 697 | [[package]] 698 | name = "rand" 699 | version = "0.8.5" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 702 | dependencies = [ 703 | "libc", 704 | "rand_chacha", 705 | "rand_core", 706 | ] 707 | 708 | [[package]] 709 | name = "rand_chacha" 710 | version = "0.3.1" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 713 | dependencies = [ 714 | "ppv-lite86", 715 | "rand_core", 716 | ] 717 | 718 | [[package]] 719 | name = "rand_core" 720 | version = "0.6.4" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 723 | dependencies = [ 724 | "getrandom", 725 | ] 726 | 727 | [[package]] 728 | name = "redox_syscall" 729 | version = "0.2.16" 730 | source = "registry+https://github.com/rust-lang/crates.io-index" 731 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 732 | dependencies = [ 733 | "bitflags", 734 | ] 735 | 736 | [[package]] 737 | name = "regex" 738 | version = "1.6.0" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 741 | dependencies = [ 742 | "regex-syntax", 743 | ] 744 | 745 | [[package]] 746 | name = "regex-automata" 747 | version = "0.1.10" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 750 | dependencies = [ 751 | "regex-syntax", 752 | ] 753 | 754 | [[package]] 755 | name = "regex-syntax" 756 | version = "0.6.27" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 759 | 760 | [[package]] 761 | name = "remove_dir_all" 762 | version = "0.5.3" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 765 | dependencies = [ 766 | "winapi", 767 | ] 768 | 769 | [[package]] 770 | name = "rpassword" 771 | version = "6.0.1" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "2bf099a1888612545b683d2661a1940089f6c2e5a8e38979b2159da876bfd956" 774 | dependencies = [ 775 | "libc", 776 | "serde", 777 | "serde_json", 778 | "winapi", 779 | ] 780 | 781 | [[package]] 782 | name = "ryu" 783 | version = "1.0.11" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" 786 | 787 | [[package]] 788 | name = "secrecy" 789 | version = "0.8.0" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" 792 | dependencies = [ 793 | "zeroize", 794 | ] 795 | 796 | [[package]] 797 | name = "serde" 798 | version = "1.0.145" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" 801 | dependencies = [ 802 | "serde_derive", 803 | ] 804 | 805 | [[package]] 806 | name = "serde_derive" 807 | version = "1.0.145" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" 810 | dependencies = [ 811 | "proc-macro2", 812 | "quote", 813 | "syn", 814 | ] 815 | 816 | [[package]] 817 | name = "serde_json" 818 | version = "1.0.85" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" 821 | dependencies = [ 822 | "itoa", 823 | "ryu", 824 | "serde", 825 | ] 826 | 827 | [[package]] 828 | name = "sharded-slab" 829 | version = "0.1.4" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 832 | dependencies = [ 833 | "lazy_static", 834 | ] 835 | 836 | [[package]] 837 | name = "signal-hook-registry" 838 | version = "1.4.0" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 841 | dependencies = [ 842 | "libc", 843 | ] 844 | 845 | [[package]] 846 | name = "slab" 847 | version = "0.4.7" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 850 | dependencies = [ 851 | "autocfg", 852 | ] 853 | 854 | [[package]] 855 | name = "smallvec" 856 | version = "1.9.0" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" 859 | 860 | [[package]] 861 | name = "socket2" 862 | version = "0.4.7" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 865 | dependencies = [ 866 | "libc", 867 | "winapi", 868 | ] 869 | 870 | [[package]] 871 | name = "strsim" 872 | version = "0.10.0" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 875 | 876 | [[package]] 877 | name = "syn" 878 | version = "1.0.100" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" 881 | dependencies = [ 882 | "proc-macro2", 883 | "quote", 884 | "unicode-ident", 885 | ] 886 | 887 | [[package]] 888 | name = "sync_wrapper" 889 | version = "0.1.1" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8" 892 | 893 | [[package]] 894 | name = "tempfile" 895 | version = "3.3.0" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 898 | dependencies = [ 899 | "cfg-if", 900 | "fastrand", 901 | "libc", 902 | "redox_syscall", 903 | "remove_dir_all", 904 | "winapi", 905 | ] 906 | 907 | [[package]] 908 | name = "termcolor" 909 | version = "1.1.3" 910 | source = "registry+https://github.com/rust-lang/crates.io-index" 911 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 912 | dependencies = [ 913 | "winapi-util", 914 | ] 915 | 916 | [[package]] 917 | name = "textwrap" 918 | version = "0.15.1" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" 921 | 922 | [[package]] 923 | name = "thread_local" 924 | version = "1.1.4" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 927 | dependencies = [ 928 | "once_cell", 929 | ] 930 | 931 | [[package]] 932 | name = "tokio" 933 | version = "1.21.1" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95" 936 | dependencies = [ 937 | "autocfg", 938 | "bytes", 939 | "libc", 940 | "memchr", 941 | "mio", 942 | "num_cpus", 943 | "once_cell", 944 | "pin-project-lite", 945 | "signal-hook-registry", 946 | "socket2", 947 | "tokio-macros", 948 | "winapi", 949 | ] 950 | 951 | [[package]] 952 | name = "tokio-io-timeout" 953 | version = "1.2.0" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" 956 | dependencies = [ 957 | "pin-project-lite", 958 | "tokio", 959 | ] 960 | 961 | [[package]] 962 | name = "tokio-macros" 963 | version = "1.8.0" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" 966 | dependencies = [ 967 | "proc-macro2", 968 | "quote", 969 | "syn", 970 | ] 971 | 972 | [[package]] 973 | name = "tokio-stream" 974 | version = "0.1.10" 975 | source = "registry+https://github.com/rust-lang/crates.io-index" 976 | checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af" 977 | dependencies = [ 978 | "futures-core", 979 | "pin-project-lite", 980 | "tokio", 981 | ] 982 | 983 | [[package]] 984 | name = "tokio-util" 985 | version = "0.7.4" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" 988 | dependencies = [ 989 | "bytes", 990 | "futures-core", 991 | "futures-sink", 992 | "pin-project-lite", 993 | "tokio", 994 | "tracing", 995 | ] 996 | 997 | [[package]] 998 | name = "tonic" 999 | version = "0.8.1" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "11cd56bdb54ef93935a6a79dbd1d91f1ebd4c64150fd61654031fd6b8b775c91" 1002 | dependencies = [ 1003 | "async-stream", 1004 | "async-trait", 1005 | "axum", 1006 | "base64", 1007 | "bytes", 1008 | "futures-core", 1009 | "futures-util", 1010 | "h2", 1011 | "http", 1012 | "http-body", 1013 | "hyper", 1014 | "hyper-timeout", 1015 | "percent-encoding", 1016 | "pin-project", 1017 | "prost", 1018 | "prost-derive", 1019 | "tokio", 1020 | "tokio-stream", 1021 | "tokio-util", 1022 | "tower", 1023 | "tower-layer", 1024 | "tower-service", 1025 | "tracing", 1026 | "tracing-futures", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "tonic-build" 1031 | version = "0.8.0" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "2fbcd2800e34e743b9ae795867d5f77b535d3a3be69fd731e39145719752df8c" 1034 | dependencies = [ 1035 | "prettyplease", 1036 | "proc-macro2", 1037 | "prost-build", 1038 | "quote", 1039 | "syn", 1040 | ] 1041 | 1042 | [[package]] 1043 | name = "tower" 1044 | version = "0.4.13" 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" 1046 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1047 | dependencies = [ 1048 | "futures-core", 1049 | "futures-util", 1050 | "indexmap", 1051 | "pin-project", 1052 | "pin-project-lite", 1053 | "rand", 1054 | "slab", 1055 | "tokio", 1056 | "tokio-util", 1057 | "tower-layer", 1058 | "tower-service", 1059 | "tracing", 1060 | ] 1061 | 1062 | [[package]] 1063 | name = "tower-http" 1064 | version = "0.3.4" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba" 1067 | dependencies = [ 1068 | "bitflags", 1069 | "bytes", 1070 | "futures-core", 1071 | "futures-util", 1072 | "http", 1073 | "http-body", 1074 | "http-range-header", 1075 | "pin-project-lite", 1076 | "tower", 1077 | "tower-layer", 1078 | "tower-service", 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "tower-layer" 1083 | version = "0.3.1" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62" 1086 | 1087 | [[package]] 1088 | name = "tower-service" 1089 | version = "0.3.2" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1092 | 1093 | [[package]] 1094 | name = "tracing" 1095 | version = "0.1.36" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" 1098 | dependencies = [ 1099 | "cfg-if", 1100 | "log", 1101 | "pin-project-lite", 1102 | "tracing-attributes", 1103 | "tracing-core", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "tracing-attributes" 1108 | version = "0.1.22" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" 1111 | dependencies = [ 1112 | "proc-macro2", 1113 | "quote", 1114 | "syn", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "tracing-core" 1119 | version = "0.1.29" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" 1122 | dependencies = [ 1123 | "once_cell", 1124 | "valuable", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "tracing-futures" 1129 | version = "0.2.5" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" 1132 | dependencies = [ 1133 | "pin-project", 1134 | "tracing", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "tracing-log" 1139 | version = "0.1.3" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 1142 | dependencies = [ 1143 | "lazy_static", 1144 | "log", 1145 | "tracing-core", 1146 | ] 1147 | 1148 | [[package]] 1149 | name = "tracing-subscriber" 1150 | version = "0.3.15" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" 1153 | dependencies = [ 1154 | "ansi_term", 1155 | "matchers", 1156 | "once_cell", 1157 | "regex", 1158 | "sharded-slab", 1159 | "smallvec", 1160 | "thread_local", 1161 | "tracing", 1162 | "tracing-core", 1163 | "tracing-log", 1164 | ] 1165 | 1166 | [[package]] 1167 | name = "try-lock" 1168 | version = "0.2.3" 1169 | source = "registry+https://github.com/rust-lang/crates.io-index" 1170 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1171 | 1172 | [[package]] 1173 | name = "unicode-ident" 1174 | version = "1.0.4" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" 1177 | 1178 | [[package]] 1179 | name = "valuable" 1180 | version = "0.1.0" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 1183 | 1184 | [[package]] 1185 | name = "version_check" 1186 | version = "0.9.4" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1189 | 1190 | [[package]] 1191 | name = "want" 1192 | version = "0.3.0" 1193 | source = "registry+https://github.com/rust-lang/crates.io-index" 1194 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1195 | dependencies = [ 1196 | "log", 1197 | "try-lock", 1198 | ] 1199 | 1200 | [[package]] 1201 | name = "wasi" 1202 | version = "0.11.0+wasi-snapshot-preview1" 1203 | source = "registry+https://github.com/rust-lang/crates.io-index" 1204 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1205 | 1206 | [[package]] 1207 | name = "which" 1208 | version = "4.3.0" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" 1211 | dependencies = [ 1212 | "either", 1213 | "libc", 1214 | "once_cell", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "winapi" 1219 | version = "0.3.9" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1222 | dependencies = [ 1223 | "winapi-i686-pc-windows-gnu", 1224 | "winapi-x86_64-pc-windows-gnu", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "winapi-i686-pc-windows-gnu" 1229 | version = "0.4.0" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1232 | 1233 | [[package]] 1234 | name = "winapi-util" 1235 | version = "0.1.5" 1236 | source = "registry+https://github.com/rust-lang/crates.io-index" 1237 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1238 | dependencies = [ 1239 | "winapi", 1240 | ] 1241 | 1242 | [[package]] 1243 | name = "winapi-x86_64-pc-windows-gnu" 1244 | version = "0.4.0" 1245 | source = "registry+https://github.com/rust-lang/crates.io-index" 1246 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1247 | 1248 | [[package]] 1249 | name = "windows-sys" 1250 | version = "0.36.1" 1251 | source = "registry+https://github.com/rust-lang/crates.io-index" 1252 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1253 | dependencies = [ 1254 | "windows_aarch64_msvc", 1255 | "windows_i686_gnu", 1256 | "windows_i686_msvc", 1257 | "windows_x86_64_gnu", 1258 | "windows_x86_64_msvc", 1259 | ] 1260 | 1261 | [[package]] 1262 | name = "windows_aarch64_msvc" 1263 | version = "0.36.1" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1266 | 1267 | [[package]] 1268 | name = "windows_i686_gnu" 1269 | version = "0.36.1" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1272 | 1273 | [[package]] 1274 | name = "windows_i686_msvc" 1275 | version = "0.36.1" 1276 | source = "registry+https://github.com/rust-lang/crates.io-index" 1277 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1278 | 1279 | [[package]] 1280 | name = "windows_x86_64_gnu" 1281 | version = "0.36.1" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1284 | 1285 | [[package]] 1286 | name = "windows_x86_64_msvc" 1287 | version = "0.36.1" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1290 | 1291 | [[package]] 1292 | name = "zeroize" 1293 | version = "1.5.7" 1294 | source = "registry+https://github.com/rust-lang/crates.io-index" 1295 | checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" 1296 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "envop" 3 | version = "0.2.0" 4 | authors = ["Kohei Suzuki "] 5 | edition = "2021" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [build-dependencies] 10 | tonic-build = "0.8" 11 | 12 | [dependencies] 13 | anyhow = "1" 14 | clap = { version = "3", features = ["derive"] } 15 | libc = "0.2" 16 | nix = "0.25" 17 | prost = "0.11" 18 | rpassword = "6" 19 | secrecy = "0.8" 20 | serde = { version = "1.0", features = ["derive"] } 21 | serde_json = "1" 22 | tempfile = "3" 23 | tokio = { version = "1.5", features = ["rt-multi-thread", "macros", "net", "signal", "process"] } 24 | tokio-stream = { version = "0.1", features = ["net"] } 25 | tonic = "0.8" 26 | tower = "0.4" 27 | tracing = "0.1" 28 | tracing-subscriber = { version = "0.3", features = ["env-filter"] } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kohei Suzuki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # envop 2 | Set environment variables from 1Password Secure Notes 3 | 4 | ## Prerequisites 5 | - Save values as custom fields of Secure Note with "envop" tag in "Private" vault 6 | - The field label is mapped to environment variable name 7 | - The field value is mapped to environment variable value 8 | - The field type must be "Text" or "Password" 9 | - Install 1Password CLI 10 | - https://developer.1password.com/docs/cli/get-started/ 11 | - Sign in to an account once 12 | - Run `op signin` once. ~/.config/op/config should be created. 13 | 14 | ## Usage 15 | ### with systemd 16 | Setup user units first. 17 | 18 | ``` 19 | % cp envop-agent.service ~/.config/systemd/user/envop-agent.service 20 | % systemctl --user enable --now envop-agent.service 21 | ``` 22 | 23 | Then you can connect to envop-agent managed by systemd. 24 | 25 | ``` 26 | % export ENVOP_AGENT_SOCK=$XDG_RUNTIME_DIR/envop-agent.sock 27 | % envop ${YOUR_ACCOUNT} aws printenv AWS_ACCESS_KEY_ID 28 | AKIA................ 29 | ``` 30 | 31 | ### daemonize 32 | ``` 33 | % eval "$(envop-agent)" 34 | % envop ${YOUR_ACCOUNT} aws printenv AWS_ACCESS_KEY_ID 35 | AKIA................ 36 | ``` 37 | 38 | ## For 1Password CLI v1 users 39 | `--use-1password-cli-v1` option is required. 40 | 41 | ``` 42 | % eval "$(envop-agent --use-1password-cli-v1)" 43 | % envop ${YOUR_ACCOUNT} aws printenv AWS_ACCESS_KEY_ID 44 | AKIA................ 45 | ``` 46 | 47 | ## Acknowledgments 48 | - Functionality and command line interface are heavily inspired by [envchain](https://github.com/sorah/envchain) 49 | - envop-agent implementation is based on [ssh-agent of OpenSSH project](https://github.com/openssh/openssh-portable) 50 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | tonic_build::compile_protos("proto/envop.proto")?; 3 | Ok(()) 4 | } 5 | -------------------------------------------------------------------------------- /envop-agent.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=envop agent 3 | 4 | [Service] 5 | # This unit file assumes envop-agent is installed to ~/.cargo/bin/envop-agent 6 | ExecStart=%h/.cargo/bin/envop-agent -b %t/envop-agent.sock 7 | 8 | [Install] 9 | WantedBy=default.target 10 | -------------------------------------------------------------------------------- /proto/envop.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package envop; 3 | 4 | service Agent { 5 | rpc SignIn(SignInRequest) returns (SignInResponse); 6 | rpc GetCredentials(GetCredentialsRequest) returns (GetCredentialsResponse); 7 | } 8 | 9 | message SignInRequest { 10 | string account = 1; 11 | string password = 2; 12 | } 13 | 14 | message SignInResponse { 15 | bool ok = 1; 16 | string error = 2; 17 | } 18 | 19 | message GetCredentialsRequest { 20 | string account = 1; 21 | string name = 2; 22 | string vault = 3; 23 | string tags = 4; 24 | } 25 | 26 | message GetCredentialsResponse { 27 | bool ok = 1; 28 | string error = 2; 29 | map credentials = 3; 30 | } 31 | -------------------------------------------------------------------------------- /src/bin/envop-agent.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, clap::Parser)] 2 | struct Opt { 3 | #[clap(long, help = "You have installed 1Password CLI v1 (legacy)")] 4 | use_1password_cli_v1: bool, 5 | #[clap( 6 | short, 7 | long, 8 | help = "Bind the envop-agent to the UNIX-domain socket. When this option is given, daemonize is skipped" 9 | )] 10 | bind_address: Option, 11 | } 12 | 13 | fn main() -> Result<(), anyhow::Error> { 14 | if std::env::var_os("RUST_LOG").is_none() { 15 | std::env::set_var("RUST_LOG", "info"); 16 | } 17 | tracing_subscriber::fmt::init(); 18 | use clap::Parser as _; 19 | let opt = Opt::parse(); 20 | unsafe { 21 | disable_tracing(); 22 | libc::setrlimit( 23 | libc::RLIMIT_CORE, 24 | &libc::rlimit { 25 | rlim_cur: 0, 26 | rlim_max: 0, 27 | }, 28 | ); 29 | } 30 | 31 | let old_umask = nix::sys::stat::umask(nix::sys::stat::Mode::from_bits(0o077).unwrap()); 32 | // Hold _socket_dir to keep temporary directory 33 | let (_socket_dir, socket_path, pid) = if let Some(socket_path) = opt.bind_address { 34 | let pid = std::process::id(); 35 | (None, socket_path, pid) 36 | } else { 37 | let socket_dir = tempfile::Builder::new().prefix("envop-agent-").tempdir()?; 38 | let parent_pid = std::process::id(); 39 | let socket_path = socket_dir.path().join(format!("agent.{}.sock", parent_pid)); 40 | 41 | // Perform daemonize 42 | if let nix::unistd::ForkResult::Parent { child } = unsafe { nix::unistd::fork() }? { 43 | println!( 44 | "ENVOP_AGENT_SOCK={}; export ENVOP_AGENT_SOCK;", 45 | socket_path.display() 46 | ); 47 | println!("ENVOP_AGENT_PID={}; export ENVOP_AGENT_PID;", child); 48 | std::process::exit(0); 49 | } 50 | 51 | nix::unistd::setsid()?; 52 | std::env::set_current_dir("/")?; 53 | let child_pid = std::process::id(); 54 | { 55 | use std::os::unix::io::AsRawFd as _; 56 | let dev_null = std::fs::File::open("/dev/null")?; 57 | nix::unistd::dup2(dev_null.as_raw_fd(), std::io::stdin().as_raw_fd())?; 58 | let stdout = 59 | std::fs::File::create(socket_dir.path().join(format!("stdout.{}.log", child_pid)))?; 60 | let stderr = 61 | std::fs::File::create(socket_dir.path().join(format!("stderr.{}.log", child_pid)))?; 62 | nix::unistd::dup2(stdout.as_raw_fd(), std::io::stdout().as_raw_fd())?; 63 | nix::unistd::dup2(stderr.as_raw_fd(), std::io::stderr().as_raw_fd())?; 64 | } 65 | 66 | let child_pid = std::process::id(); 67 | (Some(socket_dir), socket_path, child_pid) 68 | }; 69 | 70 | let rt = tokio::runtime::Runtime::new()?; 71 | rt.block_on(async { 72 | let uds = tokio::net::UnixListener::bind(&socket_path)?; 73 | let uds_stream = tokio_stream::wrappers::UnixListenerStream::new(uds); 74 | nix::sys::stat::umask(old_umask); 75 | 76 | tracing::info!(socket_path = %socket_path.display(), %pid, "Starting server"); 77 | tonic::transport::Server::builder() 78 | .add_service(envop::agent_server::AgentServer::new(Agent::new( 79 | AgentOptions { 80 | use_1password_cli_v1: opt.use_1password_cli_v1, 81 | }, 82 | ))) 83 | .serve_with_incoming_shutdown(uds_stream, shutdown()) 84 | .await?; 85 | tracing::info!("Exiting"); 86 | 87 | if let Err(e) = std::fs::remove_file(&socket_path) { 88 | tracing::warn!( 89 | "failed to remove socket file {}: {}", 90 | socket_path.display(), 91 | e 92 | ); 93 | } 94 | 95 | Ok(()) 96 | }) 97 | } 98 | 99 | #[cfg(target_os = "linux")] 100 | unsafe fn disable_tracing() { 101 | libc::prctl(libc::PR_SET_DUMPABLE, 0); 102 | } 103 | 104 | #[cfg(target_os = "macos")] 105 | unsafe fn disable_tracing() { 106 | libc::ptrace(libc::PT_DENY_ATTACH, 0, std::ptr::null_mut(), 0); 107 | } 108 | 109 | #[derive(Clone)] 110 | struct Token { 111 | account: String, 112 | token: secrecy::Secret, 113 | } 114 | 115 | struct Agent { 116 | token: std::sync::Arc>>, 117 | use_1password_cli_v1: bool, 118 | } 119 | 120 | struct AgentOptions { 121 | use_1password_cli_v1: bool, 122 | } 123 | 124 | impl Agent { 125 | fn new(opt: AgentOptions) -> Self { 126 | Self { 127 | token: Default::default(), 128 | use_1password_cli_v1: opt.use_1password_cli_v1, 129 | } 130 | } 131 | 132 | async fn get_credentials_v1( 133 | &self, 134 | token: Token, 135 | vault: &str, 136 | tags: &str, 137 | name: &str, 138 | ) -> Result, tonic::Status> { 139 | use secrecy::ExposeSecret as _; 140 | let session_name = format!("OP_SESSION_{}", token.account); 141 | let output = tokio::process::Command::new("op") 142 | .env(&session_name, token.token.expose_secret()) 143 | .arg("list") 144 | .arg("items") 145 | .arg("--vault") 146 | .arg(&vault) 147 | .arg("--categories") 148 | .arg("Secure Note") 149 | .arg("--tags") 150 | .arg(&tags) 151 | .output() 152 | .await 153 | .map_err(|e| tonic::Status::internal(format!("Failed to spawn op(1): {}", e)))?; 154 | if !output.status.success() { 155 | let error = String::from_utf8_lossy(&output.stderr).trim().to_owned(); 156 | return Ok(tonic::Response::new(envop::GetCredentialsResponse { 157 | ok: false, 158 | error, 159 | ..Default::default() 160 | })); 161 | } 162 | 163 | let item_summaries: Vec = 164 | serde_json::from_slice(&output.stdout).map_err(|e| { 165 | tonic::Status::internal(format!( 166 | "Failed to deserialize `op list items` output: {}", 167 | e 168 | )) 169 | })?; 170 | let mut credentials = std::collections::HashMap::new(); 171 | for item_summary in item_summaries 172 | .into_iter() 173 | .filter(|item_summary| item_summary.overview.title == name) 174 | { 175 | let output = std::process::Command::new("op") 176 | .env(&session_name, token.token.expose_secret()) 177 | .arg("get") 178 | .arg("item") 179 | .arg("--vault") 180 | .arg(&vault) 181 | .arg(&item_summary.uuid) 182 | .output()?; 183 | if !output.status.success() { 184 | eprintln!("`op get item {}` failed", item_summary.uuid); 185 | let error = String::from_utf8_lossy(&output.stderr).trim().to_owned(); 186 | return Ok(tonic::Response::new(envop::GetCredentialsResponse { 187 | ok: false, 188 | error, 189 | ..Default::default() 190 | })); 191 | } 192 | let item: ItemV1 = serde_json::from_slice(&output.stdout).map_err(|e| { 193 | tonic::Status::internal(format!( 194 | "Failed to deserialize `op get item` output: {}", 195 | e 196 | )) 197 | })?; 198 | for section in item.details.sections.into_iter() { 199 | for field in section.fields.into_iter() { 200 | if field.k == "string" || field.k == "concealed" { 201 | credentials.insert(field.t, field.v); 202 | } else { 203 | tracing::info!(field = %field.t, item = %item_summary.uuid, "Ignoring unknown field in item"); 204 | } 205 | } 206 | } 207 | } 208 | 209 | Ok(tonic::Response::new(envop::GetCredentialsResponse { 210 | ok: true, 211 | credentials, 212 | ..Default::default() 213 | })) 214 | } 215 | 216 | async fn get_credentials_v2( 217 | &self, 218 | token: Token, 219 | vault: &str, 220 | tags: &str, 221 | name: &str, 222 | ) -> Result, tonic::Status> { 223 | use secrecy::ExposeSecret as _; 224 | let session_name = format!("OP_SESSION_{}", token.account); 225 | let output = tokio::process::Command::new("op") 226 | .env(&session_name, token.token.expose_secret()) 227 | .arg("item") 228 | .arg("list") 229 | .arg("--format") 230 | .arg("json") 231 | .arg("--vault") 232 | .arg(&vault) 233 | .arg("--categories") 234 | .arg("Secure Note") 235 | .arg("--tags") 236 | .arg(&tags) 237 | .output() 238 | .await 239 | .map_err(|e| tonic::Status::internal(format!("Failed to spawn op(1): {}", e)))?; 240 | if !output.status.success() { 241 | let error = String::from_utf8_lossy(&output.stderr).trim().to_owned(); 242 | return Ok(tonic::Response::new(envop::GetCredentialsResponse { 243 | ok: false, 244 | error, 245 | ..Default::default() 246 | })); 247 | } 248 | 249 | let item_summaries: Vec = 250 | serde_json::from_slice(&output.stdout).map_err(|e| { 251 | tonic::Status::internal(format!( 252 | "Failed to deserialize `op item list` output: {}", 253 | e 254 | )) 255 | })?; 256 | let mut credentials = std::collections::HashMap::new(); 257 | for item_summary in item_summaries 258 | .into_iter() 259 | .filter(|item_summary| item_summary.title == name) 260 | { 261 | let output = std::process::Command::new("op") 262 | .env(&session_name, token.token.expose_secret()) 263 | .arg("item") 264 | .arg("get") 265 | .arg("--format") 266 | .arg("json") 267 | .arg("--vault") 268 | .arg(&vault) 269 | .arg(&item_summary.id) 270 | .output()?; 271 | if !output.status.success() { 272 | eprintln!("`op item get {}` failed", item_summary.id); 273 | let error = String::from_utf8_lossy(&output.stderr).trim().to_owned(); 274 | return Ok(tonic::Response::new(envop::GetCredentialsResponse { 275 | ok: false, 276 | error, 277 | ..Default::default() 278 | })); 279 | } 280 | let item: ItemV2 = serde_json::from_slice(&output.stdout).map_err(|e| { 281 | tonic::Status::internal(format!( 282 | "Failed to deserialize `op item get` output: {}", 283 | e 284 | )) 285 | })?; 286 | for field in item.fields.into_iter() { 287 | if let Some(value) = field.value { 288 | if field.type_ == "STRING" || field.type_ == "CONCEALED" { 289 | credentials.insert(field.label, value); 290 | } else { 291 | tracing::info!(field = %field.label, item = %item_summary.id, "Ignoring unknown field in item"); 292 | } 293 | } 294 | } 295 | } 296 | 297 | Ok(tonic::Response::new(envop::GetCredentialsResponse { 298 | ok: true, 299 | credentials, 300 | ..Default::default() 301 | })) 302 | } 303 | } 304 | 305 | #[tonic::async_trait] 306 | impl envop::agent_server::Agent for Agent { 307 | async fn sign_in( 308 | &self, 309 | request: tonic::Request, 310 | ) -> Result, tonic::Status> { 311 | use tokio::io::AsyncWriteExt as _; 312 | 313 | let message = request.into_inner(); 314 | let mut cmd = tokio::process::Command::new("op"); 315 | cmd.arg("signin").arg("--raw"); 316 | if !self.use_1password_cli_v1 { 317 | cmd.arg("--account"); 318 | } 319 | let mut child = cmd 320 | .arg(&message.account) 321 | .stdin(std::process::Stdio::piped()) 322 | .stdout(std::process::Stdio::piped()) 323 | .stderr(std::process::Stdio::piped()) 324 | .spawn() 325 | .map_err(|e| tonic::Status::internal(format!("Failed to spawn op(1): {}", e)))?; 326 | { 327 | let mut stdin = child.stdin.take().unwrap(); 328 | stdin 329 | .write_all(message.password.as_bytes()) 330 | .await 331 | .map_err(|e| tonic::Status::internal(format!("Failed to write password: {}", e)))?; 332 | } 333 | let output = child 334 | .wait_with_output() 335 | .await 336 | .map_err(|e| tonic::Status::internal(format!("Failed to wait op(1) process: {}", e)))?; 337 | if output.status.success() { 338 | let token = 339 | secrecy::Secret::new(String::from_utf8_lossy(&output.stdout).trim().to_owned()); 340 | { 341 | let mut token_ptr = self.token.lock().map_err(|e| { 342 | tonic::Status::internal(format!("Failed to lock internal token: {}", e)) 343 | })?; 344 | *token_ptr = Some(Token { 345 | account: message.account, 346 | token, 347 | }); 348 | } 349 | tracing::info!("Token was refreshed"); 350 | Ok(tonic::Response::new(envop::SignInResponse { 351 | ok: true, 352 | error: "".to_owned(), 353 | })) 354 | } else { 355 | let error = String::from_utf8_lossy(&output.stderr).trim().to_owned(); 356 | tracing::info!(%error, "SignIn was failed"); 357 | Ok(tonic::Response::new(envop::SignInResponse { 358 | ok: false, 359 | error, 360 | })) 361 | } 362 | } 363 | 364 | async fn get_credentials( 365 | &self, 366 | request: tonic::Request, 367 | ) -> Result, tonic::Status> { 368 | let message = request.into_inner(); 369 | let vault = if message.vault.is_empty() { 370 | "Private" 371 | } else { 372 | &message.vault 373 | }; 374 | let tags = if message.tags.is_empty() { 375 | "envop" 376 | } else { 377 | &message.tags 378 | }; 379 | 380 | let token = { 381 | let token_ptr = self.token.lock().map_err(|e| { 382 | tonic::Status::internal(format!("Failed to lock internal token: {}", e)) 383 | })?; 384 | if token_ptr.is_none() { 385 | return Ok(tonic::Response::new(envop::GetCredentialsResponse { 386 | ok: false, 387 | error: "Sign in was never called".to_owned(), 388 | ..Default::default() 389 | })); 390 | } 391 | token_ptr.as_ref().unwrap().clone() 392 | }; 393 | 394 | if self.use_1password_cli_v1 { 395 | self.get_credentials_v1(token, vault, tags, &message.name) 396 | .await 397 | } else { 398 | self.get_credentials_v2(token, vault, tags, &message.name) 399 | .await 400 | } 401 | } 402 | } 403 | 404 | #[derive(Debug, serde::Deserialize)] 405 | struct ItemSummaryV1 { 406 | uuid: String, 407 | overview: ItemOverview, 408 | } 409 | 410 | #[derive(Debug, serde::Deserialize)] 411 | struct ItemOverview { 412 | title: String, 413 | } 414 | 415 | #[derive(Debug, serde::Deserialize)] 416 | struct ItemV1 { 417 | details: ItemDetailsV1, 418 | } 419 | 420 | #[derive(Debug, serde::Deserialize)] 421 | struct ItemDetailsV1 { 422 | sections: Vec, 423 | } 424 | 425 | #[derive(Debug, serde::Deserialize)] 426 | struct ItemSectionV1 { 427 | fields: Vec, 428 | } 429 | 430 | #[derive(Debug, serde::Deserialize)] 431 | struct ItemFieldV1 { 432 | k: String, 433 | t: String, 434 | v: String, 435 | } 436 | 437 | #[derive(Debug, serde::Deserialize)] 438 | struct ItemSummaryV2 { 439 | id: String, 440 | title: String, 441 | } 442 | 443 | #[derive(Debug, serde::Deserialize)] 444 | struct ItemV2 { 445 | fields: Vec, 446 | } 447 | 448 | #[derive(Debug, serde::Deserialize)] 449 | struct ItemFieldV2 { 450 | #[serde(rename = "type")] 451 | type_: String, 452 | label: String, 453 | value: Option, 454 | } 455 | 456 | async fn shutdown() { 457 | let mut sigint = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt()) 458 | .expect("Failed to set signal handler for SIGINT"); 459 | let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) 460 | .expect("Failed to set signal handler for SIGTERM"); 461 | let sig = tokio::select! { 462 | _ = sigint.recv() => "SIGINT", 463 | _ = sigterm.recv() => "SIGTERM", 464 | }; 465 | tracing::info!("Got {}", sig); 466 | } 467 | -------------------------------------------------------------------------------- /src/bin/envop.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), anyhow::Error> { 2 | if std::env::var_os("RUST_LOG").is_none() { 3 | std::env::set_var("RUST_LOG", "info"); 4 | } 5 | tracing_subscriber::fmt::init(); 6 | 7 | let mut args = std::env::args(); 8 | let me = args.next().unwrap(); 9 | let account = args.next().unwrap_or_else(|| { 10 | eprintln!("Usage: {} ACCOUNT NAME PROG ARGS...", me); 11 | std::process::exit(1); 12 | }); 13 | let name = args.next().unwrap_or_else(|| { 14 | eprintln!("Usage: {} ACCOUNT NAME PROG ARGS...", me); 15 | std::process::exit(1); 16 | }); 17 | let prog = args.next().unwrap_or_else(|| { 18 | eprintln!("Usage: {} ACCOUNT NAME PROG ARGS...", me); 19 | std::process::exit(1); 20 | }); 21 | let tags = std::env::var("ENVOP_TAGS").unwrap_or_else(|_| "".to_owned()); 22 | let vault = std::env::var("ENVOP_VAULT").unwrap_or_else(|_| "".to_owned()); 23 | let request = envop::GetCredentialsRequest { 24 | account, 25 | name, 26 | tags, 27 | vault, 28 | }; 29 | 30 | let rt = tokio::runtime::Runtime::new()?; 31 | let resp = rt.block_on(get_credentials(request))?; 32 | 33 | let mut cmd = std::process::Command::new(&prog); 34 | cmd.envs(resp.credentials.into_iter()).args(args); 35 | let status = exec(cmd)?; 36 | if !status.success() { 37 | std::process::exit(status.code().unwrap_or(1)); 38 | } 39 | Ok(()) 40 | } 41 | 42 | async fn get_credentials( 43 | request: envop::GetCredentialsRequest, 44 | ) -> Result { 45 | use std::convert::TryFrom as _; 46 | 47 | let socket_path = std::env::var("ENVOP_AGENT_SOCK")?; 48 | let channel = tonic::transport::Endpoint::try_from("http://[::]:50051")? 49 | .connect_with_connector(tower::service_fn(move |_| { 50 | tokio::net::UnixStream::connect(socket_path.clone()) 51 | })) 52 | .await?; 53 | let mut client = envop::agent_client::AgentClient::new(channel); 54 | 55 | let resp = client 56 | .get_credentials(tonic::Request::new(request.clone())) 57 | .await? 58 | .into_inner(); 59 | if resp.ok { 60 | return Ok(resp); 61 | } 62 | 63 | let password = rpassword::prompt_password(format!( 64 | "Enter password for 1Password ({}): ", 65 | request.account 66 | ))?; 67 | let resp = client 68 | .sign_in(tonic::Request::new(envop::SignInRequest { 69 | account: request.account.clone(), 70 | password, 71 | })) 72 | .await? 73 | .into_inner(); 74 | if !resp.ok { 75 | return Err(anyhow::anyhow!("Failed to sign in: {}", resp.error)); 76 | } 77 | 78 | let resp = client 79 | .get_credentials(tonic::Request::new(request.clone())) 80 | .await? 81 | .into_inner(); 82 | if resp.ok { 83 | Ok(resp) 84 | } else { 85 | Err(anyhow::anyhow!("Failed to get credentials: {}", resp.error)) 86 | } 87 | } 88 | 89 | #[cfg(unix)] 90 | fn exec(mut cmd: std::process::Command) -> Result { 91 | use std::os::unix::process::CommandExt as _; 92 | Err(anyhow::Error::from(cmd.exec())) 93 | } 94 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::derive_partial_eq_without_eq)] 2 | 3 | tonic::include_proto!("envop"); 4 | --------------------------------------------------------------------------------