Skip to content

Commit

Permalink
Merge pull request #1 from delta-incubator/web-identity
Browse files Browse the repository at this point in the history
Prepare a refactor to support WebIdentityProvider from rusoto for authentication
  • Loading branch information
rtyler authored Jul 9, 2023
2 parents c8bb0b5 + a2037e6 commit f4e21a8
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 7 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Changelog


## v0.5.0

* Remove exported `DEFAULT_MAX_RETRY_ACQUIRE_LOCK_ATTEMPTS` which is not used within the
crate
* Introduce the `sts` feature to add `WebIdentityProvider` support for
authentication
* Refactored `DynamoDbLockClient` instantiation to follow a builder pattern, start with `for_region` rather than `new`
11 changes: 9 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
[package]
name = "dynamodb_lock"
description = "Distributed lock backed by Dynamodb"
version = "0.4.3"
authors = ["Mykhailo Osypov <[email protected]>"]
version = "0.5.0"
authors = [
"Mykhailo Osypov <[email protected]>",
"R Tyler Croy <[email protected]>",
]
edition = "2018"
readme = "README.md"
license = "Apache-2.0"
Expand All @@ -18,10 +21,14 @@ uuid = { version = "1.2", features = ["serde", "v4"] }
# https://github.com/rusoto/rusoto/issues/1980
rusoto_core = { version = "0.47", default-features = false }
rusoto_dynamodb = { version = "0.47", default-features = false }
rusoto_credential = { version = "0.47", default-features = false, optional = true}
rusoto_sts = { version ="0.47", default-features = false, optional = true }
maplit = "1"
tokio = { version = "1", features = ["fs", "macros", "rt", "io-util"] }

[features]
default = ["rustls"]
sts = ["rusoto_sts",
"rusoto_credential"]
native-tls = ["rusoto_core/native-tls", "rusoto_dynamodb/native-tls"]
rustls = ["rusoto_core/rustls", "rusoto_dynamodb/rustls"]
63 changes: 58 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ use std::fmt::Debug;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};

use maplit::hashmap;
/// Re-export of [rusuto_core::Region] for convenience
pub use rusoto_core::Region;
use rusoto_core::RusotoError;
#[cfg(feature = "sts")]
use rusoto_credential::{AutoRefreshingProvider, CredentialsError};
use rusoto_dynamodb::*;
#[cfg(feature = "sts")]
use rusoto_sts::WebIdentityProvider;
use uuid::Uuid;

/// A lock that has been successfully acquired
Expand Down Expand Up @@ -54,8 +60,6 @@ pub trait LockClient: Send + Sync + Debug {
async fn release_lock(&self, lock: &LockItem) -> Result<bool, DynamoError>;
}

pub const DEFAULT_MAX_RETRY_ACQUIRE_LOCK_ATTEMPTS: u32 = 10_000;

/// DynamoDb option keys to use when creating DynamoDbOptions.
/// The same key should be used whether passing a key in the hashmap or setting it as an environment variable.
pub mod dynamo_lock_options {
Expand Down Expand Up @@ -181,6 +185,11 @@ impl LockItem {
/// Error returned by the [`DynamoDbLockClient`] API.
#[derive(thiserror::Error, Debug, PartialEq)]
pub enum DynamoError {
#[cfg(feature = "sts")]
/// Error of the underlying authentication mechanism
#[error("Failed to authenticate: {0}")]
AuthenticationError(CredentialsError),

/// Error caused by the DynamoDB table not being created.
#[error("Dynamo table not found")]
TableNotFound,
Expand Down Expand Up @@ -245,6 +254,13 @@ impl From<RusotoError<PutItemError>> for DynamoError {
}
}

#[cfg(feature = "sts")]
impl From<CredentialsError> for DynamoError {
fn from(error: CredentialsError) -> Self {
DynamoError::AuthenticationError(error)
}
}

impl From<RusotoError<GetItemError>> for DynamoError {
fn from(error: RusotoError<GetItemError>) -> Self {
match error {
Expand Down Expand Up @@ -304,8 +320,16 @@ mod vars {
pub const OWNER_NAME_VALUE: &str = ":on";
}

/// Provides a simple library for using DynamoDB's consistent read/write feature
/// to use it for managing distributed locks.
/**
* Provides a simple library for using DynamoDB's consistent read/write feature to use it for
* managing distributed locks.
*
* ```rust
* use dynamodb_lock::{DynamoDbLockClient, Region};
*
* let lock = DynamoDbLockClient::for_region(Region::UsEast2);
* ```
*/
pub struct DynamoDbLockClient {
client: DynamoDbClient,
opts: DynamoDbOptions,
Expand All @@ -317,6 +341,12 @@ impl std::fmt::Debug for DynamoDbLockClient {
}
}

impl Default for DynamoDbLockClient {
fn default() -> Self {
Self::for_region(Region::UsEast1)
}
}

#[async_trait::async_trait]
impl LockClient for DynamoDbLockClient {
async fn try_acquire_lock(&self, data: &str) -> Result<Option<LockItem>, DynamoError> {
Expand All @@ -337,8 +367,25 @@ impl LockClient for DynamoDbLockClient {
}

impl DynamoDbLockClient {
/// construct a new DynamoDbLockClient for the given region
pub fn for_region(region: Region) -> Self {
Self::new(DynamoDbClient::new(region), DynamoDbOptions::default())
}

/// Provide the given DynamoDbLockClient with a fully custom [rusoto_dynamodb::DynamoDbClient]
pub fn with_client(mut self, client: DynamoDbClient) -> Self {
self.client = client;
self
}

/// Add the given [DynamoDbOptions]
pub fn with_options(mut self, options: DynamoDbOptions) -> Self {
self.opts = options;
self
}

/// Creates new DynamoDB lock client
pub fn new(client: DynamoDbClient, opts: DynamoDbOptions) -> Self {
fn new(client: DynamoDbClient, opts: DynamoDbOptions) -> Self {
Self { client, opts }
}

Expand Down Expand Up @@ -693,6 +740,12 @@ impl<'a> AcquireLockState<'a> {
}
}

#[cfg(feature = "sts")]
fn get_web_identity_provider() -> Result<AutoRefreshingProvider<WebIdentityProvider>, DynamoError> {
let provider = WebIdentityProvider::from_k8s_env();
Ok(AutoRefreshingProvider::new(provider)?)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit f4e21a8

Please sign in to comment.