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

CLOUDSTACK-8562: Dynamic Role-Based API Checker for CloudStack #1489

Merged
merged 4 commits into from
May 11, 2016

Conversation

rohityadavcloud
Copy link
Member

CLOUDSTACK-8562: DB-Backed Dynamic Role Based API Access Checker

This feature allows root administrators to define new roles and associate API
permissions to them.

A limited form of role-based access control for the CloudStack management server
API is provided through a properties file, commands.properties, embedded in the
WAR distribution. Therefore, customizing API permissions requires unpacking the
distribution and modifying this file consistently on all servers. The old system
also does not permit the specification of additional roles.

FS:
https://cwiki.apache.org/confluence/display/CLOUDSTACK/Dynamic+Role+Based+API+Access+Checker+for+CloudStack

DB-Backed Dynamic Role Based API Access Checker for CloudStack brings following
changes, features and use-cases:

  • Moves the API access definitions from commands.properties to the mgmt server DB
  • Allows defining custom roles (such as a read-only ROOT admin) beyond the
    current set of four (4) roles
  • All roles will resolve to one of the four known roles types (Admin, Resource
    Admin, Domain Admin and User) which maintains this association by requiring
    all new defined roles to specify a role type.
  • Allows changes to roles and API permissions per role at runtime including additions or
    removal of roles and/or modifications of permissions, without the need
    of restarting management server(s)

Upgrade/installation notes:

  • The feature will be enabled by default for new installations, existing
    deployments will continue to use the older static role based api access checker
    with an option to enable this feature
  • During fresh installation or upgrade, the upgrade paths will add four default
    roles based on the four default role types
  • For ease of migration, at the time of upgrade commands.properties will be used
    to add existing set of permissions to the default roles. cloud.account
    will have a new role_id column which will be populated based on default roles
    as well

Dynamic-roles migration tool: scripts/util/migrate-dynamicroles.py

  • Allows admins to migrate to the dynamic role based checker at a future date
  • Performs a harder one-way migrate and update
  • Migrates rules from existing commands.properties file into db and deprecates it
  • Enables an internal hidden switch to enable dynamic role based checker feature

@rohityadavcloud
Copy link
Member Author

test_staticroles.py

=== TestName: test_static_role_account_acls | Status : SUCCESS ===

scripts/util/migrate-dynamicroles.py

I'll add docs for this feature in a separate PR to admin-docs, this is the usage information:

Usage: migrate-dynamicroles.py [options]

Options:
-h, --help show this help message and exit
-b DB, --db=DB The name of the database, default: cloud
-u USER, --user=USER User name a MySQL user with privileges on cloud
database
-p PASSWORD, --password=PASSWORD
Password of a MySQL user with privileges on cloud
database
-H HOST, --host=HOST Host or IP of the MySQL server
-P PORT, --port=PORT Host or IP of the MySQL server
-f COMMANDSFILE, --properties-file=COMMANDSFILE
The commands.properties file
-d, --dryrun Dry run and debug operations this tool will perform

$ sudo ./scripts/util/migrate-dynamicroles.py
Apache CloudStack Role Permission Migration Tool
(c) Apache CloudStack Authors and the ASF, under the Apache License, Version 2.0

Running this migration tool will remove any default-role rules in cloud.role_permissions. Do you want to continue? [y/N]y
The commands.properties file has been deprecated and moved at: /etc/cloudstack/management/commands.properties.deprecated
Static role permissions from commands.properties have been migrated into the db
Dynamic role based API checker has been enabled!

test_dynamicroles.py

=== TestName: test_default_role_deletion | Status : SUCCESS ===

=== TestName: test_role_account_acls | Status : SUCCESS ===

=== TestName: test_role_account_acls_multiple_mgmt_servers | Status : SUCCESS ===

=== TestName: test_role_inuse_deletion | Status : SUCCESS ===

=== TestName: test_role_lifecycle_create | Status : SUCCESS ===

=== TestName: test_role_lifecycle_delete | Status : SUCCESS ===

=== TestName: test_role_lifecycle_list | Status : SUCCESS ===

=== TestName: test_role_lifecycle_update | Status : SUCCESS ===

=== TestName: test_role_lifecycle_update_role_inuse | Status : SUCCESS ===

=== TestName: test_rolepermission_lifecycle_create | Status : SUCCESS ===

=== TestName: test_rolepermission_lifecycle_delete | Status : SUCCESS ===

=== TestName: test_rolepermission_lifecycle_list | Status : SUCCESS ===

=== TestName: test_rolepermission_lifecycle_update | Status : SUCCESS ===

=== TestName: test_rolepermission_lifecycle_update_invalid_rule | Status : SUCCESS ===

@swill
Copy link
Contributor

swill commented Apr 12, 2016

This is a feature that we definitely need. Can I please get some code review on this PR?

@@ -143,7 +143,7 @@ def __sign(self, payload):
["=".join(
[str.lower(r[0]),
str.lower(
urllib.quote_plus(str(r[1]))
urllib.quote_plus(str(r[1]), safe="*")
Copy link
Member Author

Choose a reason for hiding this comment

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

This is ported from cloudmonkey -- https://github.com/apache/cloudstack-cloudmonkey/pull/11/files
When tests send * in the cmd arg, test failures happened due to how url encoding differs across ACS specific Java code and Python

@rohityadavcloud
Copy link
Member Author

Some screenshots *

Roles Tab:
screenshot from 2016-04-12 23-11-42

Add a new role:
screenshot from 2016-04-12 23-11-48

Adding rules to a role with API auto-completion ** (API and wildcards allowed):
screenshot from 2016-04-12 23-12-32

* feature available for root admin only
** no mgmt server restarts needed

@DaanHoogland
Copy link
Contributor

@swill @bhaisaab I started reviewing but it changed while busy, Is it done now?

@rohityadavcloud
Copy link
Member Author

@DaanHoogland I was pushing some changes and adding some info/screenshots above. Since this aims to deprecate use of commands.properties (affecting marvin and apidocs) I've a separate commit for that in this PR. All changes pushed from my end now.

@DaanHoogland
Copy link
Contributor

@bhaisaab, ok will continue tomorrow.

boolean updateRolePermission(final RolePermission rolePermission, final Rule rule, final RolePermission.Permission permission, final String description);
boolean deleteRolePermission(final RolePermission rolePermission);

List<Role> findAllRolesBy(final Long id, final String name, final RoleType roleType);
Copy link
Contributor

Choose a reason for hiding this comment

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

findAllRolesBy all three parameters? or either one of them? I will probably find out reading on but a comment/javadoc in this case would be nice (you know I'm not a fan of comments, 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.

This method tries to solve data processing for listRoles API, it can list by id (i.e. if exists, single item returned) , or returns list of role matching a name, or if nothing else passed checks if a role type was passed. @DaanHoogland do you want me to split them up into separate methods?

Copy link
Contributor

Choose a reason for hiding this comment

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

@bhaisaab, you could split them or add a javadoc so users get a clue. If the caller is in control splitting makes sense. They'd know what they are passing anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would have to agree with @DaanHoogland. Splitting into separate methods would be clearer and probably simplify the business logic per method as well (so it would be simpler to unit test).

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks fixed

response.setResponses(rolePermissionResponses);
response.setResponseName(getCommandName());
setResponseObject(response);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

same as create commands: factor out?

@DaanHoogland
Copy link
Contributor

One blocker found so far, some license headers missing.
Otherwise looks good, I wish I could say i had completely scrutinised this. It is a big chunk. I have touched everything and I will do further review while testing.

@rohityadavcloud
Copy link
Member Author

@DaanHoogland thanks, I'll fix them

@DaanHoogland
Copy link
Contributor

CI bubble run

initially test_02_redundant_VPC_default_routes failed. On manual verification it succeeded.

[root@cs1 MarvinLogs]# ssh 192.168.23.5
The authenticity of host '192.168.23.5 (192.168.23.5)' can't be established.
ECDSA key fingerprint is 61:af:15:ea:84:48:c4:78:3c:e0:b3:d5:44:30:fe:dc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.23.5' (ECDSA) to the list of known hosts.
[email protected]'s password: 
# ping -c 3 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=46 time=23.640 ms
64 bytes from 8.8.8.8: seq=1 ttl=46 time=32.166 ms
64 bytes from 8.8.8.8: seq=2 ttl=46 time=23.668 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 23.640/26.491/32.166 ms

1489.results.network.txt
1489.results.vpc_router.txt

@rohityadavcloud
Copy link
Member Author

thanks @DaanHoogland

roleType = RoleType.DomainAdmin;
break;
case Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN:
roleType = RoleType.ResourceAdmin;
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this role type? Is there any documentation on it?

Copy link
Member Author

Choose a reason for hiding this comment

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

All four default cloudstack roles -- Admin, DomainAdmin, ResourceAdmin and User. It's just an enum class, that maps these role types to account types. This method previously existed in account mgr impl, I moved it here.
They've always existed. I could not find a previous FS on this, this is the oldest document on wiki referring to RoleTypes https://cwiki.apache.org/confluence/display/CLOUDSTACK/Annotations+use+in+the+API

Copy link
Contributor

Choose a reason for hiding this comment

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

I meant the ResourceAdmin specifically. What is this role? Is there any documentation on it?

Copy link
Member Author

Choose a reason for hiding this comment

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

@pdube I think this was used to support cpbm-cloudstack integration, I don't know any documentation; please google? For backward compatibility reasons, all four roles types supported by static-role-based-checked (as in commands.properties) need to be supported.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks. I had seen it in the code and looked for more information about it, but didn't find anything conclusive

@asfgit asfgit merged commit 003b97b into apache:master May 11, 2016
asfgit pushed a commit that referenced this pull request May 11, 2016
CLOUDSTACK-8562: Dynamic Role-Based API Checker for CloudStack### CLOUDSTACK-8562: DB-Backed Dynamic Role Based API Access Checker

This feature allows root administrators to define new roles and associate API
permissions to them.

A limited form of role-based access control for the CloudStack management server
API is provided through a properties file, commands.properties, embedded in the
WAR distribution. Therefore, customizing API permissions requires unpacking the
distribution and modifying this file consistently on all servers. The old system
also does not permit the specification of additional roles.

FS:
https://cwiki.apache.org/confluence/display/CLOUDSTACK/Dynamic+Role+Based+API+Access+Checker+for+CloudStack

DB-Backed Dynamic Role Based API Access Checker for CloudStack brings following
changes, features and use-cases:
- Moves the API access definitions from commands.properties to the mgmt server DB
- Allows defining custom roles (such as a read-only ROOT admin) beyond the
  current set of four (4) roles
- All roles will resolve to one of the four known roles types (Admin, Resource
  Admin, Domain Admin and User) which maintains this association by requiring
  all new defined roles to specify a role type.
- Allows changes to roles and API permissions per role at runtime including additions or
  removal of roles and/or modifications of permissions, without the need
  of restarting management server(s)

Upgrade/installation notes:
- The feature will be enabled by default for new installations, existing
  deployments will continue to use the older static role based api access checker
  with an option to enable this feature
- During fresh installation or upgrade, the upgrade paths will add four default
  roles based on the four default role types
- For ease of migration, at the time of upgrade commands.properties will be used
  to add existing set of permissions to the default roles. cloud.account
  will have a new role_id column which will be populated based on default roles
  as well

Dynamic-roles migration tool: scripts/util/migrate-dynamicroles.py
- Allows admins to migrate to the dynamic role based checker at a future date
- Performs a harder one-way migrate and update
- Migrates rules from existing commands.properties file into db and deprecates it
- Enables an internal hidden switch to enable dynamic role based checker feature

* pr/1489:
  maven: Fix jstl version usage
  CLOUDSTACK-8562: Deprecate commands.properties
  CLOUDSTACK-8562: DB-Backed Dynamic Role Based API Access Checker
  CLOUDSTACK-9361: Centrally handle API validations

Signed-off-by: Will Stevens <[email protected]>
@rohityadavcloud
Copy link
Member Author

Thanks you @swill finally 😄

@anshul1886
Copy link

anshul1886 commented May 18, 2016

@koushik-das @swill @rhtyd Some APIs are giving permission exceptions. They can be seen by just logging into UI. I have added the commands.properties to overcome these exceptions in my setup.

@rohityadavcloud
Copy link
Member Author

@anshul1886 can you share the details, which APIs. Also, are you facing this on master or on your personal/feature branch?

@anshul1886
Copy link

@rhtyd There are many APIs. I have not prepared any list. But creating setup from scratch should reproduce it. Some operations in which it can be observed

  1. ListAffinity groups
  2. Create secondary storage

@rohityadavcloud
Copy link
Member Author

@anshul1886 I'm unable to reproduce the shared issues nor they were caught by CI/Jenkins/Travis runs. The role specific rules in role_permissions table have been copied from the last commands.properties.in file. If you've added new APIs they need to use authorized annotations.

@anshul1886
Copy link

@rhtyd Is commands.properties exist in your setup or not? If it exists then things are working fine.

@rohityadavcloud
Copy link
Member Author

@anshul1886 with dynamic-roles feature, we no longer want to use or promote use of commands.properties file which is why this has been removed in master. We no longer want to add changes/new APIs to this file as well though existing installations will continue to use the static-checker until they decide to upgrade.

You need to use the annotations as described on the wiki (this has been shared recently on dev ML as well):
https://cwiki.apache.org/confluence/display/CLOUDSTACK/Annotations+use+in+the+API
https://cwiki.apache.org/confluence/display/CLOUDSTACK/CloudStack+API+Development

I think you've not rebuilt your branch after a rebase, you need to perform a clean rebuild.

@anshul1886
Copy link

@rhtyd I have rebuilt my branch which was rebased yesterday. I am creating new setup. There is no new API introduced in my branch. I am talking about existing APIs which are failing.

After putting commands.properties I am not facing issues. But as you pointed that is not what is intended with this PR.

@rohityadavcloud
Copy link
Member Author

@anshul1886 okay, let's debug;

  • After you mvn re-built cleanly, did you run mvn deploydb?
  • If yes, what is the output of: select * from configuration where name='dynamic.apichecker.enabled'\G;
    For a fresh/clean install, the value should be 'true'.
  • Do you see any rules in cloud.role_permissions table for admin user (role_id=1). Default root admins (or account created using the default root admin role) are allowed all APIs. Are you using CloudStack as a non-root admin?
  • Check that there is no commands.properties file in the classpath for dynamic-roles to work. None of the apichecker will work if you've a commands.properties file in classpath but have dynamic.apichecker.enabled set to true. Try git clean -fdx to get rid of non-tracked files, or do a find and remove commands.properties file.
  • Check role_id column in cloud.accounts table, it should be 1 for root admin accounts. If it's NULL, something went wrong with the upgrade path.
  • Check errors on why the APIs are failing are you seeing, open Chrome dev-tools etc and share the results. Also check api/mgmt server logs.

@swill
Copy link
Contributor

swill commented May 18, 2016

If we have to revert this, it will be a mess. Lets try to get to the bottom of this ASAP as the freeze is basically here...

@rohityadavcloud
Copy link
Member Author

rohityadavcloud commented May 18, 2016

@swill Travis and your CI are passing with this feature during which a data center is deployed and all sorts of APIs are called so it's likely an env issue specific for @anshul1886. We've put a lot of testing effort on this including various upgrade scenarios, and have seen huge amount of effort on code review so it is not needed to revert the feature; though if there is a valid bug it ought to be fixed and that's what freeze is about -- fixing bugs.

Here what I'm speculating where it is failing:
Developer sets up CloudStack with a db schema prior to when RBAC was merged. Then, the developer rebuilds CloudStack but does not redeploy a fresh/clean db, and commands.properties.in is removed so his static-checker won't work. The root admin with role_id=1 is by default allowed all APIs in the dynamic checker so the feature ensures that root-admin is never locked out of the system. The developers ought to cleanly rebuild CloudStack and re-deploy a fresh db after a rebase in their feature branch or on master.

Lastly, even after request I'm yet to see some valid logs, exception, screenshots etc from @anshul1886 that would help me debug and fix the issue, if any.

@swill
Copy link
Contributor

swill commented May 18, 2016

I agree. But I have not tested the UI at all. Has your team been testing through the UI as well as through the API?

@rohityadavcloud
Copy link
Member Author

@swill yes sir. I'll personally make sure to perform another test round tomorrow both with UI, marvin and APIs/cloudmonkey.

@swill
Copy link
Contributor

swill commented May 18, 2016

@rhtyd thank you sir. I am trying to get everything ready to freeze. Damn this is a lot of work. :(

@anshul1886
Copy link

@rhtyd Its a clean setup. It is not even complete because of one other bug introduced by PR #816.

Summary of the steps:

  1. mvn -P systemvm clean install -DskipTests
  2. mvn -P developer -pl developer -Ddeploydb
  3. mvn -pl :cloud-client-ui jetty:run
  4. Open UI start seeing those errors.

For commit history on my setup see PR #351.

And that commits code is not even coming into picture.

To go ahead I have disabled dynamic.apichecker.enabled and copied the commands.properties file. After that I was blocked by the bug introduced by #816. So I have not completed my setup.

@rohityadavcloud
Copy link
Member Author

@anshul1886 I'm yet to see chrome dev-tool screenshots, actual errors reported in the UI and see answers for questions I asked; again -- the role_id in accounts table, your environment info (win/linux/osx etc).

Now, I cannot guarantee that this will work in your feature branch as I don't know what changes your branch has; I've only tested master with a fresh environment on a linux machine and it is working for me both using maven and using rpms http://packages.shapeblue.com/cloudstack/custom/master-rbac:

screenshot from 2016-05-19 10-43-47

Created a user with user role:

screenshot from 2016-05-19 10-45-19

Was able to log in:

screenshot from 2016-05-19 10-45-39

@anshul1886
Copy link

screen shot 2016-05-19 at 11 34 36 am

screen shot 2016-05-19 at 11 35 06 am

screen shot 2016-05-19 at 11 36 20 am

screen shot 2016-05-19 at 11 36 58 am

@rhtyd Same results on master. I have not done anything in setup.

My dev box is ubuntu 12.04

@anshul1886
Copy link

anshul1886 commented May 19, 2016

@rhtyd Default value for dynamic.apichecker.enabled is true. role_id for default account is 1. In logs only exception I am getting is
Exception caught error running commands: Cannot run program "/usr/bin/ipmitool": error=2, No such file or directory
2016-05-19 11:24:45,141 ERROR o.a.c.o.d.i.IpmitoolOutOfBandManagementDriver (logid:) OutOfBandManagementDriver ipmitool failed initialization with error: Cannot run program "/usr/bin/ipmitool": error=2, No such file or directory; standard output: null

@rohityadavcloud
Copy link
Member Author

rohityadavcloud commented May 19, 2016

@anshul1886 is this environment installed using rpms/deb or it's a developer machine with Ubuntu 12.04? Would you prefer a GTM to get to the bottom of the issue, instead of back and forth on PR/ML?

@anshul1886
Copy link

dev machine which I am using for last 2-3 years

@rohityadavcloud
Copy link
Member Author

rohityadavcloud commented May 19, 2016

@anshul1886 if you need help join this GTM now: https://app.gotomeeting.com/?meetingId=981540549 (or use the meeting id for a desktop client). I've personally tested master and I think the issues you're presenting are your specific env related.

I'll wait for you for about 15-20 mins.

@abhinandanprateek
Copy link
Contributor

@rhtyd @anshul1886 This week I rebased the ospf changes with current master and did not have any issues. OSPF adds 2 new APIs and they are using the new scheme of things, looked good to Marvin and UI.

@rohityadavcloud
Copy link
Member Author

@swill I had a GTM with Anshul to figure out the issue, his environment is not clean and I've asked him to setup a new environment (effectively a new dev box). I've shared notes with him that if commands.properties file is present anywhere on the classpath with the dynamic feature enabled would cause issues as requirement for dynamic roles feature to work is that the commands.properties file does not exist on the classpath.

@anshul1886
Copy link

@rhtyd It looks fine now. It was present in some tomcat folder.

@swill
Copy link
Contributor

swill commented May 19, 2016

Thanks guys for getting that sorted out. Is the problems that @anshul1886 ran into something that others could potentially run into? Would it be useful to document the problem and the solution so others can benefit from it if they run into it?

@rohityadavcloud
Copy link
Member Author

@swill the problem was environment dependent where an unclean environment was used to build/run management server, it is recommended to git clean -fdx one's local repository (or at least run a mvn clean -P developer,systemvm -Dnoredist -Dsimulator) to get rid of old files.

The case has been documented on the FS that for dynamic roles feature to work the setting value should be true and there should be no commands.properties file readable on the classpath.

@swill
Copy link
Contributor

swill commented May 19, 2016

@rhtyd thanks, just wanted to make sure we extracted anything that was useful from @anshul1886's experience. Thanks for working this out guys...

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.