Thread: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

[HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Joel Jacobson
Date:
Hi Hackers,

Currently, it's only possible to grant/revoke execute on functions to roles.

I think it would be useful in many situations, both for documentation purposes,
but also for increased security, to in a precise way control what
other function(s)
are allowed to execute a specific function.

This would be useful for functions that are not supposed to be used
manually by any human or any other function(s) than the few places
where the function makes sense to use.

Thoughts?

/Joel



Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Pavel Stehule
Date:


2017-02-22 8:06 GMT+01:00 Joel Jacobson <joel@trustly.com>:
Hi Hackers,

Currently, it's only possible to grant/revoke execute on functions to roles.

I think it would be useful in many situations, both for documentation purposes,
but also for increased security, to in a precise way control what
other function(s)
are allowed to execute a specific function. 

This would be useful for functions that are not supposed to be used
manually by any human or any other function(s) than the few places
where the function makes sense to use.

Thoughts?

I had similar idea. The possibility to specify a list of functions can have a performance impact when ACL can be too long.

Just idea - what is based on idea "using schema like package". We can introduce new kind of functions X, that cannot be executed on toplevel - and can be executed only from standard functions defined in same schema.

Usage of X functions can be locked in schema.

It allow similar functionality to your proposal, but the check can be faster - and you don't need to maintain list of enabled caller functions.

Regards

Pavel


/Joel


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Joel Jacobson
Date:
On Wed, Feb 22, 2017 at 9:07 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
> Usage of X functions can be locked in schema.

I think that's also a good idea. Both are useful I think. They solve
two different use-cases.

If there are multiple callers of a private function within a schema,
it would be useful if you could just declare it PRIVATE,
to prevent any top-level usage of the function,
and to prevent any other function than functions in the same schema
from calling it.

This would be similar to how e.g. a private method in a Java class can
be called by any other method in the same class.
I think that's also a useful idea, but a different use-case.

This would be useful if you have lots of callers of a function,
and it would of course be tedious if you had to explicitly GRANT EXECUTE
for each function that you want should be allowed to call the function.
In that case, a PRIVATE declaration of the function would be better.

But if it is important a function is absolutely not called by any
other function than a a single very specific function,
then it would be better with a specific GRANT EXECUTE ON FUNCTION
foo() to bar() in the function definition file for bar(),
which would make it clear to a developer looking at the bar() source
code that the function is only supposed to be called by foo().

But like I said, I also like your PRIVATE idea. I think most functions
in my schemas would actually be PRIVATE, and only a few would be
PUBLIC, since you usually have more internal functions in a schema,
that are not supposed to be called outside of the schema and doesn't
even make sense outside of the schema.



Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Pavel Stehule
Date:


2017-02-22 9:20 GMT+01:00 Joel Jacobson <joel@trustly.com>:
On Wed, Feb 22, 2017 at 9:07 AM, Pavel Stehule <pavel.stehule@gmail.com> wrote:
> Usage of X functions can be locked in schema.

I think that's also a good idea. Both are useful I think. They solve
two different use-cases.

If there are multiple callers of a private function within a schema,
it would be useful if you could just declare it PRIVATE,
to prevent any top-level usage of the function,
and to prevent any other function than functions in the same schema
from calling it.

This would be similar to how e.g. a private method in a Java class can
be called by any other method in the same class.
I think that's also a useful idea, but a different use-case.

This would be useful if you have lots of callers of a function,
and it would of course be tedious if you had to explicitly GRANT EXECUTE
for each function that you want should be allowed to call the function.
In that case, a PRIVATE declaration of the function would be better.

But if it is important a function is absolutely not called by any
other function than a a single very specific function,
then it would be better with a specific GRANT EXECUTE ON FUNCTION
foo() to bar() in the function definition file for bar(),
which would make it clear to a developer looking at the bar() source
code that the function is only supposed to be called by foo().


can be solution to check a call stack and if it is not expected, than RAISE some exception? I hope, so I understand to use case.

CREATE OR REPLACE FUNCTION outer_func() RETURNS integer AS $$
BEGIN RETURN inner_func();
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION inner_func() RETURNS integer AS $$
DECLARE stack text;
BEGIN GET DIAGNOSTICS stack = PG_CONTEXT; RAISE NOTICE E'--- Call Stack ---\n%', stack; RETURN 1;
END;
$$ LANGUAGE plpgsql;

SELECT outer_func();

The solution based on rights is elegant, but in this moment I cannot to see all possible impacts on performance - because it means new check for any call of any function. Maybe checking call stack can be good enough - I have not idea how often use case it it. 

Regards

Pavel
 
But like I said, I also like your PRIVATE idea. I think most functions
in my schemas would actually be PRIVATE, and only a few would be
PUBLIC, since you usually have more internal functions in a schema,
that are not supposed to be called outside of the schema and doesn't
even make sense outside of the schema.

Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Tom Lane
Date:
Joel Jacobson <joel@trustly.com> writes:
> Currently, it's only possible to grant/revoke execute on functions to roles.

> I think it would be useful in many situations, both for documentation purposes,
> but also for increased security, to in a precise way control what
> other function(s) are allowed to execute a specific function.

I think this is really *not* a good idea.  The entire permissions model
is built around granting permissions to roles, by other roles.  Allowing
non-role objects to hold permissions would be a complicated mess and
probably create security bugs.  Confusing function OIDs with role OIDs
is a likely example.  Another problem is that roles are installation-wide
while functions are not, and all the ACL catalog infrastructure is
designed for the permissions-holding entities to be installation-wide.
No doubt that could be dealt with, but it would be more complexity and
another fertile source of bugs.  Complexity in security-related concepts
is not a good thing.

It's not that hard, if you have needs like this, to make an owning role
for each such function.  You might end up with a lot of single-purpose
roles, but they could be grouped under one or a few group roles for most
purposes beyond the individual tailored grants.
        regards, tom lane



Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Joel Jacobson
Date:
On Wed, Feb 22, 2017 at 2:18 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> I think this is really *not* a good idea.  The entire permissions model
> is built around granting permissions to roles, by other roles.

My bad. I shouldn't have proposed the idea on how to achieve/implement the idea.

I should instead just have presented the idea without suggesting to
use the permissions model.

Do you think it's a bad idea in general? Or is it just the idea of
using the permissions model for the purpose that is a bad idea?

If it's a good idea apart from that, then maybe we can figure out some other
more feasible way to control what functions can call what other functions?

> It's not that hard, if you have needs like this, to make an owning role
> for each such function.  You might end up with a lot of single-purpose
> roles, but they could be grouped under one or a few group roles for most
> purposes beyond the individual tailored grants.

I think that approach is not very user-friendly, but maybe it can be
made more convenient if adding syntactic sugar to allow doing it all
in a single command?

Or maybe there is some other way to implement it without the permissions model.



Re: [HACKERS] GRANT EXECUTE ON FUNCTION foo() TO bar();

From
Jim Nasby
Date:
On 2/22/17 2:51 AM, Pavel Stehule wrote:
> The solution based on rights is elegant, but in this moment I cannot to
> see all possible impacts on performance - because it means new check for
> any call of any function. Maybe checking call stack can be good enough -
> I have not idea how often use case it it.

I think the simple solution to that is not to use proacl for this 
purpose but to add an oidvector to pg_proc that is a list of allowed 
callers. If the vector is kept sorted then it's a simple binary search.

BTW, I agree that this feature would be useful, as would PRIVATE, but 
they're two separate features.
-- 
Jim Nasby, Data Architect, Blue Treble Consulting, Austin TX
Experts in Analytics, Data Architecture and PostgreSQL
Data in Trouble? Get it in Treble! http://BlueTreble.com
855-TREBLE2 (855-873-2532)