Skip to content

Commit

Permalink
Merge pull request #20 from andrewwhitehead/fix/enc-profile-key
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewwhitehead authored Aug 16, 2021
2 parents c3eecb0 + ce922d5 commit a93ce8d
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 19 deletions.
48 changes: 48 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ jobs:

- name: Cache cargo resources
uses: Swatinem/rust-cache@v1
with:
sharedKey: deps

- name: Cargo check
uses: actions-rs/cargo@v1
Expand All @@ -59,6 +61,47 @@ jobs:
command: test
args: --workspace

test-postgres:
name: Postgres
runs-on: ubuntu-latest
needs: [check]

services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Install Rust toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable

- name: Cache cargo resources
uses: Swatinem/rust-cache@v1
with:
sharedKey: deps

- name: Test
uses: actions-rs/cargo@v1
env:
POSTGRES_URL: postgres://postgres:postgres@localhost:5432/test-db
with:
command: test
args: --features pg_test

build-manylinux:
name: Build Library
needs: [check]
Expand All @@ -85,6 +128,8 @@ jobs:

- name: Cache cargo resources
uses: Swatinem/rust-cache@v1
with:
sharedKey: deps

- name: Build library
env:
Expand Down Expand Up @@ -126,6 +171,8 @@ jobs:

- name: Cache cargo resources
uses: Swatinem/rust-cache@v1
with:
sharedKey: deps

- name: Build library
env:
Expand Down Expand Up @@ -183,6 +230,7 @@ jobs:
python setup.py bdist_wheel --python-tag=py3 --plat-name=${{ matrix.plat-name }}
pip install pytest pytest-asyncio dist/*
python -m pytest
TEST_STORE_URI=sqlite://test.db python -m pytest
working-directory: wrappers/python

- if: "runner.os == 'Linux'"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["askar-crypto"]

[package]
name = "aries-askar"
version = "0.2.1"
version = "0.2.2"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar secure storage"
Expand Down
2 changes: 1 addition & 1 deletion askar-crypto/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "askar-crypto"
version = "0.2.1"
version = "0.2.2"
authors = ["Hyperledger Aries Contributors <[email protected]>"]
edition = "2018"
description = "Hyperledger Aries Askar cryptography"
Expand Down
7 changes: 7 additions & 0 deletions src/backend/db_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,13 @@ pub fn init_keys<'a>(
method: StoreKeyMethod,
pass_key: PassKey<'a>,
) -> Result<(ProfileKey, Vec<u8>, StoreKey, String), Error> {
if method == StoreKeyMethod::RawKey && pass_key.is_empty() {
// disallow random key for a new database
return Err(err_msg!(
Input,
"Cannot create a store with a blank raw key"
));
}
let (store_key, store_key_ref) = method.resolve(pass_key)?;
let profile_key = ProfileKey::new()?;
let enc_profile_key = encode_profile_key(&profile_key, &store_key)?;
Expand Down
15 changes: 10 additions & 5 deletions src/backend/postgres/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,25 @@ impl Backend for PostgresStore {
fn create_profile(&self, name: Option<String>) -> BoxFuture<'_, Result<String, Error>> {
let name = name.unwrap_or_else(random_profile_name);
Box::pin(async move {
let key = ProfileKey::new()?;
let enc_key = key.to_bytes()?;
let store_key = self.key_cache.store_key.clone();
let (profile_key, enc_key) = unblock(move || {
let profile_key = ProfileKey::new()?;
let enc_key = encode_profile_key(&profile_key, &store_key)?;
Result::<_, Error>::Ok((profile_key, enc_key))
})
.await?;
let mut conn = self.conn_pool.acquire().await?;
if let Some(pid) = sqlx::query_scalar(
"INSERT INTO profiles (name, profile_key) VALUES ($1, $2)
ON CONFLICT DO NOTHING RETURNING id",
)
.bind(&name)
.bind(enc_key.as_ref())
.bind(enc_key)
.fetch_optional(&mut conn)
.await?
{
self.key_cache
.add_profile(name.clone(), pid, Arc::new(key))
.add_profile(name.clone(), pid, Arc::new(profile_key))
.await;
Ok(name)
} else {
Expand Down Expand Up @@ -585,7 +590,7 @@ async fn resolve_profile_key(
if let Some((pid, key)) = cache.get_profile(profile.as_str()).await {
Ok((pid, key))
} else {
if let Some(row) = sqlx::query("SELECT id, profile_key FROM profiles WHERE name=?1")
if let Some(row) = sqlx::query("SELECT id, profile_key FROM profiles WHERE name=$1")
.bind(profile.as_str())
.fetch_optional(conn)
.await?
Expand Down
18 changes: 13 additions & 5 deletions src/backend/postgres/test_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::PostgresStore;
use crate::{
backend::db_utils::{init_keys, random_profile_name},
error::Error,
future::{block_on, sleep, timeout, unblock},
future::{sleep, spawn_ok, timeout, unblock},
protect::{generate_raw_store_key, KeyCache, StoreKeyMethod},
storage::Store,
};
Expand Down Expand Up @@ -94,12 +94,20 @@ impl std::ops::Deref for TestDB {
impl Drop for TestDB {
fn drop(&mut self) {
if let Some(lock_txn) = self.lock_txn.take() {
block_on(lock_txn.close()).expect("Error closing database connection");
spawn_ok(async {
lock_txn
.close()
.await
.expect("Error closing database connection");
});
}
if let Some(inst) = self.inst.take() {
block_on(timeout(Duration::from_secs(30), inst.close()))
.expect("Timed out waiting for the pool connection to close")
.expect("Error closing connection pool");
spawn_ok(async {
timeout(Duration::from_secs(30), inst.close())
.await
.expect("Timed out waiting for the pool connection to close")
.expect("Error closing connection pool");
});
}
}
}
17 changes: 13 additions & 4 deletions src/backend/sqlite/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,29 @@ impl Backend for SqliteStore {
fn create_profile(&self, name: Option<String>) -> BoxFuture<'_, Result<String, Error>> {
let name = name.unwrap_or_else(random_profile_name);
Box::pin(async move {
let key = ProfileKey::new()?;
let enc_key = key.to_bytes()?;
let store_key = self.key_cache.store_key.clone();
let (profile_key, enc_key) = unblock(move || {
let profile_key = ProfileKey::new()?;
let enc_key = encode_profile_key(&profile_key, &store_key)?;
Result::<_, Error>::Ok((profile_key, enc_key))
})
.await?;
let mut conn = self.conn_pool.acquire().await?;
let done =
sqlx::query("INSERT OR IGNORE INTO profiles (name, profile_key) VALUES (?1, ?2)")
.bind(&name)
.bind(enc_key.as_ref())
.bind(enc_key)
.execute(&mut conn)
.await?;
if done.rows_affected() == 0 {
return Err(err_msg!(Duplicate, "Duplicate profile name"));
}
self.key_cache
.add_profile(name.clone(), done.last_insert_rowid(), Arc::new(key))
.add_profile(
name.clone(),
done.last_insert_rowid(),
Arc::new(profile_key),
)
.await;
Ok(name)
})
Expand Down
7 changes: 7 additions & 0 deletions tests/docker_pg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env sh
docker run --rm -p 5432:5432 --name aries-test-postgres -e POSTGRES_PASSWORD=mysecretpassword -d postgres
if [ $? != "0" ]; then
echo "Error starting postgres container"
exit 1
fi
echo POSTGRES_URL=postgres://postgres:mysecretpassword@localhost:5432/test-db cargo test --features pg_test
2 changes: 1 addition & 1 deletion wrappers/python/aries_askar/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def __init__(self, handle: StoreHandle, uri: str):
@classmethod
def generate_raw_key(cls, seed: Union[str, bytes] = None) -> str:
"""Generate a new raw key for a Store."""
bindings.generate_raw_key(seed)
return bindings.generate_raw_key(seed)

@property
def handle(self) -> StoreHandle:
Expand Down
2 changes: 1 addition & 1 deletion wrappers/python/aries_askar/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""aries_askar library wrapper version."""

__version__ = "0.2.1"
__version__ = "0.2.2"
52 changes: 51 additions & 1 deletion wrappers/python/tests/test_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
}


def raw_key() -> str:
return Store.generate_raw_key(b"00000000000000000000000000000My1")


@fixture
async def store() -> Store:
key = Store.generate_raw_key(b"00000000000000000000000000000My1")
key = raw_key()
store = await Store.provision(TEST_STORE_URI, "raw", key, recreate=True)
yield store
await store.close(remove=True)
Expand Down Expand Up @@ -179,5 +183,51 @@ async def test_key_store(store: Store):

@mark.asyncio
async def test_profile(store: Store):
# New session in the default profile
async with store as session:
# Insert a new entry
await session.insert(
TEST_ENTRY["category"],
TEST_ENTRY["name"],
TEST_ENTRY["value"],
TEST_ENTRY["tags"],
)

profile = await store.create_profile()

async with store.session(profile) as session:
# Should not find previously stored record
assert (
await session.count(
TEST_ENTRY["category"], {"~plaintag": "a", "enctag": "b"}
)
) == 0

# Insert a new entry
await session.insert(
TEST_ENTRY["category"],
TEST_ENTRY["name"],
TEST_ENTRY["value"],
TEST_ENTRY["tags"],
)
assert (
await session.count(
TEST_ENTRY["category"], {"~plaintag": "a", "enctag": "b"}
)
) == 1

if ":memory:" not in TEST_STORE_URI:
# Test accessing profile after re-opening
key = raw_key()
store_2 = await Store.open(TEST_STORE_URI, "raw", key)
print("try profile", profile)
async with store_2.session(profile) as session:
# Should not find previously stored record
assert (
await session.count(
TEST_ENTRY["category"], {"~plaintag": "a", "enctag": "b"}
)
) == 1
await store_2.close()

await store.remove_profile(profile)

0 comments on commit a93ce8d

Please sign in to comment.