contabo / cntb

Contabo Command Line Interface
https://contabo.com
GNU General Public License v3.0
185 stars 27 forks source link

Question about Role-Permissions: How to restrict a user with snapshot permission to one Instance? #31

Open ferenc-hechler opened 1 year ago

ferenc-hechler commented 1 year ago

How to configure roles is not well documented, especially how apiPermissions and resourcePermissions work together.

I want to create a user, who is allowed to create and restore snapshots only for one special instance and not for any other instance.

I have three VPS instances 100123456, 100123457 and 100123458. The "snapshotmanager" user should be allowed to create snapshots for instance 100123456, but not for the other instances.

What I did:

cntb create tag --name "SNAPINST" 
  173123

cntb create tagAssignment 173123 instance 100123456

cntb get tagAssignments 173123 
  TAGID   TAGNAME  RESOURCETYPE  RESOURCEID  RESOURCENAME
  173123  SNAPINST instance      100123456   vmd115123

cntb create role --name "snapshotmgr" --permissions "[{\"apiName\" : \"/v1/compute/instances/:instanceId/snapshots\", \"actions\": [\"CREATE\", \"READ\"], \"resources\": [173123]}]"
  82345

cntb create user --firstName Snapshot --lastName Manager --email snapshot-manager@example.com --enabled --locale en --roles 82345
  9c112233-4455-6677-8899-aabbccddeeff

cntb resendEmailVerification user 9c112233-4455-6677-8899-aabbccddeeff

# click link in email

cntb resetPassword user 9c112233-4455-6677-8899-aabbccddeeff

# click link in email and enter password "abcd-2345"

Now I tried if the user is really restricted to the instance tagged with SNAPINST:

cntb config set-credentials --oauth2-clientid=... --oauth2-client-secret=... --oauth2-user=snapshot-manager@example.com --oauth2-password="abcd-2345"

cntb get instance 100123456
level=error msg="Error while retrieving instance: 403 - Forbidden access to /v1/compute/instances/:instanceId with GET\n"
level=fatal msg="Aborting, due to errors"

That is as expected. The role only grants access to the snapshots api and not to the get instance endpoint.

cntb get snapshots 100123456
  SNAPSHOTID      NAME                     DESCRIPTION  INSTANCEID  CREATEDDATE
  snap1688512345  VPS456 snapshot 1                     100123456   2023-07-05T18:33:29Z
  snap1688512367  VPS456 snapshot 2                     100123456   2023-07-05T16:13:22Z
  snap1688512389  VPS456 snapshot 3                     100123456   2023-07-05T14:52:53Z

That is as expected. Now I try to get the snapshots for another instance (which is not tagged with "SNAPINST"):

cntb get snapshots 100123457
  SNAPSHOTID      NAME                     DESCRIPTION  INSTANCEID  CREATEDDATE
  snap1688555345  VPS457 snapshot 1                     100123457   2023-07-05T18:33:29Z
  snap1688555367  VPS457 snapshot 2                     100123457   2023-07-05T16:13:22Z

That is not, what I wanted. The user should not have access to this instance. I tried it another way, to hard-code the instance id in the path, when defining the role, but that is not accepted:

cntb create role --name "snapshotmgr2" --permissions "[{\"apiName\" : \"/v1/compute/instances/100123456/snapshots\", \"actions\": [\"CREATE\", \"READ\"]}]"
level=error msg="Error creating role: 400 - Bad Request Cannot find action CREATE for apiName /v1/compute/instances/100123456/snapshots. You can find a list of available apiNames and actions at '/api-permissions'\n"
level=fatal msg="Aborting, due to errors"

So, my question is: How do I configure a user to get access to snapshots only for one instance?

ferenc-hechler commented 1 year ago

When I look at the role I created, the resources section is empty. So it is validated when creating the role (the id has to be a TAG id), but afterwards it is somehow dropped. I tried the example request and the resources are not dropped:

cntb create role --name "infrastructure" --permissions "[{\"apiName\" : \"/v1/compute/instances\", \"actions\": [\"CREATE\", \"READ\"], \"resources\": [173123]}]"
  82555

And then I tried to update the user to have both roles, but then I get an error message, that a user can have only 1 Role, which is in contradiction to the statements in the API description:

cntb update user 9c112233-4455-6677-8899-aabbccddeeff --roles "82345,82555"
level=error msg="Error while updating user: 400 - Bad Request only 1 role can be assigned to a user\n"
level=fatal msg="Aborting, due to errors"

So, I think, I am doing something fundamentally wrong...

ferenc-hechler commented 1 year ago

Another try to combine both permissions in one role:

cntb create role --name "combined" --permissions "[{\"apiName\" : \"/v1/compute/instances\", \"actions\": [\"CREATE\", \"READ\"], \"resources\": [173923]},{\"apiName\" : \"/v1/compute/instances/:instanceId/snapshots\", \"actions\": [\"CREATE\", \"READ\"]}]"
  82666

now I see only one instance with cntb get instances, but I still can get the snapshots from the other instances, when I know the id.

Maximilian-Temeschinko commented 1 year ago

Hello, sorry for the late response. We fixed the issue, that snapshots of an instances where not guarded by the Tag on that instance. What you did with creating the Tag, then assigning it to the instance and adding it to a role in the resourcePermissions was correct.

Currently we only allow one role per user, we hope that most of the use cases can be covered by adding specific api endpoints and tags to a role. We where planning on allowing multiple roles per user in the future, so the API as well as the cli tool already expect an array of roles.

ferenc-hechler commented 1 year ago

Hi @Maximilian-Temeschinko,

thanks for the fix. I tested it and it does not works for all commands I use.

Here is the user config:

$ cntb get user 9c112233-4455-6677-8899-aabbccddeeff -oyaml

- customerId: "34567"
  email: snapshot-manager@example.com
  emailVerified: true
  enabled: true
  firstName: Snapshot
  lastName: Manager
  locale: en
  owner: false
  roles:
  - accessAllResources: false
    admin: false
    customerId: "34567"
    name: snapshotmgr
    permissions:
    - actions:
      - CREATE
      - READ
      apiName: /v1/compute/instances/:instanceId/snapshots
      resources:
      - tagId: 173123
        tagName: SNAPINST
    - actions:
      - CREATE
      apiName: /v1/compute/instances/:instanceId/snapshots/:snapshotId/rollback
      resources:
      - tagId: 173123
        tagName: SNAPINST
    - actions:
      - CREATE
      apiName: /v1/compute/instances/:instanceId/actions/restart
      resources:
      - tagId: 173123
        tagName: SNAPINST
    - actions:
      - DELETE
      apiName: /v1/compute/instances/:instanceId/snapshots/:snapshotId
      resources:
      - tagId: 173123
        tagName: SNAPINST
    roleId: 82345
    tenantId: DE
    type: custom
  tenantId: DE
  totp: false
  userId: 9c112233-4455-6677-8899-aabbccddeeff

Logging in with this user:

$ cntb config set-credentials --oauth2-clientid=... --oauth2-client-secret=... --oauth2-user=snapshot-manager@example.com --oauth2-password="abcd-2345"

Getting snapshots for an instance, which is not tagged with SNAPINST:

$ cntb get snapshots 100123456
level=error msg="Error while retrieving snapshots: 403 - Forbidden access to instance with instanceId: 100123456\n"
level=fatal msg="Aborting, due to errors"

That is better than before.

But rolling back the same instance to an old snapshot is not forbidden:

$ cntb rollback snapshot "100123456" "snap1678901234"
Instance 100123456 rollback to snapshotId snap1678901234

Also creating a new snapshot for the instance is possible:

$ cntb create snapshot "100123456" --name "neuersnapshot"
snap1689012345

But deleting the newly created snapshot is forbidden:

$ cntb delete snapshot "100123456" "snap1689012345"
level=error msg="Error while deleting snapshot: 403 - Forbidden access to instance with instanceId: 100123456\n"
level=fatal msg="Aborting, due to errors"

Another function, which I use is to restart the instance (not snapshot related) is also possible for all instances:

$ cntb restart instance "100123456"
  INSTANCEID  ACTION
  100123456   restart

So, it is getting better, but still something to do ;-)

ngotzmann commented 1 year ago

Hello, sorry for the late response again... All the issues should be fixed, until you find more :smile:
And thanks for finding and reporting the bugs!

ferenc-hechler commented 1 year ago

Hi @ngotzmann ,

we are getting closer... :-)

All snapshot related commands are now restricted as expected. But restarting an instance which is not tagged correctly is still possible.

$ cntb restart instance "100123456"
  INSTANCEID  ACTION
  100123456   restart
andreiduca03 commented 8 months ago

Hi, the issue is fixed now in the new version: v1.4.9