Skip to content

Add API accounts with command and server permissions - #1317

Open
iliaross wants to merge 13 commits into
masterfrom
dev/api-account-permissions
Open

iliaross wants to merge 13 commits into
masterfrom
dev/api-account-permissions

Conversation

@iliaross

Copy link
Copy Markdown
Member

Hello Jamie,

This PR adds dedicated API accounts for scripts, curl, and agents. Administrators choose which commands each account can run and which virtual servers, templates, and plans it can use.

For example, an account can create virtual servers without permission to list, change, or delete them. Accounts start with no command permissions, and commands added later are not allowed automatically.

Accounts can be managed through the API Access page or root-only CLI commands. They have no Unix login, and the companion Webmin change webmin/webmin#2901 blocks access to the Webmin interface and general RPC.

Scripts and AI agents should only receive the access their task needs. Separate accounts with permissions users can review and revoke reduce the need to share administrator credentials and give users a concrete reason to trust automation with their servers.

@iliaross

Copy link
Copy Markdown
Member Author

Example:

image image

Comment thread run-api-command.pl
}
&require_mail();

if (&is_api_access_user()) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you explain what is happening here exactly? Is the goal to allow non-root users to run API commands?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This check simply determines if the caller is a dedicated API account.

The goal is to let that account run approved API commands without giving it root credentials. As I showed earlier, an administrator can create an API login and choose which commands and virtual servers it can access.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Root meaning Webmin root, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Meaning a standard/privileged Webmin user, that always is root.

Comment thread api-account-cli.pl

# Reject HTTP and in-process dispatch before reading configuration or passwords.
# Both UIDs must be root; Webmin initialization must not promote a setuid caller.
if ($< != 0 || $> != 0 || $module_name ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In that situation would this be run by a non-root user? Everything in Webmin runs as root, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In that situation would this be run by a non-root user?

This check protects the account-management CLI only, so the UID checks reject someone invoking the script directly as a non-root Unix user.

And, the remaining checks reject HTTP and in-process calls, even as root. Creating or changing API accounts using these commands is restricted to root on the CLI.

Everything in Webmin runs as root, right?

Jamie, of course! Nothing changes about how commands run. Nothing. Webmin still runs them as before.

Again, overall change just checks which commands the API account is allowed to run and which virtual servers it can access.

Comment thread virtual-server-lib.pl Outdated

# Require the API entry point and account policy before loading module helpers.
# Reject API accounts if Webmin lacks the endpoint restriction checks.
if ($access{'api_id'} ||

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is this ACL checking happening here? It seems like an odd place to be checking permissions in one the libraries, compared to how other permissions checks in Virtualmin work.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It only stopped API accounts from using other pages, even when Webmin is below the expected version that doesn't have API-only checks.

I'd rather update the module.info dependency instead. I've cleared this up to drop this overly defensive checks.

Comment thread api_access.cgi Outdated
require './virtual-server-lib.pl';
&ReadParse();
&master_admin() || &error($text{'apiaccess_ecannot'});
defined(&webmin_user_api_only) && defined(&ui_multi_select_list) &&

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why would these not be defined?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Same, dropped now. Thanks.

Comment thread api_access.cgi Outdated
print &ui_page_start();
@users = &list_api_access_users();

if (!$in{'new'} && !defined($in{'user'})) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why not have separate CGIs for the list of users and for editing one user, like we do elsewhere in Virtualmin ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed. Fixed now too.

Comment thread api-access-lib.pl
# The pro flag marks commands that need Pro when run by a dedicated API account.
# Scoped commands enforce account permissions themselves. Other commands may
# affect resources outside the account's domain list.
sub list_api_access_commands

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this function actually parsing all the other .pl files? That seems like an odd solution to me, better to have an actual list of commands like we do in commands-lib.pl

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Alright, the latest patch 15ae76a moves discovery into list_api_commands sub in commands-lib.pl file, and now shared by both, so my new API Access no longer has its own scanner.

Comment thread remote.cgi Outdated
# A master HTTP login cannot invoke terminal-only account management either.
&is_api_account_command($in{'program'}) &&
&api_error($text{'remote_eclionly'});
# Only dedicated API accounts need this edition check; other logins keep

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"edition check" ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, it checks for GРL or Рrо еdition. Commands like create-domain, clone-domain, disable-domain, and enable-domain should require Рrо when used with this new dedicated API. The idea is to keep this consistent with our existing reseller features, which are already Рrо-only.

image

@jcameron

Copy link
Copy Markdown
Collaborator

I'm sorry to say it, and maybe I am just dumb, but this code is very hard to review! Was it written by hand or with some AI tool? The flow and style and permissions system is unlike the rest of Virtualmin, so it's hard for me to understand what is going on.

Also, are these API accounts supposed to be secure in that they have access to only manage a subset of domains, and are guaranteed to not be able to effect anything outside of them? Sort of like what we support already for domain owner and reseller accounts.

@iliaross

Copy link
Copy Markdown
Member Author

Also, are these API accounts supposed to be secure in that they have access to only manage a subset of domains, and are guaranteed to not be able to effect anything outside of them? Sort of like what we support already for domain owner and reseller accounts.

Similar, yes. Think of it as a gate in front of the existing commands. A login allowed only list-users for example.tld can list users there. It cannot run other commands, log into the Webmin UI, or use generic Webmin RPC. Webmin still runs the approved command as usual though.

For create-domain, the administrator chooses which plans and templates the account can use. It can create new top-level servers using those settings and the plan's limits, and creating a sub-server also requires access to its parent.

Some commands affect the whole server. If an administrator explicitly grants one of those, the selected-domain list does not limit its effects. Those commands are shown separately in the UI.

And again, we reuse Virtualmin's existing commands and permission helpers. There is only new logic to check which commands an API account may run and which servers, plans and templates it may use. So I’m not rebuilding the existing security checks.

I'm sorry to say it, and maybe I am just dumb, but this code is very hard to review! Was it written by hand or with some AI tool? The flow and style and permissions system is unlike the rest of Virtualmin, so it's hard for me to understand what is going on.

Yes, I used AI to help (re-)write, and test through and through in particular. However, I came up with it, then designed it and rewrote it a handful of times until I was satisfied with it.

This fixes the API account form to show the automatic server access switch only under Selected only, where it has an effect.

Switching to All preserves its saved value.

It also simplifies the help and renames the switch to Automatically include servers this account creates.
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.

2 participants