From 3b6d2d5e543b1ff160221e061c1d70afac411505 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 4 Apr 2024 11:31:39 +0200 Subject: [PATCH 1/6] Add `.justfile` for easier development Signed-off-by: Wiktor Kwapisiewicz --- .codespellrc | 2 +- .gitattributes | 1 + .github/workflows/ci.yml | 18 ++++++++--- .justfile | 66 ++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 5 +++ Cargo.lock | 24 +++++++-------- deny.toml | 20 ++++++++++++ scripts/hooks/pre-commit | 1 + scripts/hooks/pre-push | 5 +++ 9 files changed, 124 insertions(+), 18 deletions(-) create mode 100644 .gitattributes create mode 100755 .justfile create mode 100644 CONTRIBUTING.md create mode 100644 deny.toml create mode 120000 scripts/hooks/pre-commit create mode 100755 scripts/hooks/pre-push diff --git a/.codespellrc b/.codespellrc index e55647b..2ef9961 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,3 +1,3 @@ [codespell] -skip = .cargo,.git,target +skip = .cargo,.git,target,Cargo.lock ignore-words-list = crate,ser diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcadb2c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e354b5b..0b90935 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,8 +17,11 @@ jobs: name: Check spelling runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 + - run: cargo install --locked just + - run: sudo apt-get install -y codespell - name: Check spelling - uses: codespell-project/actions-codespell@master + run: just spelling formatting: name: Check formatting @@ -31,8 +34,11 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - run: cargo install --locked just + - run: rustup install nightly + - run: rustup component add rustfmt --toolchain nightly - name: Check formatting - run: cargo fmt --all -- --check + run: just formatting tests: name: Unit tests @@ -45,8 +51,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - - name: Build and test - run: cargo build --verbose --all && cargo test --verbose --all + - run: cargo install --locked just + - name: Run unit tests + run: just tests lints: name: Clippy lints @@ -59,8 +66,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - run: cargo install --locked just - name: Check for lints - run: cargo clippy -- -D warnings + run: just lints integration: name: Integration tests diff --git a/.justfile b/.justfile new file mode 100755 index 0000000..306d8ca --- /dev/null +++ b/.justfile @@ -0,0 +1,66 @@ +#!/usr/bin/env -S just --working-directory . --justfile +# Since this is a first recipe it's being run by default. +# Faster checks need to be executed first for better UX. For example + +# codespell is very fast. cargo fmt does not need to download crates etc. +check: spelling formatting lints dependencies tests + +# Checks common spelling mistakes +spelling: + codespell + +# Checks source code formatting +formatting: + just --unstable --fmt --check + # We're using nightly to properly group imports, see .rustfmt.toml + cargo +nightly fmt -- --check + +# Lints the source code +lints: + cargo clippy --all -- -D warnings + +# Checks for issues with dependencies +dependencies: + cargo deny check + +# Runs all unit tests. By default ignored tests are not run. Run with `ignored=true` to run only ignored tests +tests: + cargo test --all + +# Checks for commit messages +check-commits REFS='main..': + #!/usr/bin/env bash + set -euo pipefail + for commit in $(git rev-list "{{ REFS }}"); do + MSG="$(git show -s --format=%B "$commit")" + CODESPELL_RC="$(mktemp)" + git show "$commit:.codespellrc" > "$CODESPELL_RC" + if ! grep -q "Signed-off-by: " <<< "$MSG"; then + printf "Commit %s lacks \"Signed-off-by\" line.\n" "$commit" + printf "%s\n" \ + " Please use:" \ + " git rebase --signoff main && git push --force-with-lease" \ + " See https://developercertificate.org/ for more details." + exit 1; + elif ! codespell --config "$CODESPELL_RC" - <<< "$MSG"; then + printf "The spelling in commit %s needs improvement.\n" "$commit" + exit 1; + else + printf "Commit %s is good.\n" "$commit" + fi + done + +# Fixes common issues. Files need to be git add'ed +fix: + #!/usr/bin/env bash + if ! git diff-files --quiet ; then + echo "Working tree has changes. Please stage them: git add ." + exit 1 + fi + + codespell --write-changes + just --unstable --fmt + cargo clippy --fix --allow-staged + + # fmt must be last as clippy's changes may break formatting + cargo +nightly fmt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e214012 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,5 @@ +# Contributing + +```sh +git config core.hooksPath scripts/hooks/ +``` diff --git a/Cargo.lock b/Cargo.lock index 02b0b9e..8d027fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -212,9 +212,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -505,9 +505,9 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "miniz_oxide" @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -769,9 +769,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "relative-path" @@ -1028,9 +1028,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.55" +version = "2.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" dependencies = [ "proc-macro2", "quote", @@ -1045,9 +1045,9 @@ checksum = "d72e255c0541f86589b0287139b70bd941a197ea4cea8fd8f87afe9c965a99e4" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "libc", diff --git a/deny.toml b/deny.toml new file mode 100644 index 0000000..8b994eb --- /dev/null +++ b/deny.toml @@ -0,0 +1,20 @@ +[advisories] +version = 2 +yanked = "deny" +ignore = [ + "RUSTSEC-2023-0071", # the vurnerable crate is used in tests only +] + +[bans] +deny = [ +] +multiple-versions = "allow" + +[licenses] +version = 2 +allow = [ + "Apache-2.0", + "MIT", + "Unicode-DFS-2016", + "BSD-3-Clause", +] diff --git a/scripts/hooks/pre-commit b/scripts/hooks/pre-commit new file mode 120000 index 0000000..4838f41 --- /dev/null +++ b/scripts/hooks/pre-commit @@ -0,0 +1 @@ +../../.justfile \ No newline at end of file diff --git a/scripts/hooks/pre-push b/scripts/hooks/pre-push new file mode 100755 index 0000000..b5d54da --- /dev/null +++ b/scripts/hooks/pre-push @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +set -euo pipefail + +just check-commits From 4c29ff3258710b309bdec3e96248d68528cdbc04 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 4 Apr 2024 11:58:08 +0200 Subject: [PATCH 2/6] Add `SECURITY.md` file Signed-off-by: Wiktor Kwapisiewicz --- SECURITY.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..548daef --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +# Security policy + +If you have discovered a security vulnerability in this project, please report it privately. +Do not disclose it as a public issue. +This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +This project is maintained by a team of volunteers on a reasonable-effort basis. +As such, please give us at least 90 days to work on a fix before public exposure. +We will contact you back within 2 business days after reporting the issue. + +Thanks for helping make the project safe for everyone! + +## Reporting a vulnerability + +Please, report the vulnerability either through [new security advisory form][ADV] or by directly contacting our security contacts. + +[ADV]: https://github.com/wiktor-k/ssh-agent-lib/security/advisories/new + +Security contacts: + - [Wiktor Kwapisiewicz][WK], preferably encrypted with the following OpenPGP certificate: [`6539 09A2 F0E3 7C10 6F5F AF54 6C88 57E0 D8E8 F074`][KEY]. + +[WK]: https://github.com/wiktor-k +[KEY]: https://keys.openpgp.org/vks/v1/by-fingerprint/653909A2F0E37C106F5FAF546C8857E0D8E8F074 + +## Supported Versions + +Security updates are applied only to the most recent release. From 46c3b10fa7b1fe54d98cf49dca7c28f5e9a44f93 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 4 Apr 2024 12:24:45 +0200 Subject: [PATCH 3/6] Add check for dependencies Signed-off-by: Wiktor Kwapisiewicz --- .github/workflows/ci.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b90935..798b03f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,22 @@ jobs: - run: cargo install --locked just - name: Run unit tests run: just tests - + + deps: + name: Check dependencies + strategy: + matrix: + include: + - os: ubuntu-latest + - os: macos-latest + - os: windows-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + - run: cargo install --locked just cargo-deny + - name: Run unit tests + run: just dependencies + lints: name: Clippy lints strategy: From 7e4bd792f9fabc5254302dea81b940eb66ea717d Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 4 Apr 2024 12:15:31 +0200 Subject: [PATCH 4/6] Add imports grouping Signed-off-by: Wiktor Kwapisiewicz --- .rustfmt.toml | 5 +++++ examples/key_storage.rs | 30 ++++++++++++++---------------- src/agent.rs | 10 +++++----- src/lib.rs | 4 ++-- src/proto/extension.rs | 3 ++- tests/roundtrip.rs | 3 ++- 6 files changed, 30 insertions(+), 25 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..ea3b011 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,5 @@ +# CHECK: https://github.com/rust-lang/rustfmt/issues/5083 state == open +group_imports = "StdExternalCrate" + +# CHECK: https://github.com/rust-lang/rustfmt/issues/3348 state == open +format_code_in_doc_comments = true diff --git a/examples/key_storage.rs b/examples/key_storage.rs index b0faba3..876a652 100644 --- a/examples/key_storage.rs +++ b/examples/key_storage.rs @@ -1,12 +1,17 @@ +use std::error::Error; +use std::sync::{Arc, Mutex}; + use async_trait::async_trait; use log::info; +use rsa::pkcs1v15::SigningKey; +use rsa::sha2::{Sha256, Sha512}; +use rsa::signature::{RandomizedSigner, SignatureEncoding}; +use rsa::BigUint; +use sha1::Sha1; #[cfg(windows)] use ssh_agent_lib::agent::NamedPipeListener as Listener; -use ssh_agent_lib::proto::extension::SessionBind; -#[cfg(not(windows))] -use tokio::net::UnixListener as Listener; - use ssh_agent_lib::agent::{Agent, Session}; +use ssh_agent_lib::proto::extension::SessionBind; use ssh_agent_lib::proto::message::{self, Message, SignRequest}; use ssh_agent_lib::proto::{signature, AddIdentityConstrained, KeyConstraint}; use ssh_key::{ @@ -14,15 +19,8 @@ use ssh_key::{ public::PublicKey, Algorithm, Signature, }; - -use std::error::Error; -use std::sync::{Arc, Mutex}; - -use rsa::pkcs1v15::SigningKey; -use rsa::sha2::{Sha256, Sha512}; -use rsa::signature::{RandomizedSigner, SignatureEncoding}; -use rsa::BigUint; -use sha1::Sha1; +#[cfg(not(windows))] +use tokio::net::UnixListener as Listener; #[derive(Clone, PartialEq, Debug)] struct Identity { @@ -79,9 +77,9 @@ impl KeyStorage { let algorithm; let private_key = rsa::RsaPrivateKey::from_components( - BigUint::from_bytes_be(&key.public.n.as_bytes()), - BigUint::from_bytes_be(&key.public.e.as_bytes()), - BigUint::from_bytes_be(&key.private.d.as_bytes()), + BigUint::from_bytes_be(key.public.n.as_bytes()), + BigUint::from_bytes_be(key.public.e.as_bytes()), + BigUint::from_bytes_be(key.private.d.as_bytes()), vec![], )?; let mut rng = rand::thread_rng(); diff --git a/src/agent.rs b/src/agent.rs index b8a2cd1..e41b654 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -1,3 +1,8 @@ +use std::fmt; +use std::io; +use std::marker::Unpin; +use std::mem::size_of; + use async_trait::async_trait; use byteorder::{BigEndian, ReadBytesExt}; use futures::{SinkExt, TryStreamExt}; @@ -12,11 +17,6 @@ use tokio::net::{UnixListener, UnixStream}; use tokio_util::bytes::{Buf, BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder, Framed}; -use std::fmt; -use std::io; -use std::marker::Unpin; -use std::mem::size_of; - use super::error::AgentError; use super::proto::{message::Message, ProtoError}; diff --git a/src/lib.rs b/src/lib.rs index c9b22bb..38a6289 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ pub mod agent; pub mod error; #[cfg(feature = "agent")] -pub use self::agent::Agent; +pub use async_trait::async_trait; #[cfg(feature = "agent")] -pub use async_trait::async_trait; +pub use self::agent::Agent; diff --git a/src/proto/extension.rs b/src/proto/extension.rs index 157774f..567b9b3 100644 --- a/src/proto/extension.rs +++ b/src/proto/extension.rs @@ -113,10 +113,11 @@ impl Decode for KeySpec { #[cfg(test)] mod tests { - use super::*; use hex_literal::hex; use testresult::TestResult; + use super::*; + #[test] fn parse_bind() -> TestResult { let mut buffer: &[u8] = &[ diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs index f879dfa..bf5797b 100644 --- a/tests/roundtrip.rs +++ b/tests/roundtrip.rs @@ -1,7 +1,8 @@ +use std::path::PathBuf; + use rstest::rstest; use ssh_agent_lib::proto::Message; use ssh_encoding::{Decode, Encode}; -use std::path::PathBuf; use testresult::TestResult; #[rstest] From d78f4e23673fc6070d6c7e70fc15f17527b3e45b Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Fri, 5 Apr 2024 09:19:53 +0200 Subject: [PATCH 5/6] Add funding Signed-off-by: Wiktor Kwapisiewicz --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7570f60 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: wiktor-k From bd20cdb6f4755da0b096aafd7f0cc0cb5d0d1a33 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Fri, 5 Apr 2024 09:08:34 +0200 Subject: [PATCH 6/6] Add contributing guide Signed-off-by: Wiktor Kwapisiewicz --- CONTRIBUTING.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e214012..0a40cc5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,76 @@ # Contributing +Thanks for taking the time to contribute to this project! + +All changes need to: + +- pass basic checks, including tests, formatting and lints, +- be signed-off. + +## Basic checks + +We are using standard Rust ecosystem tools including `rustfmt` and `clippy` with one minor difference. +Due to a couple of `rustfmt` features being available only in nightly (see the `.rustfmt.toml` file) nightly `rustfmt` is necessary. + +All of these details are captured in a `.justfile` and can be checked by running [`just`'](https://just.systems/). + +To run all checks locally before sending them to CI you can set your git hooks directory: + ```sh git config core.hooksPath scripts/hooks/ ``` + +## Developer Certificate of Origin + +The sign-off is a simple line at the end of the git commit message, which certifies that you wrote it or otherwise have the right to pass it on as a open-source patch. + +The rules are pretty simple: if you can [certify the below][DCO]: + +``` +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. +``` + +then you just add a line saying + + Signed-off-by: Random J Developer + +using your name. + +If you set your `user.name` and `user.email`, you can sign your commit automatically with [`git commit --signoff`][GSO]. + +To sign-off your last commit: + + git commit --amend --signoff + +[DCO]: https://developercertificate.org +[GSO]: https://git-scm.com/docs/git-commit#git-commit---signoff + +If you want to fix multiple commits use: + + git rebase --signoff main + +To check if your commits are correctly signed-off locally use `just check-commits`.