Skip to content

Commit 4e2ed06

Browse files
committed
feat(rust): use the any driver for sqlx to add support for postgres
1 parent a5848f5 commit 4e2ed06

File tree

103 files changed

+4455
-2898
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+4455
-2898
lines changed

.github/workflows/rust.yml

+239-190
Large diffs are not rendered by default.

Cargo.lock

+8-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

NOTICE.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,15 @@ This file contains attributions for any 3rd-party open source code used in this
192192
| equivalent | Apache-2.0, MIT | https://crates.io/crates/equivalent |
193193
| errno | MIT, Apache-2.0 | https://crates.io/crates/errno |
194194
| error-code | BSL-1.0 | https://crates.io/crates/error-code |
195+
| etcetera | MIT, Apache-2.0 | https://crates.io/crates/etcetera |
195196
| event-listener | Apache-2.0, MIT | https://crates.io/crates/event-listener |
196197
| event-listener-strategy | Apache-2.0, MIT | https://crates.io/crates/event-listener-strategy |
197198
| fastrand | Apache-2.0, MIT | https://crates.io/crates/fastrand |
198199
| fd-lock | MIT, Apache-2.0 | https://crates.io/crates/fd-lock |
199200
| fdeflate | MIT, Apache-2.0 | https://crates.io/crates/fdeflate |
200201
| ff | MIT, Apache-2.0 | https://crates.io/crates/ff |
201202
| fiat-crypto | MIT, Apache-2.0, BSD-1-Clause | https://crates.io/crates/fiat-crypto |
203+
| finl_unicode | MIT, Apache-2.0 | https://crates.io/crates/finl_unicode |
202204
| flate2 | MIT, Apache-2.0 | https://crates.io/crates/flate2 |
203205
| flexi_logger | MIT, Apache-2.0 | https://crates.io/crates/flexi_logger |
204206
| flume | Apache-2.0, MIT | https://crates.io/crates/flume |
@@ -487,11 +489,12 @@ This file contains attributions for any 3rd-party open source code used in this
487489
| spin | MIT | https://crates.io/crates/spin |
488490
| spki | Apache-2.0, MIT | https://crates.io/crates/spki |
489491
| sqlformat | MIT, Apache-2.0 | https://crates.io/crates/sqlformat |
490-
| sqlx | MIT, Apache-2.0 | https://crates.io/crates/sqlx |
491-
| sqlx-core | MIT, Apache-2.0 | https://crates.io/crates/sqlx-core |
492-
| sqlx-macros | MIT, Apache-2.0 | https://crates.io/crates/sqlx-macros |
493-
| sqlx-macros-core | MIT, Apache-2.0 | https://crates.io/crates/sqlx-macros-core |
494-
| sqlx-sqlite | MIT, Apache-2.0 | https://crates.io/crates/sqlx-sqlite |
492+
| sqlx | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
493+
| sqlx-core | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
494+
| sqlx-macros | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
495+
| sqlx-macros-core | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
496+
| sqlx-postgres | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
497+
| sqlx-sqlite | MIT, Apache-2.0 | https://github.com/etorreborre/sqlx?rev=5fec648d2de0cbeed738dcf1c6f5bc9194fc439b |
495498
| stable_deref_trait | MIT, Apache-2.0 | https://crates.io/crates/stable_deref_trait |
496499
| static_assertions | MIT, Apache-2.0 | https://crates.io/crates/static_assertions |
497500
| stm32-device-signature | MIT, Apache-2.0 | https://crates.io/crates/stm32-device-signature |
@@ -500,6 +503,7 @@ This file contains attributions for any 3rd-party open source code used in this
500503
| stm32h7 | MIT, Apache-2.0 | https://crates.io/crates/stm32h7 |
501504
| stm32h7xx-hal | 0BSD | https://crates.io/crates/stm32h7xx-hal |
502505
| str-buf | BSL-1.0 | https://crates.io/crates/str-buf |
506+
| stringprep | MIT, Apache-2.0 | https://crates.io/crates/stringprep |
503507
| strip-ansi-escapes | Apache-2.0, MIT | https://crates.io/crates/strip-ansi-escapes |
504508
| strsim | MIT | https://crates.io/crates/strsim |
505509
| strum | MIT | https://crates.io/crates/strum |
@@ -586,6 +590,7 @@ This file contains attributions for any 3rd-party open source code used in this
586590
| waker-fn | Apache-2.0, MIT | https://crates.io/crates/waker-fn |
587591
| walkdir | Unlicense, MIT | https://crates.io/crates/walkdir |
588592
| want | MIT | https://crates.io/crates/want |
593+
| wasite | Apache-2.0, BSL-1.0, MIT | https://crates.io/crates/wasite |
589594
| wasm-bindgen | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen |
590595
| wasm-bindgen-backend | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen-backend |
591596
| wasm-bindgen-futures | MIT, Apache-2.0 | https://crates.io/crates/wasm-bindgen-futures |
@@ -604,6 +609,7 @@ This file contains attributions for any 3rd-party open source code used in this
604609
| web-time | MIT, Apache-2.0 | https://crates.io/crates/web-time |
605610
| weezl | MIT, Apache-2.0 | https://crates.io/crates/weezl |
606611
| which | MIT | https://crates.io/crates/which |
612+
| whoami | Apache-2.0, BSL-1.0, MIT | https://crates.io/crates/whoami |
607613
| winapi | MIT, Apache-2.0 | https://crates.io/crates/winapi |
608614
| winapi-i686-pc-windows-gnu | MIT, Apache-2.0 | https://crates.io/crates/winapi-i686-pc-windows-gnu |
609615
| winapi-util | Unlicense, MIT | https://crates.io/crates/winapi-util |

implementations/rust/Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ nextest:
4848
nextest_%:
4949
cargo --locked nextest --config-file $(ROOT_DIR)/tools/nextest/.config/nextest.toml run -E 'package($*)' --no-fail-fast
5050
cargo --locked test --doc
51+
test_postgres:
52+
export OCKAM_POSTGRES_HOST=localhost
53+
export OCKAM_POSTGRES_PORT=5433
54+
export OCKAM_POSTGRES_DATABASE_NAME=test
55+
export OCKAM_POSTGRES_USER=postgres
56+
export OCKAM_POSTGRES_PASSWORD=password
57+
cargo --locked nextest --config-file $(ROOT_DIR)/tools/nextest/.config/nextest.toml run -E 'test(sql) or test(cli_state)' --no-fail-fast --test-threads 1
5158

5259
lint: lint_cargo_fmt_check lint_cargo_deny lint_cargo_clippy
5360
lint_cargo_fmt_check:

implementations/rust/ockam/ockam_abac/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ ockam_executor = { version = "0.80.0", path = "../ockam_executor", default-featu
5050
regex = { version = "1.10.5", default-features = false, optional = true }
5151
rustyline = { version = "14.0.0", optional = true }
5252
rustyline-derive = { version = "0.10.0", optional = true }
53-
sqlx = { version = "0.7.4", optional = true }
53+
sqlx = { git = "https://github.com/etorreborre/sqlx", rev = "5fec648d2de0cbeed738dcf1c6f5bc9194fc439b", optional = true }
5454
str-buf = "3.0.3"
5555
tokio = { version = "1.38", default-features = false, optional = true, features = ["sync", "time", "rt", "rt-multi-thread", "macros"] }
5656
tracing = { version = "0.1", default-features = false, features = ["attributes"] }

implementations/rust/ockam/ockam_abac/src/policy/storage/resource_policy_repository_sql.rs

+22-34
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use tracing::debug;
55
use ockam_core::async_trait;
66
use ockam_core::compat::vec::Vec;
77
use ockam_core::Result;
8-
use ockam_node::database::{FromSqlxError, SqlxDatabase, SqlxType, ToSqlxType, ToVoid};
8+
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToVoid};
99

1010
use crate::{Action, Expr, ResourceName, ResourcePoliciesRepository, ResourcePolicy};
1111

@@ -43,13 +43,15 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
4343
expression: &Expr,
4444
) -> Result<()> {
4545
let query = query(
46-
r#"INSERT OR REPLACE INTO resource_policy
47-
VALUES (?, ?, ?, ?)"#,
46+
r#"INSERT INTO resource_policy (resource_name, action, expression, node_name)
47+
VALUES ($1, $2, $3, $4)
48+
ON CONFLICT (resource_name, action, node_name)
49+
DO UPDATE SET expression = $3"#,
4850
)
49-
.bind(resource_name.to_sql())
50-
.bind(action.to_sql())
51-
.bind(expression.to_string().to_sql())
52-
.bind(self.node_name.to_sql());
51+
.bind(resource_name)
52+
.bind(action)
53+
.bind(expression)
54+
.bind(&self.node_name);
5355
query.execute(&*self.database.pool).await.void()
5456
}
5557

@@ -61,11 +63,11 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
6163
let query = query_as(
6264
r#"SELECT resource_name, action, expression
6365
FROM resource_policy
64-
WHERE node_name=$1 and resource_name=$2 and action=$3"#,
66+
WHERE node_name = $1 and resource_name = $2 and action = $3"#,
6567
)
66-
.bind(self.node_name.to_sql())
67-
.bind(resource_name.to_sql())
68-
.bind(action.to_sql());
68+
.bind(&self.node_name)
69+
.bind(resource_name)
70+
.bind(action);
6971
let row: Option<PolicyRow> = query
7072
.fetch_optional(&*self.database.pool)
7173
.await
@@ -77,9 +79,9 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
7779
let query = query_as(
7880
r#"SELECT resource_name, action, expression
7981
FROM resource_policy
80-
WHERE node_name=$1"#,
82+
WHERE node_name = $1"#,
8183
)
82-
.bind(self.node_name.to_sql());
84+
.bind(&self.node_name);
8385
let row: Vec<PolicyRow> = query.fetch_all(&*self.database.pool).await.into_core()?;
8486
row.into_iter()
8587
.map(|r| r.try_into())
@@ -93,10 +95,10 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
9395
let query = query_as(
9496
r#"SELECT resource_name, action, expression
9597
FROM resource_policy
96-
WHERE node_name=$1 and resource_name=$2"#,
98+
WHERE node_name = $1 and resource_name = $2"#,
9799
)
98-
.bind(self.node_name.to_sql())
99-
.bind(resource_name.to_sql());
100+
.bind(&self.node_name)
101+
.bind(resource_name);
100102
let row: Vec<PolicyRow> = query.fetch_all(&*self.database.pool).await.into_core()?;
101103
row.into_iter()
102104
.map(|r| r.try_into())
@@ -106,29 +108,15 @@ impl ResourcePoliciesRepository for ResourcePolicySqlxDatabase {
106108
async fn delete_policy(&self, resource_name: &ResourceName, action: &Action) -> Result<()> {
107109
let query = query(
108110
r#"DELETE FROM resource_policy
109-
WHERE node_name=? and resource_name=? and action=?"#,
111+
WHERE node_name = $1 and resource_name = $2 and action = $3"#,
110112
)
111-
.bind(self.node_name.to_sql())
112-
.bind(resource_name.to_sql())
113-
.bind(action.to_sql());
113+
.bind(&self.node_name)
114+
.bind(resource_name)
115+
.bind(action);
114116
query.execute(&*self.database.pool).await.void()
115117
}
116118
}
117119

118-
// Database serialization / deserialization
119-
120-
impl ToSqlxType for ResourceName {
121-
fn to_sql(&self) -> SqlxType {
122-
SqlxType::Text(self.as_str().to_string())
123-
}
124-
}
125-
126-
impl ToSqlxType for Action {
127-
fn to_sql(&self) -> SqlxType {
128-
SqlxType::Text(self.to_string())
129-
}
130-
}
131-
132120
/// Low-level representation of a row in the resource_policy table
133121
#[derive(FromRow)]
134122
struct PolicyRow {

implementations/rust/ockam/ockam_abac/src/policy/storage/resource_repository_sql.rs

+33-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use core::str::FromStr;
2+
use sqlx::database::HasArguments;
3+
use sqlx::encode::IsNull;
24
use sqlx::*;
35
use tracing::debug;
46

57
use ockam_core::async_trait;
68
use ockam_core::Result;
7-
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToSqlxType, ToVoid};
9+
use ockam_node::database::{FromSqlxError, SqlxDatabase, ToVoid};
810

911
use crate::{Resource, ResourceName, ResourceType, ResourcesRepository};
1012

@@ -37,23 +39,25 @@ impl ResourcesSqlxDatabase {
3739
impl ResourcesRepository for ResourcesSqlxDatabase {
3840
async fn store_resource(&self, resource: &Resource) -> Result<()> {
3941
let query = query(
40-
r#"INSERT OR REPLACE INTO resource
41-
VALUES (?, ?, ?)"#,
42+
r#"
43+
INSERT INTO resource (resource_name, resource_type, node_name)
44+
VALUES ($1, $2, $3)
45+
ON CONFLICT DO NOTHING"#,
4246
)
43-
.bind(resource.resource_name.to_sql())
44-
.bind(resource.resource_type.to_sql())
45-
.bind(self.node_name.to_sql());
47+
.bind(&resource.resource_name)
48+
.bind(&resource.resource_type)
49+
.bind(&self.node_name);
4650
query.execute(&*self.database.pool).await.void()
4751
}
4852

4953
async fn get_resource(&self, resource_name: &ResourceName) -> Result<Option<Resource>> {
5054
let query = query_as(
5155
r#"SELECT resource_name, resource_type
5256
FROM resource
53-
WHERE node_name=$1 and resource_name=$2"#,
57+
WHERE node_name = $1 and resource_name = $2"#,
5458
)
55-
.bind(self.node_name.to_sql())
56-
.bind(resource_name.to_sql());
59+
.bind(&self.node_name)
60+
.bind(resource_name);
5761
let row: Option<ResourceRow> = query
5862
.fetch_optional(&*self.database.pool)
5963
.await
@@ -66,24 +70,38 @@ impl ResourcesRepository for ResourcesSqlxDatabase {
6670

6771
let query = query(
6872
r#"DELETE FROM resource
69-
WHERE node_name=? and resource_name=?"#,
73+
WHERE node_name = $1 and resource_name = $2"#,
7074
)
71-
.bind(self.node_name.to_sql())
72-
.bind(resource_name.to_sql());
75+
.bind(&self.node_name)
76+
.bind(resource_name);
7377
query.execute(&mut *transaction).await.void()?;
7478

7579
let query = sqlx::query(
7680
r#"DELETE FROM resource_policy
77-
WHERE node_name=? and resource_name=?"#,
81+
WHERE node_name = $1 and resource_name = $2"#,
7882
)
79-
.bind(self.node_name.to_sql())
80-
.bind(resource_name.to_sql());
83+
.bind(&self.node_name)
84+
.bind(resource_name);
8185
query.execute(&mut *transaction).await.void()?;
8286

8387
transaction.commit().await.void()
8488
}
8589
}
8690

91+
// Database serialization / deserialization
92+
93+
impl Type<Any> for ResourceName {
94+
fn type_info() -> <Any as Database>::TypeInfo {
95+
<String as Type<Any>>::type_info()
96+
}
97+
}
98+
99+
impl sqlx::Encode<'_, Any> for ResourceName {
100+
fn encode_by_ref(&self, buf: &mut <Any as HasArguments>::ArgumentBuffer) -> IsNull {
101+
<String as sqlx::Encode<'_, Any>>::encode_by_ref(&self.to_string(), buf)
102+
}
103+
}
104+
87105
/// Low-level representation of a row in the resource_type_policy table
88106
#[derive(FromRow)]
89107
#[allow(dead_code)]

0 commit comments

Comments
 (0)