Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep ACL conditions as maps #3501

Merged
merged 13 commits into from
Jan 17, 2022
Merged

Keep ACL conditions as maps #3501

merged 13 commits into from
Jan 17, 2022

Conversation

chrzaszcz
Copy link
Member

@chrzaszcz chrzaszcz commented Jan 13, 2022

The goal is to simplify and unify the internal ACL format and the ACL matching logic.

Main changes:

  • Patterns are not converted from maps to tuples. By avoiding enumerating all allowed combinations, there are new possibilities, in particular {user = "alice", server = "localhost", resource = "res"}, which was unsupported before.
  • There was an implicit check for the domain performed only for arbitrarily chosen patterns, e.g. for {user = "alice"} but not for {resource = "res"}, which was counter-intuitive and undocumented. Now the check is called match = "current_domain" and it is enabled by default unless the user disables it with match = "all".
  • The API is now unified and simplified. The host type (which can be global) is mandatory and the domain is optional. The domain-less version is used only for corner cases: s2s and components. In these cases the check for "current_domain" is omitted because it would always fail.
    • In the previous code that check would be replaced with a check if the user's domain matches any locally hosted domain, but this one was also implicit. It's not supported in the new code atm. The ponly place where it could be useful would be to decide what users can connect to a component - either all of them or the ones from any local domain. I could add this in a new PR.

Not changed:

  • Condition values (including regular expressions) are still converted with nodeprep. It is sketchy, but it passes the tests, so I left it unchanged for the sake of brevity.

@mongoose-im

This comment has been minimized.

@mongoose-im

This comment has been minimized.

@codecov
Copy link

codecov bot commented Jan 14, 2022

Codecov Report

Merging #3501 (85bb20b) into master (b9b34c2) will decrease coverage by 0.05%.
The diff coverage is 98.14%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3501      +/-   ##
==========================================
- Coverage   81.00%   80.94%   -0.06%     
==========================================
  Files         418      418              
  Lines       32329    32318      -11     
==========================================
- Hits        26187    26160      -27     
- Misses       6142     6158      +16     
Impacted Files Coverage Δ
src/mod_muc.erl 74.77% <66.66%> (ø)
src/acl.erl 93.87% <100.00%> (+2.21%) ⬆️
src/config/mongoose_config_spec.erl 99.20% <100.00%> (-0.03%) ⬇️
src/ejabberd_c2s.erl 88.66% <100.00%> (ø)
src/ejabberd_commands.erl 87.67% <100.00%> (+0.17%) ⬆️
src/ejabberd_s2s.erl 81.46% <100.00%> (+0.21%) ⬆️
src/ejabberd_s2s_in.erl 77.11% <100.00%> (+0.09%) ⬆️
src/ejabberd_sm.erl 84.59% <100.00%> (-0.33%) ⬇️
src/mam/mod_mam.erl 88.57% <100.00%> (ø)
src/mam/mod_mam_muc.erl 74.01% <100.00%> (ø)
... and 13 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b9b34c2...85bb20b. Read the comment docs.

Functional changes:
- More possibilities to combine rules
- Domain check is now explicit with #{match => all}
- Domain can't be 'global' anymore,
  because user's one can be passed instead with the same effect
@mongoose-im

This comment has been minimized.

@mongoose-im

This comment has been minimized.

Maps are now handled in acl.erl
'nodeprep' for all values is kept as it seems to be good enough.
The name was updated as the functions were unified.
The  module does not support dynamic domains yet,
but the host type can be safely obtained from the server host.
The host type can be safely obtained here.
This is now used:
- By s2s when the "user" is actually another server.
- By components when the "server" is a component.

In both cases the 'current_domain' check would never succeed,
so the user would always have to add 'match = "all"' to the ACL.
Expect the default 'match => current_domain' condition as well.
@mongoose-im

This comment has been minimized.

s2s tests need domain to host type resolution now
It is not needed, the pattern is valid without it.
The main change is the default condition 'match = "current_domain"',
which was implicit and hard to control before the changes.
@chrzaszcz chrzaszcz changed the title Acl spec map Keep ACL conditions as maps Jan 14, 2022
@mongoose-im

This comment has been minimized.

@chrzaszcz chrzaszcz marked this pull request as ready for review January 14, 2022 15:15
@mongoose-im
Copy link
Collaborator

mongoose-im commented Jan 14, 2022

small_tests_24 / small_tests / 85bb20b
Reports root / small


small_tests_23 / small_tests / 85bb20b
Reports root / small


dynamic_domains_mysql_redis_24 / mysql_redis / 85bb20b
Reports root/ big
OK: 2673 / Failed: 0 / User-skipped: 248 / Auto-skipped: 0


dynamic_domains_pgsql_mnesia_24 / pgsql_mnesia / 85bb20b
Reports root/ big
OK: 2690 / Failed: 0 / User-skipped: 231 / Auto-skipped: 0


dynamic_domains_pgsql_mnesia_23 / pgsql_mnesia / 85bb20b
Reports root/ big
OK: 2690 / Failed: 0 / User-skipped: 231 / Auto-skipped: 0


dynamic_domains_mssql_mnesia_24 / odbc_mssql_mnesia / 85bb20b
Reports root/ big
OK: 2690 / Failed: 0 / User-skipped: 231 / Auto-skipped: 0


ldap_mnesia_23 / ldap_mnesia / 85bb20b
Reports root/ big
OK: 1500 / Failed: 0 / User-skipped: 390 / Auto-skipped: 0


ldap_mnesia_24 / ldap_mnesia / 85bb20b
Reports root/ big
OK: 1500 / Failed: 0 / User-skipped: 390 / Auto-skipped: 0


internal_mnesia_24 / internal_mnesia / 85bb20b
Reports root/ big
OK: 1541 / Failed: 0 / User-skipped: 349 / Auto-skipped: 0


pgsql_mnesia_23 / pgsql_mnesia / 85bb20b
Reports root/ big
OK: 3077 / Failed: 0 / User-skipped: 240 / Auto-skipped: 0


pgsql_mnesia_24 / pgsql_mnesia / 85bb20b
Reports root/ big
OK: 3077 / Failed: 0 / User-skipped: 240 / Auto-skipped: 0


mysql_redis_24 / mysql_redis / 85bb20b
Reports root/ big
OK: 3072 / Failed: 0 / User-skipped: 245 / Auto-skipped: 0


elasticsearch_and_cassandra_24 / elasticsearch_and_cassandra_mnesia / 85bb20b
Reports root/ big
OK: 1834 / Failed: 0 / User-skipped: 361 / Auto-skipped: 0


mssql_mnesia_24 / odbc_mssql_mnesia / 85bb20b
Reports root/ big
OK: 3077 / Failed: 0 / User-skipped: 240 / Auto-skipped: 0


riak_mnesia_24 / riak_mnesia / 85bb20b
Reports root/ big
OK: 1680 / Failed: 0 / User-skipped: 362 / Auto-skipped: 0

Copy link
Contributor

@Premwoik Premwoik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, it looks good to me :)

Copy link
Collaborator

@NelsonVides NelsonVides left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems very well written to me, got a better idea about what ACLs are, so this is already a win :)

I have one comment for something I suspect might be unsafe and this could be a good opportunity to improve.

I also see some places for micro performance improvements, like, non-compiled regexes, or more common, when we do match_acl for a non-global host-type, we fetch the acl lists for both the host-type and global, and do ++, which, if the lists are big, can incur into a lot of garbage being generated. I do mind a bit because this kind of code is run everywhere in all sorts of tight loops, so I just wanted to raise awareness for potentially slow code. Nevertheless this was already like that (I just never explored this code much), it is not related to the scope of this task, and we can work on that later when we get some client deployment using ACLs and asking for improvements 🚀

Comment on lines +974 to 975
case acl:match_rule(HostType, LServer, max_user_sessions, JID) of
Max when is_integer(Max) -> Max;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just makes me realise, I think we're not checking that this number is strictly positive, right? 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't, that's right, it might be good to fix next.

Regarding the '++' on host and global rules, I am rewriting this right now so that it will be precomputed per host type. Expect a PR today 🙂

case acl:match_rule(
From, max_s2s_connections, jid:make(<<"">>, To, <<"">>)) of
{ok, HostType} = mongoose_domain_api:get_host_type(From),
case acl:match_rule(HostType, max_s2s_connections, jid:make(<<"">>, To, <<"">>)) of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<<"">> triggers me

Copy link
Member Author

@chrzaszcz chrzaszcz Jan 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, it was already there... 🙈

Copy link
Contributor

@arcusfelis arcusfelis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks ok.

@arcusfelis arcusfelis merged commit 86ba0f1 into master Jan 17, 2022
@arcusfelis arcusfelis deleted the acl-spec-map branch January 17, 2022 17:42
@Premwoik Premwoik added this to the 5.1.0 milestone May 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants