From: Jeff Davis Date: Tue, 30 Jun 2020 22:20:00 +0000 (-0700) Subject: LP#1843818: remote authentication fixes X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=355f8367e530db5ad3cc2b463c21d555156b9d3f;p=working%2FEvergreen.git LP#1843818: remote authentication fixes - Remove the "allow_inactive" option. It didn't work, supporting it would require a lot of extra code, and we don't allow inactive users to authenticate in other contexts. - Use a SERIAL primary key on config.remoteauth_profile so that profile names can be changed in the client. - Simplify the reporter label to "Remote Authentication Profile" while we're at it. Signed-off-by: Jeff Davis --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 560d372eab..f2b30b9a40 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -13111,15 +13111,15 @@ SELECT usr, - - + + + - diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm index 82163160f1..33352cebad 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/RemoteAuth.pm @@ -93,7 +93,7 @@ sub load_config { return undef unless $name; # load config - my $config = $e->retrieve_config_remoteauth_profile($name); + my $config = $e->search_config_remoteauth_profile({name => $name})->[0]; if ($config and $U->is_true($config->enabled)) { return $config; } diff --git a/Open-ILS/src/sql/Pg/150.remoteauth.sql b/Open-ILS/src/sql/Pg/150.remoteauth.sql index 0b36c4991c..4f08f36f5d 100644 --- a/Open-ILS/src/sql/Pg/150.remoteauth.sql +++ b/Open-ILS/src/sql/Pg/150.remoteauth.sql @@ -1,13 +1,13 @@ BEGIN; CREATE TABLE config.remoteauth_profile ( - name TEXT PRIMARY KEY, + id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL, description TEXT, context_org INT NOT NULL REFERENCES actor.org_unit(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, enabled BOOLEAN NOT NULL DEFAULT FALSE, perm INT NOT NULL REFERENCES permission.perm_list(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED, restrict_to_org BOOLEAN NOT NULL DEFAULT TRUE, - allow_inactive BOOL NOT NULL DEFAULT FALSE, allow_expired BOOL NOT NULL DEFAULT FALSE, block_list TEXT, usr_activity_type INT REFERENCES config.usr_activity_type(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED @@ -50,10 +50,6 @@ BEGIN RETURN 'expired'; END IF; - IF usr.active IS FALSE AND profile.allow_inactive IS FALSE THEN - RETURN 'blocked'; - END IF; - -- Proximity of user's home_ou to context_org to see if penalties should be ignored. SELECT INTO home_prox prox FROM actor.org_unit_proximity WHERE from_org = usr.home_ou AND to_org = profile.context_org; diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.remoteauth_pkey.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.remoteauth_pkey.sql new file mode 100644 index 0000000000..5340edd738 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.remoteauth_pkey.sql @@ -0,0 +1,114 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +-- The allow_inactive rule is deprecated, warn if any profile is using it. +DO $SQL$ +BEGIN + PERFORM * FROM config.remoteauth_profile WHERE allow_inactive IS TRUE; + IF FOUND THEN + RAISE NOTICE 'Remote authentication is no longer supported for inactive users.'; + END IF; +END; +$SQL$; + + +DROP FUNCTION IF EXISTS actor.permit_remoteauth(TEXT, BIGINT); + + +-- Add a new SERIAL primary key (the "id" column) to config.remoteauth_profile. +-- The primary key is generally the first column, so we drop and recreate the +-- config.remoteauth_profile table (preserving any existing data, of course) in +-- order to get our desired column order. +CREATE TABLE config.remoteauth_profile_temp ( + id SERIAL PRIMARY KEY, + name TEXT UNIQUE NOT NULL, + description TEXT, + context_org INT NOT NULL REFERENCES actor.org_unit(id) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + enabled BOOLEAN NOT NULL DEFAULT FALSE, + perm INT NOT NULL REFERENCES permission.perm_list(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED, + restrict_to_org BOOLEAN NOT NULL DEFAULT TRUE, + allow_expired BOOL NOT NULL DEFAULT FALSE, + block_list TEXT, + usr_activity_type INT REFERENCES config.usr_activity_type(id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED +); + +INSERT INTO config.remoteauth_profile_temp ( + name, description, context_org, enabled, perm, restrict_to_org, + allow_expired, block_list, usr_activity_type +) SELECT + name, description, context_org, enabled, perm, restrict_to_org, + allow_expired, block_list, usr_activity_type +FROM config.remoteauth_profile; + +DROP TABLE config.remoteauth_profile; +ALTER TABLE config.remoteauth_profile_temp RENAME TO remoteauth_profile; + + +CREATE OR REPLACE FUNCTION actor.permit_remoteauth (profile_name TEXT, userid BIGINT) RETURNS TEXT AS $func$ +DECLARE + usr actor.usr%ROWTYPE; + profile config.remoteauth_profile%ROWTYPE; + perm TEXT; + context_org_list INT[]; + home_prox INT; + block TEXT; + penalty_count INT; +BEGIN + + SELECT INTO usr * FROM actor.usr WHERE id = userid AND NOT deleted; + IF usr IS NULL THEN + RETURN 'not_found'; + END IF; + + IF usr.barred IS TRUE THEN + RETURN 'blocked'; + END IF; + + SELECT INTO profile * FROM config.remoteauth_profile WHERE name = profile_name; + SELECT INTO context_org_list ARRAY_AGG(id) FROM actor.org_unit_full_path( profile.context_org ); + + -- user's home library must be within the context org + IF profile.restrict_to_org IS TRUE AND usr.home_ou NOT IN (SELECT * FROM UNNEST(context_org_list)) THEN + RETURN 'not_found'; + END IF; + + SELECT INTO perm code FROM permission.perm_list WHERE id = profile.perm; + IF permission.usr_has_perm(usr.id, perm, profile.context_org) IS FALSE THEN + RETURN 'not_found'; + END IF; + + IF usr.expire_date < NOW() AND profile.allow_expired IS FALSE THEN + RETURN 'expired'; + END IF; + + -- Proximity of user's home_ou to context_org to see if penalties should be ignored. + SELECT INTO home_prox prox FROM actor.org_unit_proximity WHERE from_org = usr.home_ou AND to_org = profile.context_org; + + -- Loop through the block list to see if the user has any matching penalties. + IF profile.block_list IS NOT NULL THEN + FOR block IN SELECT UNNEST(STRING_TO_ARRAY(profile.block_list, '|')) LOOP + SELECT INTO penalty_count COUNT(DISTINCT csp.*) + FROM actor.usr_standing_penalty usp + JOIN config.standing_penalty csp ON (csp.id = usp.standing_penalty) + WHERE usp.usr = usr.id + AND usp.org_unit IN ( SELECT * FROM UNNEST(context_org_list) ) + AND ( usp.stop_date IS NULL or usp.stop_date > NOW() ) + AND ( csp.ignore_proximity IS NULL OR csp.ignore_proximity < home_prox ) + AND csp.block_list ~ block; + IF penalty_count > 0 THEN + -- User has penalties that match this block, so auth is not permitted. + -- Don't bother testing the rest of the block list. + RETURN 'blocked'; + END IF; + END LOOP; + END IF; + + -- User has passed all tests. + RETURN 'success'; + +END; +$func$ LANGUAGE plpgsql; + +COMMIT; + diff --git a/Open-ILS/tests/datasets/sql/remoteauth.sql b/Open-ILS/tests/datasets/sql/remoteauth.sql index f967efb090..d588a3f73e 100644 --- a/Open-ILS/tests/datasets/sql/remoteauth.sql +++ b/Open-ILS/tests/datasets/sql/remoteauth.sql @@ -5,7 +5,7 @@ INSERT INTO config.usr_activity_type (id, ewho, ewhat, ehow, egroup, label) VALU -- config for Basic HTTP Authentication (SYS1) INSERT INTO config.remoteauth_profile (name, description, context_org, enabled, perm, - restrict_to_org, allow_inactive, allow_expired, block_list, usr_activity_type) + restrict_to_org, allow_expired, block_list, usr_activity_type) VALUES ('Basic', 'Basic HTTP Authentication for SYS1', 2, TRUE, 1, - TRUE, FALSE, FALSE, NULL, 1001); + TRUE, FALSE, NULL, 1001); diff --git a/docs/TechRef/remoteauth.adoc b/docs/TechRef/remoteauth.adoc index ceb61d6b69..4b0989de63 100644 --- a/docs/TechRef/remoteauth.adoc +++ b/docs/TechRef/remoteauth.adoc @@ -66,7 +66,6 @@ In each endpoint's Apache configuration, the OILSRemoteAuthProfile variable spec * *perm:* a permission which the user must have in order to be authenticated via RemoteAuth * *restrict_to_org:* only allow users belonging to this location to be authenticated, even if the client can retrieve users at other locations -* *allow_inactive:* allow authentication for inactive users * *allow_expired:* allow authentication for expired users * *block_list:* authentication is not permitted if the user has a standing penalty at this location with one of these blocks