Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/core-protocol.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,16 @@ jobs:
LMM_MODEL_PROCESS_CORE_SHA256="$(sha256sum "$LMM_MODEL_PROCESS_CORE_BIN" | cut -d ' ' -f1)"
LMM_MODEL_PROCESS_ROOT="$(mktemp -d /tmp/lmm-model-XXXXXXXX)"
export LMM_MODEL_PROCESS_CORE_BIN LMM_MODEL_PROCESS_CORE_SHA256 LMM_MODEL_PROCESS_ROOT
# The non-ignored payment recovery case requires sealed Core, Go host
# and bootstrap binaries. The 302-second case stays ignored.
CGO_ENABLED=0 go test -C ../extensions -mod=readonly -c -o "$RUNNER_TEMP/lmm-payment-bootstrap" ./internal/modules/payments
LMM_PAYMENT_CORE_BIN="$LMM_MODEL_PROCESS_CORE_BIN"
LMM_PAYMENT_CORE_SHA256="$LMM_MODEL_PROCESS_CORE_SHA256"
LMM_PAYMENT_GO_BIN="$(realpath "$LMM_RELAY_EXTENSION_BIN")"
LMM_PAYMENT_GO_SHA256="$(sha256sum "$LMM_PAYMENT_GO_BIN" | cut -d ' ' -f1)"
LMM_PAYMENT_BOOTSTRAP_BIN="$(realpath "$RUNNER_TEMP/lmm-payment-bootstrap")"
LMM_PAYMENT_BOOTSTRAP_SHA256="$(sha256sum "$LMM_PAYMENT_BOOTSTRAP_BIN" | cut -d ' ' -f1)"
export LMM_PAYMENT_CORE_BIN LMM_PAYMENT_CORE_SHA256 LMM_PAYMENT_GO_BIN LMM_PAYMENT_GO_SHA256 LMM_PAYMENT_BOOTSTRAP_BIN LMM_PAYMENT_BOOTSTRAP_SHA256
cargo test --locked --all-targets --no-fail-fast 2>&1 | tee "$RUNNER_TEMP/core-tests.log"
- name: Go contract and race tests
if: ${{ !cancelled() }}
Expand Down
6 changes: 5 additions & 1 deletion deployment/postgres/grant-core-runtime.sql
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ SELECT EXISTS (
\else
\echo 'Refusing unsafe runtime role or login-enabled installation owner.'
ROLLBACK;
\quit 1
-- psql \quit ignores an exit status, so a refused script would otherwise
-- leave the process successful after this rollback. ON_ERROR_STOP is set above.
DO $$ BEGIN
RAISE EXCEPTION 'Refusing unsafe runtime role or login-enabled installation owner.';
END $$;
\endif

REVOKE CREATE, TEMPORARY ON DATABASE :"core_database" FROM PUBLIC;
Expand Down
18 changes: 17 additions & 1 deletion services/core/tests/browser_sessions_independent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ impl RuntimeRole {
let database = owner.connect_options().get_database().unwrap().to_owned();
let mut admin = reqwest::Url::parse(&std::env::var("DATABASE_URL").unwrap()).unwrap();
assert_eq!(admin.host_str(), Some("127.0.0.1"));
// The official grant script refuses, and rolls back, unless the NOLOGIN
// installation owner already exists. That role is cluster-wide.
sqlx::raw_sql(
"DO $$ BEGIN \
CREATE ROLE lmm_core_owner NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS; \
EXCEPTION WHEN duplicate_object THEN \
IF EXISTS (SELECT FROM pg_roles r WHERE r.rolname='lmm_core_owner' AND r.rolcanlogin) THEN \
RAISE EXCEPTION 'installation owner must not log in'; \
END IF; \
END $$;",
)
.execute(owner)
.await
.unwrap();
let grants = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../deployment/postgres/grant-core-runtime.sql");
let output = std::process::Command::new("/usr/bin/psql")
Expand Down Expand Up @@ -55,7 +69,9 @@ impl RuntimeRole {
.unwrap();
assert!(
output.status.success(),
"official runtime grants failed before session behavior"
"official runtime grants failed before session behavior\nstdout: {}\nstderr: {}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
admin.set_path(&database);
admin.set_username(&name).unwrap();
Expand Down
12 changes: 10 additions & 2 deletions services/core/tests/oauth2_pi_independent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,20 @@ async fn revoked_expired_stream_retains_original_hold_until_authoritative_reconc
pool: PgPool,
) {
with_fixture(pool,true,|f|async move {
let token=f.token(100).await;let mut spec=f.spec("independent-crash",60);spec.lease_seconds=1;spec.maximum_seconds=1;
let token=f.token(100).await;
// A one-second lease is already stale before start once reserve and the
// following serializable transaction cross a clock second. Dispatch must
// succeed first; expiry is then the same explicit lease move used by the
// charging recovery tests.
let spec=f.spec("independent-crash",60);
let held=f.reserve(&token.access_token,&spec,&[1;32]).await.unwrap();
assert!(f.charging.start_oauth(&f.issuer,&held.id,&[1;32]).await.unwrap());
f.issuer.revoke_for_client("lmm-pi",&token.access_token).await.unwrap();
sqlx::query("UPDATE core_identity.users SET active=false WHERE id=$1").bind(f.user).execute(&f.owner).await.unwrap();
tokio::time::sleep(Duration::from_secs(2)).await;
let mut expiry=f.owner.begin().await.unwrap();
sqlx::query("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE").execute(&mut *expiry).await.unwrap();
sqlx::query("UPDATE core_charging.requests SET lease_until=floor(extract(epoch FROM clock_timestamp()))::bigint-1,revision=revision+1 WHERE id=$1").bind(&held.id).execute(&mut *expiry).await.unwrap();
expiry.commit().await.unwrap();
let recovered=f.charging.recover_expired(10).await.unwrap();assert_eq!(recovered.len(),1);let recovered=&recovered[0];assert_eq!(recovered.state,"reconcile");assert_eq!(recovered.oauth_source,held.oauth_source);
assert_eq!(f.ledger.balance(f.account).await.unwrap().reserved_units,60);
let usage=Usage{input:25,..Default::default()};
Expand Down
Loading