-
Notifications
You must be signed in to change notification settings - Fork 350
WIP: ACLs #4013
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
Draft
nrwahl2
wants to merge
123
commits into
ClusterLabs:main
Choose a base branch
from
nrwahl2:nrwahl2-acls
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
WIP: ACLs #4013
+2,275
−1,130
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Don't do other best practices yet. Those will be in upcoming commits. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Also use const for the GList iterator and the xml_acl_t variable. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
If the "else"/"docpriv->acls == NULL" block was executed, then target was set to NULL, which meant we wouldn't do anything else before returning true. Also drop some redundancies: * The dropped trace message doesn't seem very helpul. * pcmk__xml_copy() is guaranteed to return non-NULL if its second argument is non-NULL. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Nothing in the loop can set it to NULL. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Only element nodes have attributes. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
5b2ccd1 to
b35c6bd
Compare
Call pcmk__xe_remove_matching_attrs(), which is made for this purpose. Write a simple match function to ensure we only remove non-ID attributes. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And rename pcmk__apply_acl() to pcmk__apply_acls(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
The pcmk__if_tracing() block makes sense but it feels like premature optimization and makes the code harder to read. I'm not worried about the overhead of allocating and freeing a small GString each time we apply an ACL. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Also rename a variable and drop a trace message that seems unhelpful. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
We drop a trace log in order to do this. To get the number of matches from pcmk__xpath_foreach_result(), we'd have to pass a struct as user data to hold both the ACL itself and the match count. That doesn't seem worth the trouble. We still have the trace message after applying an ACL to a particular match. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And rename to pcmk__unpack_acls(). In general, we assume that an XML node has a non-NULL doc and that its doc has a non-NULL _private field. If we ever want to start checking that (in case a node somehow originated outside of pcmk__xe_create()), we should do it more broadly. The two callers already ensure that target is not NULL. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
It is possible that these values won't get used, but fetching and setting them is pretty lightweight. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Or at least try to clarify it a bit, by returning early if not target or group. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Use the second argument of pcmk__xe_first_child() and pcmk__xe_next() to specify what type of element to get (PCMK_XE_ACL_ROLE). Also unindent a block with pcmk__trace() in it, and use pcmk__xe_id(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
An acl_permission element's ID is currently used only for logging. So we can be permissive and allow this. It seems that our usual approach to things that the schema doesn't allow is to continue processing them if it's possible (for example, if it doesn't result in a broken reference). So warn here. For missing or invalid "kind" attribute, we have to ignore the element, so set a config error. It doesn't look as if we're very consistent about when we set warnings vs. errors, so I'm just doing what feels like it makes the most sense. We could just as well call all of these warnings or call all of these errors. Also, log the parent type and ID parenthetically for errors other than missing ID. If we proceeded with unpacking an acl_permission element without an ID, we want any further log messages to have some identifying information about where or what the acl_permission element is. It doesn't hurt to log this even if the acl_permission's ID is set. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
So that it's beneath its helpers. No code changes otherwise. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Further improvements are coming. For now, we have a recursive call and a new (temporary) forward declaration of parse_acl_entry(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
This involves removing some const qualifiers, because pcmk__xpath_search() takes a non-const xmlDoc. Our convention is to use a non-const pointer argument whenever we use one of the argument's fields (in this case, the doc field) as a non- const. At first, this feels like a use case for pcmk__xe_resolve_idref(), but that function would need to be extended in at least two ways: * It would need to match a PCMK_XA_ID attribute instead of a PCMK_XA_ID_REF attribute. * It would need to match a referenced element whose type differs from that of the referencing element (PCMK_XE_ACL_ROLE vs. PCMK_XE_ROLE). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And rename to unpack_acl_target(). We could simplify further, except that we've been allowing <acl_target> and <acl_group> elements to contain <acl_permission> elements and unpacking them in violation of the schema. I've marked this as "fix" to add to the change log, because it does change behavior: if <role> elements are nested within <acl_role> elements, they will now be ignored. They should never have been configured in the first place. Thus far, I have made an effort to maintain backward compatibility even for configurations that the schema doesn't allow. I have not done so here. A workaround would risk an infinite loop of following references, and trying to prevent that is not worth the trouble. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And make it static. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
This is similar to pcmk__xml_tree_foreach(), except for the following: * It removes a node and its subtree if the function returns true. pcmk__xml_tree_foreach() would have a use-after-free if its function freed its xmlNode * argument. (This has not been observed with any existing calls.) * pcmk__xml_tree_foreach_remove() currently offers no way to stop iterating. The function's return value instead tells us whether to remove a node. Obviously we don't recurse down a freed node's subtree, however. * The function does not currently accept user data. A user data argument may be added later if needed. * pcmk__xml_tree_foreach_remove() returns void. We can later return a boolean or integer value if we need to know whether any nodes were removed. Nothing uses this yet. Also correct the Doxygen of pcmk__xml_tree_foreach() (fn is an [in] parameter) and add a note that fn may not remove its argument. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
And change its name to pcmk__check_creation_acls(), since it's checking rather than applying ACLs. Use pcmk__xml_tree_foreach_remove() to "drive" the recursion, instead of building it into pcmk__check_creation_acls(). Functionize the main logic into the helper check_creation_disallowed(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
If xml->doc or xml->doc->_private were NULL, then we would not have called this function. See pcmk__xml_doc_all_flags_set(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Note to reviewer: this code is expected to be removed a few commits from now. This commit was part of my process of trying to understand the filtering logic. It may make review easier, or it may make it more tedious. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Note to reviewer: this code is expected to be removed a few commits from now. This commit was part of my process of trying to understand the filtering logic. It may make review easier, or it may make it more tedious. Use pcmk__xpath_foreach_result(). Also drop a trace message, for two reasons: * We don't have easy access to num_results anymore. (We'd have to get it via a counter variable or something.) * The message tells us how many nodes were filtered by a given XPath, but not which nodes. So it doesn't seem especially useful. If we want tracing for ACL filtering (which seems like a reasonable thing to want), then we should make it more granular so that it's informative. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
There's no reason to filter all the children if we can already tell that we're going to deny the user access to the entire document. Also drop the NULL-check of target. It's guaranteed non-NULL by this point. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
This is less for efficiency and more for understandability, before we make a larger change to this code. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
b35c6bd to
a8c05ce
Compare
This is a substantial refactor. Most of the details are in the comments.
It took me days to understand exactly what xml_acl_filtered_copy() was
doing, particularly in the calls to purge_xml_attributes(). For a while
I was pretty sure that we could be exposing "denied" children if an
ancestor had the pcmk__xf_acl_read or pcmk__xf_acl_write flag set. I'm
no longer confident that was the case, although it may have been.
The whole process was convoluted. We unpacked all of a user's ACLs and
applied them to matching nodes throughout the document. Then we went
through the unpacked list of a user's ACLs (docpriv->acls) and found the
ones with "deny" permissions and non-NULL xpath. (By the way, I believe
all ACLs should have non-NULL xpath by that point.)
Then for each of those "deny" ACLs, we filtered the document based on
it. We ran an XPath query to find all the nodes in the document that
matched the "deny" ACL, and we called purge_xml_attributes() on each
such node. A return value of true indicated that the current node either
was readable or had at least one readable descendant.
* If the current node had the pcmk__xf_acl_read or pcmk__xf_acl_write
flag set (is_mode_allowed()), then it was readable and we returned
true immediately. Some read or write ACL had matched that node during
the apply stage. Of course this could never be true for the top-level
call, because the top-level call was always for some node that a
"deny" ACL had matched.
* Otherwise, the current node was unreadable. We called
purge_xml_attributes() on all children.
- If any children returned true, then we had at least one readable
descendant. We removed all attributes except for ID and then
returned true.
- Otherwise, we had no readable descendants. Since the current node
was also unreadable, we removed the current node's subtree and
returned false.
As mentioned, this was convoluted. The key observation is that before we
did any of that, we had already applied all the ACLs throughout the
document. So all we have to do is recurse from the top down, determine
which nodes are readable for the current ACL user, and filter out the
rest. The comments explain how this works.
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
To replace xml_acl_filtered_copy(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Perform a CIB query as a given user if you want to filter CIB XML as that user. This function shouldn't have been used for arbitrary (non-CIB) XML anyway. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
a8c05ce to
85e299e
Compare
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
To replace pcmk_acl_required(). Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
It's in utils.c, not acl.c. Signed-off-by: Reid Wahl <nrwahl@protonmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.