-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 601368a
Showing
18 changed files
with
888 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
root = true | ||
|
||
[*] | ||
insert_final_newline = true | ||
charset = utf-8 | ||
indent_style = space | ||
end_of_line = lf | ||
tab_width = 2 | ||
|
||
[*.rs] | ||
tab_width = 4 | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target | ||
**/*.rs.bk | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "authorized_keys" | ||
version = "0.9.0" | ||
authors = ["Liam Dawson <[email protected]>"] | ||
edition = "2018" | ||
description = "Parse and manipulate OpenSSH `authorized_keys` files" | ||
homepage = "https://github.com/hubauth/authorized_keys" | ||
repository = "https://github.com/hubauth/authorized_keys.git" | ||
readme = "README.md" | ||
keywords = ["openssh", "authorized_keys"] | ||
categories = ["config", "parser-implementations"] | ||
license = "MIT OR Apache-2.0" | ||
|
||
[dependencies] | ||
pest = { version = "2.0", optional = true } | ||
pest_derive = { version = "2.0", optional = true } | ||
data-encoding = { version = "2.1", optional = true } | ||
|
||
[features] | ||
default = ['parse'] | ||
parse = ['pest', 'pest_derive'] | ||
key_encoding = ['data-encoding'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
check: check-fmt check-tests check-clippy check-docs | ||
|
||
check-fmt: | ||
cargo fmt -- --check | ||
|
||
check-tests: | ||
cargo test | ||
cargo test --features "key_encoding" | ||
|
||
check-clippy: | ||
cargo clippy --all-targets --all-features -- -D warnings | ||
|
||
check-docs: | ||
cargo doc | ||
|
||
fix: fix-fmt | ||
|
||
fix-fmt: | ||
cargo fmt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
# authorized_keys-rs | ||
|
||
Parse and manipulate OpenSSH `authorized_keys` files. | ||
|
||
## Installation | ||
|
||
`Cargo.toml`: | ||
|
||
```toml | ||
[features] | ||
authorized_keys = "0.9" | ||
``` | ||
|
||
## Features | ||
|
||
* Parse `authorized_keys` files | ||
* Parse individual lines from `authorized_keys` files | ||
* Change the parts of a line (options, key type, encoded key, comments) | ||
with convenience methods | ||
* Write `authorized_keys` files in the correct format | ||
* Depends on `pest`, `pest_derive` by default: | ||
* `data-encoding` if you want to edit keys as bytes | ||
* No dependencies if you disable the default `parsing` feature | ||
|
||
## Contributing | ||
|
||
### Requirements | ||
|
||
* `rustc`/`cargo` 1.34+ ([`rustup`] recommended) | ||
* `cargo clippy --version` 0.0.212+ | ||
* `cargo fmt --version` 1.0.3-stable+ | ||
|
||
### Process | ||
|
||
1. Open an issue for the contribution you'd like to make | ||
* Check for duplicates first :slightly_smiling_face: | ||
1. Fork the repository, make your changes on a branch | ||
1. Add tests for new features | ||
1. Ensure `just check` passes locally | ||
1. Open a PR for the changes | ||
* Add yourself as an author to `Cargo.toml` and `README.md`, if you'd like! | ||
|
||
## Authors | ||
|
||
* [Liam Dawson](https://github.com/liamdawson) | ||
|
||
## License | ||
|
||
Rustfmt is distributed under the terms of both the MIT license and the | ||
Apache License (Version 2.0). | ||
|
||
See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Take a list of GitHub user keys, and restrict them so they can only run the command uptime (and cannot port-forward/etc) | ||
|
||
extern crate authorized_keys; | ||
|
||
use authorized_keys::openssh::v2::*; | ||
use std::iter::FromIterator; | ||
use std::str::FromStr; | ||
|
||
const SAMPLE_FILE: &str = include_str!("./harden_keys_data.txt"); | ||
|
||
fn main() { | ||
let key_file = | ||
AuthorizedKeysFile::from_str(SAMPLE_FILE).expect("that was a valid authorized_keys file!"); | ||
|
||
println!("Before:\n{}", SAMPLE_FILE); | ||
|
||
println!( | ||
"After:\n{}", | ||
AuthorizedKeysFile::from_iter(key_file.into_iter().flat_map(|line| { | ||
match line { | ||
AuthorizedKeysFileLine::Comment(_) => None, | ||
AuthorizedKeysFileLine::AuthorizedKey(key) => { | ||
Some(AuthorizedKeysFileLine::AuthorizedKey( | ||
key.clear_options() | ||
.option_name("restrict".to_owned()) | ||
.option(("command".to_owned(), Some("uptime".to_owned()))), | ||
)) | ||
} | ||
} | ||
})) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
agent-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCve8gcxEQKaue8XynCD8rG4KowiW3RGFJzOWhAvCi+WTRlujUE8zRLBBtsXcHCC85+N6g+ZjMLJql1JIhCncov7Lp5jBAiBi847RegvbALeux774PHGpc6A+xPMpEDbfMWjVXwbPG/B/A+hA1G/wMEYmfzkRi4DUyCS7wPBNWM9510WxNYZzjk0zA3o+/ezCuaeX4xzBFXkX84Z3J8bI79yuRBhqSm0MVGyh2R+w75YZbaSGhqgeWXhKtV0ZtVKOP6/nDaJ4kx2f2RguqF/E2yp/liyiggDGz53kGfJ5nizsr6SwB1qIh85m/rEiYmWib+ZrFBc1KyefV9Tpztc1dr0RcVRuXAfb+nxAVuZbDTL1A2nY9+g0byEVX6jm6uEaJ2yascaqyw0NXjhTsXR9v4H50z4wMp0l1vtCXHF3dawKdMIHjia+feFmopT8QZJm5omK3xemTqwRrdiWp6IdADwN3q1nqg1wKm5D702hzAchRJ6BOMINRBtkMn+2mQLjbmKiXoEm6Yxq1RKCG7w89wrm9tGdxrikJ/dxcdWQt2gY9YubrjsW3BpLqA+Y73KX3dv3STwKgr2kEscZO1OxE2kqHYYCGBWWR6BmXLtQ2FqRtehTRQD2QR0aIF1l/7S06HqfwC4KExV1bGyIiq9JCfAzp3KfS/H4VeRVln7WhduQ== | ||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMztcDi7sGTxckdd6GrxI7LVVwf98rnYMvnjLWL/jxiS5Iz0F4dWu3nrms3iVVD6hY4eLaNNuAocfa0CbcAQWNddomjLn+6OnQGDpm5q5I2KaOm+xgGmpj69kyrBx4QtMq0e2OcPMTY/qBTBYbILg2pW8TEx9CjuF5RJSpKbeWE1KPJGJI7pd2D/1G5ZTvbPiq6lNk3O0VhXPRw1Jlkb2ND470vif3ymC0FeA6iLyguTZY+OYIqismu1gD1UFSWNfakIgWmvIPsoOs/Z46mj7GEk82CQF6qe5fOioPle4B9zNnXWAyxiJwEnF7TAh/vul1aeGVOT58AA61wjIYp14R | ||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCvadoe8lkYt2hhTVrMrLUM7ZWmE3a3GMOUstixaWaZ+tSvk6DPIcv9AoD69YNJ+eix0BTAHovhI0WHNyWRvJCJnzJMv7bXTpwN5vNe5PjSgVdQLaZKZSLBJVOr0lMzb3SlOZD4a2TfhbAhk98ItcdlOBiDSYHB2u57kwfqAZleyW4okWBZ1zRTZjaCA6yvAVYrFFvQ+jRLSkvAvuhjH+EpvF+kJvJ7OtIZm7g05fx7HBWIL/lVJnUOYm4SFjh4vOEYsF2dE+8FlwAwt3YJiykU1kSGtOcwXWdTYqEEnhqfsi6P945UagqOvf7q2PWnQrMvoICdTLPbzU3ciInVziqt | ||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNqTam+/remPBe8o9g1eaRhT21Hp8FOPQ+FrYD5/9/E/pHm+0mrhx50ACCqslSvWKz2sk4urWk6HMj75icjyWXQhTMa8wiWRClX/Ni3HELEkM1o4lGaEMaY8TVhd8Vdd0RlckGpdt6e8oiYNplbnQwe/vqsz5Wgu2vhh8k02DtohGEPKtmsCB2s4FX1bpmRG6J0cImeO1umFubnkCF5tFPhnuuSW2xuKG94bYL6TYz7C2bHJXCk4/s/Bas9n4Pp+NYy/vYYk1KJWbyOmsMkfVxd0QJxvroLKAt1bwOWIwLN0+GZnoOgG3xX7/bZJirBaDnylt3dwQr0Mps11EI4QOp | ||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhdFJxWKJHGaTmihR6kpgseQQ8fc1NFTHUlpUW9M5QJErZ9CbPVHKXAc4gFFB85PiY2JFJyORhmZiUMPqlGRZ/CwdYQ7AoCSjaGqxi06jRynywYPkCyw/YzE+R0ZgSCrQsGrdenPz9NmWEXfmY1BDol4gO5zecg5X+EMbG35Kwhm6FqcX5j8aF+d09cQtAflFGUTAX/QUFLxZXRdtxCj7SdczFczCdsEY1SCG8LUALXdBSLJNsqwJaEUvvqkjkZuD6cAPU6pDCgifQeegzpAqVTwRE+mDG4J6p7mEqMxAOrqd9X+PZCAmENS2fo9C4BGqESe7F5vf5P/RKkiZE2pSz | ||
agent-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC7hGnhOradeDBJ6ibZYXBtCti7UGmr9B0R9QjlQlAg35gW4bpBkT+Vij01jMP+dZMDZcLxfEOmmF9QFy2KMnxa42XXb8EeXovYiNvWeqAWfzQYKo7r2pgtwMLlN+ITRktE5tnEu7F5vgkSuDTyk0s2fvrKU5u88IID0k4aqBLp14oOAIur4Z+Zm4a545XOhJ7bEvM+nn/GGlzXATq7+Vd5DTcR/hn+Hi+YOuVT7BAmRsRTrCHT0xF9NiLZTw8AevUuUiCkoGQeyxU6p0D65emqWE9Wgu7xPR1B0DVV1t4zDwWULAvmFyLgwISL2WW7RwJfckTj3VCnSD6/4OEVFTqbISUM0FPNl2s9mme9yq3e5JR8ZpcxnLRybE4Gt+8ykiUgNcBxHsM2iJB5Ine512Vip5SiVZcRBTTY7bdy0wouvMvaL8UeNWql9q/9J+37T3+AYYHesr4zsdvD0NbVVtDKcgG3YhFIs6+B5rE99vYe8QnPzg2RiSxQz1yPaZFRbfMkAGS9G9mzbouxZSYfNOONlp7Xa0xnVqq9pAYDUmZf5JzpOvwmSuhTeQ+xJTxfZ7WtKpWnSdw5khx9N0i9ex4hNo8jcLLPBqwGztAkZbFHiFqGbA9qmkCMcuTpJkPYmviWFrdNoH+JiTJMFKVojGwGYtScEG5QwgdYBpxeeUhSjQ== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Remove all comments and other human-readable data from a list of keys | ||
|
||
extern crate authorized_keys; | ||
|
||
use authorized_keys::openssh::v2::*; | ||
use std::iter::FromIterator; | ||
use std::str::FromStr; | ||
|
||
const SAMPLE_FILE: &str = include_str!("./sanitize_keys_data.txt"); | ||
|
||
fn main() { | ||
let key_file = | ||
AuthorizedKeysFile::from_str(SAMPLE_FILE).expect("that was a valid authorized_keys file!"); | ||
|
||
println!("Before:\n{}", SAMPLE_FILE); | ||
|
||
println!( | ||
"After:\n{}", | ||
AuthorizedKeysFile::from_iter(key_file.into_iter().flat_map(|line| match line { | ||
AuthorizedKeysFileLine::Comment(_) => None, | ||
AuthorizedKeysFileLine::AuthorizedKey(key) => { | ||
Some(AuthorizedKeysFileLine::AuthorizedKey(key.remove_comments())) | ||
} | ||
})) | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# this is a sample file showing the process of removing all "human | ||
# readable information", for whatever purposes. | ||
|
||
ssh-rsa AAAAuQ== here are | ||
ssh-rsa AAAAp14R some details | ||
# here's a comment about the following keys | ||
ssh-rsa AAAAziqt for humans to read | ||
|
||
ssh-rsa AAAA4QOp or non-humans, I guess | ||
ssh-rsa AAAA2pSz just probably not raw | ||
|
||
ssh-rsa AAAAjQ== CPUs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
//! Parse and manipulate OpenSSH `authorized_keys` files. | ||
//! | ||
//! This [crate] provides parsers and manipulations for OpenSSH | ||
//! `authorized_key` files. [Example usages] include validating, | ||
//! sanitizing, and hardening `authorized_keys` files. | ||
//! | ||
//! [crate]: https://crates.io/crates/authorized_keys | ||
//! [Example usages]: https://github.com/hubauth/authorized_keys/blob/master/examples/ | ||
#![deny(missing_docs)] | ||
#![warn(clippy::all, clippy::pedantic)] | ||
|
||
#[macro_use] | ||
extern crate pest_derive; | ||
|
||
pub mod openssh; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
//! Formats and functions for OpenSSH `authorized_keys` files | ||
pub mod v2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use super::models::{AuthorizedKey, AuthorizedKeysFile, AuthorizedKeysFileLine}; | ||
use std::fmt::{Display, Error, Formatter}; | ||
|
||
impl Display for AuthorizedKey { | ||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { | ||
let options = self.options_string(); | ||
|
||
if !options.is_empty() { | ||
write!(f, "{} ", options)?; | ||
} | ||
write!(f, "{}", self.key_def())?; | ||
if !self.comments.trim().is_empty() { | ||
write!(f, " {}", self.comments.trim())?; | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
impl Display for AuthorizedKeysFile { | ||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { | ||
for line in &self.lines { | ||
match line { | ||
AuthorizedKeysFileLine::Comment(val) => writeln!(f, "{}", val)?, | ||
AuthorizedKeysFileLine::AuthorizedKey(val) => writeln!(f, "{}", val)?, | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::AuthorizedKey; | ||
|
||
#[test] | ||
fn it_writes_a_key() { | ||
let mut subject = AuthorizedKey::default(); | ||
subject.key_type = "ssh-ed25519".to_owned(); | ||
subject.encoded_key = | ||
"AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM".to_owned(); | ||
|
||
assert_eq!( | ||
&subject.to_string(), | ||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM" | ||
); | ||
} | ||
|
||
#[test] | ||
fn it_writes_a_key_with_comments() { | ||
let mut subject = AuthorizedKey::default(); | ||
subject.key_type = "ssh-ed25519".to_owned(); | ||
subject.encoded_key = | ||
"AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM".to_owned(); | ||
subject.comments = " the quick brown fox jumped over the lazy dog ".to_owned(); | ||
|
||
assert_eq!(&subject.to_string(), "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM the quick brown fox jumped over the lazy dog"); | ||
} | ||
|
||
#[test] | ||
fn it_writes_a_key_with_an_option() { | ||
let mut subject = AuthorizedKey::default(); | ||
subject | ||
.options | ||
.push(("no-agent-forwarding".to_owned(), None)); | ||
subject.key_type = "ssh-ed25519".to_owned(); | ||
subject.encoded_key = | ||
"AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM".to_owned(); | ||
|
||
assert_eq!(&subject.to_string(), "no-agent-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM"); | ||
} | ||
|
||
#[test] | ||
fn it_writes_a_complex_key() { | ||
let mut subject = AuthorizedKey::default(); | ||
subject | ||
.options | ||
.push(("no-agent-forwarding".to_owned(), None)); | ||
subject.options.push(( | ||
"command".to_owned(), | ||
Some("echo \\\"Hello, world!\\\"".to_owned()), | ||
)); | ||
subject | ||
.options | ||
.push(("environment".to_owned(), Some("PATH=/bin:/sbin".to_owned()))); | ||
subject.options.push(( | ||
"environment".to_owned(), | ||
Some("LOGNAME=ssh-user".to_owned()), | ||
)); | ||
subject.key_type = "ssh-ed25519".to_owned(); | ||
subject.encoded_key = | ||
"AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM".to_owned(); | ||
subject.comments = "this is a more complex example".to_owned(); | ||
|
||
assert_eq!(&subject.to_string(), "no-agent-forwarding,command=\"echo \\\"Hello, world!\\\"\",environment=\"PATH=/bin:/sbin\",environment=\"LOGNAME=ssh-user\" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGgqo1o+dOHqeIc7A5MG53s5iYwpMQm7f3hnn+uxtHUM this is a more complex example"); | ||
} | ||
} |
Oops, something went wrong.