Skip to content

Commit

Permalink
Add support to store backup keys in vault
Browse files Browse the repository at this point in the history
  • Loading branch information
cholcombe973 committed Nov 25, 2016
1 parent 7ef9b54 commit 01ca96c
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 7 deletions.
107 changes: 107 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ version = "0.1.0"
[features]
ceph = ["ceph-rust"]
gluster = ["gfapi-sys"]
vault = ["hashicorp_vault"]

[dependencies]
ceph-rust = {git = "https://github.com/cholcombe973/ceph-rust", optional = true}
Expand All @@ -24,6 +25,7 @@ rustc-serialize = "^0.3"
tempdir = "^0.3"
time = "0.1.35"
url = "^1.2"
hashicorp_vault = {version = "^0.6", optional = true}

[dependencies.rust-acd]
git = "https://github.com/fpgaminer/rust-acd.git"
Expand Down
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,28 @@ Preserve is an encrypted backup system written in Rust. All backup data is encr

## Usage

1. Generate a keyfile
1. Generate a keyfile without vault.

```
preserve keygen --keyfile > keyfile
preserve keygen --keyfile keyfile
```

Make sure to store this keyfile in a safe place. Anyone who has access to this keyfile can read your backups and/or corrupt them.
Make sure to store this keyfile in a safe place. Anyone who has access to this keyfile can read your backups and/or corrupt them. If you build
preserve with the `vault` feature you can store the key in hashicorp-vault. Preserve will then pull down the key as needed so it doesn't need to
be stored locally.

The vault key storage uses the `.config/vault.json` file to configure it. Fields for this file are:
```
{
"host": "http://localhost:8200",
"token": "<token>",
}
```

Generating a keyfile with vault:
```
preserve keygen
```
2. Configure your backend.

Ceph is supported as a backend. Use `--backend ceph`. The ceph backend uses the
Expand Down Expand Up @@ -69,6 +84,7 @@ them use cargo build with the `--features` flag and specify either one or both
of the backends.
`cargo build --features "ceph gluster"`. Make sure you have `librados-dev` and
`glusterfs-common` installed or these backends will fail to link properly.
The vault key storage

## Test
```
Expand Down
44 changes: 40 additions & 4 deletions src/cmds/keygen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
use keystore::KeyStore;
use std::fs::OpenOptions;
use std::io::{self, BufWriter, Write};
use std::fs::{File, OpenOptions};
use std::io::{self, BufWriter, Read, Write};

use clap::ArgMatches;
use error::*;
use keystore::KeyStore;
#[cfg(feature="vault")]
use rustc_serialize::json;
#[cfg(feature="vault")]
use vault::Client;

#[cfg(feature="vault")]
#[derive(RustcDecodable)]
struct VaultConfig {
/// The url location of a vault writable host
host: String,
/// The token that can be used to write to vault
token: String,
}

#[cfg(feature="vault")]
fn save_keys_to_vault(buffer: &Vec<u8>) -> Result<()> {
let vault_config: VaultConfig = {
let mut f = try!(File::open(".config/vault.json"));
let mut s = String::new();
try!(f.read_to_string(&mut s));
try!(json::decode(&s))
};
let client = try!(Client::new(&vault_config.host, &vault_config.token));
try!(client.set_secret("backup_key", &String::from_utf8_lossy(&buffer)));
Ok(())
}

pub fn execute(args: &ArgMatches) {
// Open output file/stdout for writing
#[cfg(not(feature="vault"))]
let file: Box<Write> = match args.value_of("keyfile") {
Some(path) => {
// Won't overwrite existing file
Expand All @@ -25,14 +53,22 @@ pub fn execute(args: &ArgMatches) {
}
None => Box::new(io::stdout()),
};
#[cfg(not(feature="vault"))]
let mut writer = BufWriter::new(file);
#[cfg(feature="vault")]
let mut buffer: Vec<u8> = Vec::new();
#[cfg(feature="vault")]
let mut writer = BufWriter::new(&mut buffer);

// Create a new keystore
let keystore = KeyStore::new();

// Save the keystore to the destination (file/stdout)
match keystore.save(&mut writer) {
Ok(_) => (),
Ok(_) => {
#[cfg(feature="vault")]
save_keys_to_vault(&writer.get_ref());
}
Err(err) => {
error!("Could not write to keyfile: {}", err);
return;
Expand Down
13 changes: 13 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub enum Error {
ArchiveNotFound,
InvalidArchiveName,
BackendOnDifferentDevices,
#[cfg(feature = "vault")]
VaultError(::vault::Error),
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -66,6 +68,8 @@ impl StdError for Error {
RadosError(ref e) => e.description(),
#[cfg(feature = "gluster")]
GlusterError(ref e) => e.description(),
#[cfg(feature = "vault")]
VaultError(ref e) => e.description(),
BlockNotFound => "The specified block was not found",
ArchiveNotFound => "The specified archive was not found",
InvalidArchiveName => {
Expand Down Expand Up @@ -95,6 +99,8 @@ impl StdError for Error {
Acd(ref error) => Some(error),
#[cfg(feature = "gluster")]
GlusterError(ref error) => Some(error),
#[cfg(feature = "vault")]
VaultError(ref error) => Some(error),
#[cfg(feature = "ceph")]
RadosError(ref error) => Some(error),
ArchiveNameConflict => None,
Expand Down Expand Up @@ -138,3 +144,10 @@ impl From<::gfapi_sys::gluster::GlusterError> for Error {
GlusterError(err)
}
}

#[cfg(feature = "vault")]
impl From<::vault::Error> for Error {
fn from(err: ::vault::Error) -> Error {
VaultError(err)
}
}
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ extern crate rand;
extern crate tempdir;
extern crate time;
extern crate url;
#[cfg(feature = "vault")]
extern crate hashicorp_vault as vault;

mod archive;
mod backend;
Expand Down

0 comments on commit 01ca96c

Please sign in to comment.