Skip to content

Commit 765eec1

Browse files
committed
readyset: Verify upstream permissions at startup
Check the replication-related permissions on MySQL. If --disable-setup-ddl-replication or --disable-create-publication are not passed, also check for superuser permissions on PostgreSQL, optionally looking for the special RDS way of defining a superuser. Address: REA-5937 Change-Id: Id5519e4688e8f8a49e2173d1f0a72db759e9434d Reviewed-on: https://gerrit.readyset.name/c/readyset/+/10600 Tested-by: Buildkite CI Reviewed-by: Michael Zink <michael.z@readyset.io>
1 parent 94bd386 commit 765eec1

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

readyset/src/verify.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,49 @@ async fn verify_replication(conn: &mut DatabaseConnection) -> Result<()> {
196196
Ok(())
197197
}
198198

199+
async fn verify_permissions(conn: &mut DatabaseConnection, options: &Options) -> Result<()> {
200+
match conn.dialect() {
201+
Dialect::MySQL => {
202+
let grants: Vec<Vec<String>> = conn.query("SHOW GRANTS").await?.try_into()?;
203+
let grants: Vec<String> = grants.into_iter().flatten().collect();
204+
macro_rules! ensure_permission {
205+
($permission:literal) => {
206+
ensure!(
207+
grants.iter().any(|grant| grant.contains($permission)),
208+
concat!("Readyset user missing ", $permission, " permissions")
209+
);
210+
};
211+
}
212+
ensure_permission!("REPLICATION CLIENT");
213+
ensure_permission!("REPLICATION SLAVE");
214+
}
215+
Dialect::PostgreSQL => {
216+
let config = &options.server_worker_options.replicator_config;
217+
if !config.disable_setup_ddl_replication && !config.disable_create_publication {
218+
let has_super: bool = query_one_value(
219+
conn,
220+
"SELECT usesuper FROM pg_user where usename = CURRENT_USER",
221+
)
222+
.await?;
223+
let has_super = has_super || {
224+
// RDS has its own representation of super.
225+
let has_super: Result<String> = query_one_value(
226+
conn,
227+
"SELECT rolname FROM pg_roles WHERE \
228+
pg_has_role(CURRENT_USER, rolname, 'member') AND \
229+
rolname = 'rds_superuser'",
230+
)
231+
.await;
232+
has_super.is_ok()
233+
};
234+
ensure!(has_super, "Readyset user missing SUPERUSER permissions");
235+
}
236+
}
237+
}
238+
info!("Verified upstream permissions");
239+
Ok(())
240+
}
241+
199242
/// Run through a list of checks to make sure we're good to go before attempting to snapshot.
200243
pub async fn verify(options: &Options) -> Result<()> {
201244
let mut errors = Vec::new();
@@ -234,6 +277,7 @@ pub async fn verify(options: &Options) -> Result<()> {
234277
if let Some(conn) = &mut conn {
235278
add_err!(verify_version(conn).await);
236279
add_err!(verify_replication(conn).await);
280+
add_err!(verify_permissions(conn, options).await);
237281
}
238282

239283
if errors.is_empty() {

0 commit comments

Comments
 (0)