Skip to content

Fine-Grained Role Configuration for Console Access (hawtio) #222

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

Merged

Conversation

4nt01ne
Copy link
Contributor

@4nt01ne 4nt01ne commented Apr 17, 2025

Hi all,

This draft PR is intended to kick off a discussion on the best approach to enhance console access configuration.

Current state:
The proposed changes introduce breaking updates to the following variables:

  • activemq_hawtio_role
  • activemq_management_access_default
  • activemq_management_access_domains
    ...as well as the related templates.

However, the new default values preserve the existing behavior, so setups that don’t override these variables won’t be impacted.

Background:
We’re using the Red Hat downstream amq_broker collection and plan to raise a support request referencing this PR.

Our challenge:
We need more granular control over which roles can access the Jolokia console. Specifically:

  • Some roles need full access.
  • Some roles require scoped access per domain/key.
  • Others roles should only access the console, without permission to produce nor consume addresses.

We’ve already implemented this logic in our own Ansible code, but it conflicts with the current activemq role causing unwanted broker restarts on every run.

To support our production rollout, we’d like to upstream this capability.

Highlights of this PR:

  • activemq_hawtio_role is now an array. Each role is applied to all entries in activemq_management_access_domains. If methods are defined with an empty roles array, it falls back to this default.
  • activemq_management_access_default and activemq_management_access_domains allow assigning specific permissions to roles per MBean method.
  • activemq_management_access_domains enables fine-grained access control at the domain and/or key level.
  • A new test module, console_access, verifies the new behavior—all existing tests pass with the updated defaults.
  • Documentation has been updated accordingly.

Note on backward compatibility:
To avoid breaking changes, we could add logic in the templates to detect and apply the new structure only if explicitly used.

Looking forward to your feedback and suggestions!

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 18, 2025

Our Red Hat Case number: 04120046

@4nt01ne 4nt01ne marked this pull request as draft April 18, 2025 07:57
@guidograzioli guidograzioli added the major_changes Major changes mean the user can CHOOSE to make a change when they update but do not have to label Apr 22, 2025
@guidograzioli
Copy link
Member

Thanks a lot for your contribution. I'd really prefer to handle the management xml using xpath/xsd, but let me go thru the molecule test (kudos) and see how it behaves. Happy to co-author, btw?

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 22, 2025

you're welcome ;-) @guidograzioli .
Be my guest to handle the feature how you like.
I will be more than happy to co-author (I am learning ansible and would like to learn from others)

@guidograzioli
Copy link
Member

Cool; since this is a major change, I'll release the current patch version, then bump and this PR will be the headline of version 2.3 :)

@RanabirChakraborty
Copy link
Member

@4nt01ne can you please resolve the lint issues as well?

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 22, 2025

sure @RanabirChakraborty. I am trying to figure out what is still wrong in the task name

@guidograzioli
Copy link
Member

guidograzioli commented Apr 22, 2025

sure @RanabirChakraborty. I am trying to figure out what is still wrong in the task name

roles/activemq/tasks/user_roles.yml:24: task_has_valid_name: Invalid task name 'Unique security settings roles'
roles/activemq/tasks/user_roles.yml:28: task_has_valid_name: Invalid task name 'Unique default management roles'
roles/activemq/tasks/user_roles.yml:32: task_has_valid_name: Invalid task name 'Unique management roles'
roles/activemq/tasks/user_roles.yml:36: task_has_valid_name: Invalid task name 'All activemq roles'

Just prepend the task names with "Set ...." or "Make ... " (or anything here, it's a picky linter rule, but it helps maintaining the quality level of task names)

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 22, 2025

@RanabirChakraborty, linting is fixed but "Download activemq archive" is failing in a workflow

@guidograzioli
Copy link
Member

That's alright, there's been multiple CI jobs and all the concurrent downloads makes apache.org throttle us down. I'll re-run the jobs in a bit and start the review in the meantime

@guidograzioli guidograzioli marked this pull request as ready for review April 22, 2025 14:25
@cmasopust
Copy link

cmasopust commented Apr 24, 2025

IMHO this solution can only be the first part of a fine-grained role configuration because in this stage (if I understand it correctly), it only allows to define fine-grained access to different domains but always for all roles in activemq_hawtio_role. But I think usually there will be the need to define different permissions for different roles, e.g. have an admin role, have a read-only role, etc.

@guidograzioli
Copy link
Member

The goal for the collection is to support any configuration allowed in activemq; mind that this is still WIP and will only be part of the next major release. I am more than happy to consider an alternate/parallel implementation PR or to welcome more co-authors in this PR.

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 24, 2025

I'm not sure if I fully understand your remark, @cmasopust.

The changes introduced in this PR allow the following:

  • You can grant any desired level of permissions to all roles listed in activemq_hawtio_role. These roles will be automatically appended to each defined permission. If you want specific permissions exclusively for roles in activemq_hawtio_role, you can define an empty array for the other roles, and only activemq_hawtio_role roles will be included.

  • You can configure access permissions for any role at either the default level or specific domain levels, and optionally refine permissions further with domain-specific keys.

Example

Given the following configuration:

activemq_hawtio_role: ['admin', 'operator']
activemq_management_access_default:
  - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
    roles: ['read-only']
  - methods: ['set*', '*']
    roles: []
activemq_management_access_domains:
  - accesses:
      - methods: ['list*', 'get*', 'is*', 'set*', 'browse*', 'count*', '*']
        roles: []
  - key: 'address=queue.*'
    accesses:
      - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
        roles: ['specific']
      - methods: ['set*', '*']
        roles: []
  - name: 'com.myapp'
    key: 'address=intern.*'
    accesses:
      - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
        roles: ['business']
      - methods: ['set*', '*']
        roles: []

This configuration generates the following management.xml. The default domain when not specified is "org.apache.activemq.artemis":

<management-context xmlns="http://activemq.apache.org/schema">
  <authorisation>
    <allowlist>
      <entry domain="hawtio"/>
    </allowlist>
    <default-access>
      <access method="list*" roles="read-only,admin,operator"/>
      <access method="get*" roles="read-only,admin,operator"/>
      <access method="is*" roles="read-only,admin,operator"/>
      <access method="browse*" roles="read-only,admin,operator"/>
      <access method="count*" roles="read-only,admin,operator"/>
      <access method="set*" roles="admin,operator"/>
    </default-access>
    <role-access>
      <match domain="org.apache.activemq.artemis">
        <access method="list*" roles="admin,operator"/>
        <access method="get*" roles="admin,operator"/>
        <access method="is*" roles="admin,operator"/>
        <access method="browse*" roles="admin,operator"/>
        <access method="count*" roles="admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
      <match domain="org.apache.activemq.artemis" key="address=queue.*">
        <access method="list*" roles="specific,admin,operator"/>
        <access method="get*" roles="specific,admin,operator"/>
        <access method="is*" roles="specific,admin,operator"/>
        <access method="browse*" roles="specific,admin,operator"/>
        <access method="count*" roles="specific,admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
      <match domain="com.myapp" key="address=intern.*">
        <access method="list*" roles="business,admin,operator"/>
        <access method="get*" roles="business,admin,operator"/>
        <access method="is*" roles="business,admin,operator"/>
        <access method="browse*" roles="business,admin,operator"/>
        <access method="count*" roles="business,admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
    </role-access>
  </authorisation>
</management-context>

If you are suggesting extending this further to allow different fine-grained permissions per role beyond what is already achievable, please clarify.
But as @guidograzioli is suggesting, you're welcome to co-author this PR.

@cmasopust
Copy link

I'm not sure if I fully understand your remark, @cmasopust.

The changes introduced in this PR allow the following:

  • You can grant any desired level of permissions to all roles listed in activemq_hawtio_role. These roles will be automatically appended to each defined permission. If you want specific permissions exclusively for roles in activemq_hawtio_role, you can define an empty array for the other roles, and only activemq_hawtio_role roles will be included.
  • You can configure access permissions for any role at either the default level or specific domain levels, and optionally refine permissions further with domain-specific keys.

Example

Given the following configuration:

activemq_hawtio_role: ['admin', 'operator']
activemq_management_access_default:
  - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
    roles: ['read-only']
  - methods: ['set*', '*']
    roles: []
activemq_management_access_domains:
  - accesses:
      - methods: ['list*', 'get*', 'is*', 'set*', 'browse*', 'count*', '*']
        roles: []
  - key: 'address=queue.*'
    accesses:
      - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
        roles: ['specific']
      - methods: ['set*', '*']
        roles: []
  - name: 'com.myapp'
    key: 'address=intern.*'
    accesses:
      - methods: ['list*', 'get*', 'is*', 'browse*', 'count*']
        roles: ['business']
      - methods: ['set*', '*']
        roles: []

This configuration generates the following management.xml. The default domain when not specified is "org.apache.activemq.artemis":

<management-context xmlns="http://activemq.apache.org/schema">
  <authorisation>
    <allowlist>
      <entry domain="hawtio"/>
    </allowlist>
    <default-access>
      <access method="list*" roles="read-only,admin,operator"/>
      <access method="get*" roles="read-only,admin,operator"/>
      <access method="is*" roles="read-only,admin,operator"/>
      <access method="browse*" roles="read-only,admin,operator"/>
      <access method="count*" roles="read-only,admin,operator"/>
      <access method="set*" roles="admin,operator"/>
    </default-access>
    <role-access>
      <match domain="org.apache.activemq.artemis">
        <access method="list*" roles="admin,operator"/>
        <access method="get*" roles="admin,operator"/>
        <access method="is*" roles="admin,operator"/>
        <access method="browse*" roles="admin,operator"/>
        <access method="count*" roles="admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
      <match domain="org.apache.activemq.artemis" key="address=queue.*">
        <access method="list*" roles="specific,admin,operator"/>
        <access method="get*" roles="specific,admin,operator"/>
        <access method="is*" roles="specific,admin,operator"/>
        <access method="browse*" roles="specific,admin,operator"/>
        <access method="count*" roles="specific,admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
      <match domain="com.myapp" key="address=intern.*">
        <access method="list*" roles="business,admin,operator"/>
        <access method="get*" roles="business,admin,operator"/>
        <access method="is*" roles="business,admin,operator"/>
        <access method="browse*" roles="business,admin,operator"/>
        <access method="count*" roles="business,admin,operator"/>
        <access method="set*" roles="admin,operator"/>
      </match>
    </role-access>
  </authorisation>
</management-context>

If you are suggesting extending this further to allow different fine-grained permissions per role beyond what is already achievable, please clarify. But as @guidograzioli is suggesting, you're welcome to co-author this PR.

Thanks a lot, exactly such example I was missing :) looks like I was looking at a wrong branch because in the role_access.management.xml.j2 which I looked at, the "roles" are always set to the whole content of activemq_hawtio_role.

So, sorry for the confusion and thanks a lot for that PR !!!

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 24, 2025

you're welcome @cmasopust .
FYI, if you look at the changes in this pr:

@cmasopust
Copy link

you're welcome @cmasopust . FYI, if you look at the changes in this pr:

Looking forward now for the release that contains this PR! thanks again!

@guidograzioli
Copy link
Member

ok gentleman, since you agreed on the scope of the change, and in the meanwhile i was able to recover from the CI build outage, I'll rebase the PR, force push, and then add a couple change on top of it:

  • validate the generated management.xml with the activemq.xsd schema
  • rename activemq_hawtio_role (the list) to activemq_hawtio_roles
  • reintroduce activemq_hawtio_role with default value = activemq_hawtio_roles.join(',')

please let me know if you have any comments on that

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 29, 2025

That is very good @guidograzioli.
The management.xml validation is a very good idea.
I was about to suggest to rename activemq_hawtio_role to activemq_hawtio_roles but your suggestion is better.
Please go ahead

guidograzioli and others added 2 commits April 29, 2025 19:17
Co-authored-by: Antoine Wils <antoine@wils.life>
Co-authored-by: Guido Grazioli <ggraziol@redhat.com>
Co-authored-by: Antoine Wils <antoine@wils.life>
Co-authored-by: Guido Grazioli <ggraziol@redhat.com>
@guidograzioli guidograzioli force-pushed the fine_grained_hawtio_roles branch from 013c618 to 4e2558c Compare April 29, 2025 18:50
Copy link
Member

@guidograzioli guidograzioli left a comment

Choose a reason for hiding this comment

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

LGTM

@guidograzioli
Copy link
Member

Please review my changes

Co-authored-by: Antoine Wils <antoine@wils.life>
Co-authored-by: Guido Grazioli <ggraziol@redhat.com>
@guidograzioli guidograzioli force-pushed the fine_grained_hawtio_roles branch from 4e2558c to 212bfd0 Compare April 29, 2025 19:19
@4nt01ne 4nt01ne force-pushed the fine_grained_hawtio_roles branch 3 times, most recently from cdcf4e3 to 8d6f2bc Compare April 29, 2025 21:26
Co-authored-by: Antoine Wils <antoine@wils.life>
Co-authored-by: Guido Grazioli <ggraziol@redhat.com>
@4nt01ne 4nt01ne force-pushed the fine_grained_hawtio_roles branch from 8d6f2bc to fa63854 Compare April 29, 2025 21:34
@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 29, 2025

LGTM thx!
FYI @guidograzioli: I have fixed and improved the documentation. Then I ran all the molecule tests and ansible-lint locally successfully.

@guidograzioli
Copy link
Member

Cool; I'll merge after CI completes (after the merge, your PRs won't need maintainer approval to execute CI).
Thank you very much for your contribution again

@4nt01ne
Copy link
Contributor Author

4nt01ne commented Apr 30, 2025

It was really interesting to contribute, learned quite a bit about both Contributing and Ansible along the way!

What are the next steps after the merge in terms of the release timeline @guidograzioli ?

@guidograzioli guidograzioli merged commit e6182c2 into ansible-middleware:main Apr 30, 2025
28 checks passed
@guidograzioli
Copy link
Member

The downstream redhat.amq_broker collection should hit automation hub early next week, there is more intergration testing to be performed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major_changes Major changes mean the user can CHOOSE to make a change when they update but do not have to
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants